fceux/output/luaScripts/scrolling-pitch-display.lua

207 lines
5.6 KiB
Lua

-- Scrolling Pitch Display for FCEUX
-- 2014-07-19
-- Robert Hart (rnhart.net)
SCREEN_LEFT = 0
SCREEN_RIGHT = 255
MIDI_LEFT = 18
MIDI_RIGHT = 102
MIDI_RANGE = (MIDI_RIGHT + 1) - MIDI_LEFT
SCREEN_RANGE = (SCREEN_RIGHT + 1) - SCREEN_LEFT
BACKGROUND_COLOR = {0,0,0,70}
SCROLL_BOTTOM = 225
SCROLL_SIZE = 216
KEYBOARD_SIZE = 5
KEYBOARD_TOP = SCROLL_BOTTOM
KEYBOARD_BOTTOM = SCROLL_BOTTOM + KEYBOARD_SIZE
KEYBOARD_FILLS = ({[0]="white","black","white","black","white","white","black","white","black","white","black","white"})
-- FCEUX 2.2.2 pitch fixes
SHORT_FIX_DOWN = 12 * ( math.log(93/2) / math.log(2) )
DPCM_FIX_DOWN = 12 * ( math.log(11) / math.log(2) )
function round(x)
return math.floor( x + .5 )
end
function Scale(x)
temp = math.floor ( (x - MIDI_LEFT) * SCREEN_RANGE / MIDI_RANGE + .5 )
if (temp < SCREEN_LEFT) then temp = SCREEN_LEFT
elseif (temp > SCREEN_RIGHT) then temp = SCREEN_RIGHT
end
return temp
end
WIDTH = {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2}
COLOR = {[0]="P39", [1]="P15", [2]="P2C", [3]="P15", ["triangle"]="P12", ["noise-short"]="P30", ["noise-long"]="P10", ["dpcm"]="P1A", ["dpcm-melodic"]="P2A" }
function Reset()
history = {}
previous_frame = emu.framecount() - 1
-- Set up DPCM visualization function
hash = rom.gethash("md5")
if (hash == "d4782e6bbf337f075174345fe4848983") then -- My demo
DELTAS_PERIOD = 64
DPCM_KEY_DOWN = 12 * (math.log(DELTAS_PERIOD)/math.log(2))
DPCM_KEY_DOWN = DPCM_KEY_DOWN + DPCM_FIX_DOWN
DPCM_Function = function()
if(snd.dpcm.volume > 0) then
if (snd.dpcm.dmcaddress == 0xC000) then
dpcm_key = Scale(snd.dpcm.midikey - DPCM_KEY_DOWN)
dpcm_color = COLOR["dpcm-melodic"]
dpcm_width = WIDTH[8]
else
dpcm_key = Scale(MIDI_LEFT + 1 + snd.dpcm.regs.frequency)
dpcm_color = COLOR["dpcm"]
dpcm_width = WIDTH[8]
end
return {dpcm_key, dpcm_color, dpcm_width}
else
return nil
end
end
elseif (hash == "e02c7c510e0e37b1f2711103fff9e58a") then -- Ikinari Musician
DELTAS_PERIOD = 64
DPCM_KEY_DOWN = 12 * (math.log(DELTAS_PERIOD)/math.log(2))
DPCM_KEY_DOWN = DPCM_KEY_DOWN + DPCM_FIX_DOWN
DPCM_Function = function()
if(snd.dpcm.volume > 0) then
if (snd.dpcm.dmcaddress == 0xFF00) then
dpcm_key = Scale(MIDI_LEFT + 1 + snd.dpcm.regs.frequency)
dpcm_color = COLOR["dpcm"]
dpcm_width = WIDTH[round((snd.dpcm.dmcseed/127)*14)+1]
elseif (snd.dpcm.dmcaddress == 0xFF80) then
dpcm_key = Scale(snd.dpcm.midikey - DPCM_KEY_DOWN)
dpcm_color = COLOR["dpcm-melodic"]
dpcm_width = WIDTH[8]
end
return {dpcm_key, dpcm_color, dpcm_width}
else
return nil
end
end
else -- Default DPCM
previous_seed = sound.get().rp2a03.dpcm.dmcseed
DPCM_Function = function()
if(snd.dpcm.volume > 0) then
previous_seed = snd.dpcm.dmcseed
return {Scale(MIDI_LEFT + 1 + snd.dpcm.regs.frequency), COLOR["dpcm"], WIDTH[8]}
elseif ( snd.dpcm.dmcseed ~= previous_seed) then
seed_change = math.abs(previous_seed - snd.dpcm.dmcseed)
previous_seed = snd.dpcm.dmcseed
return {Scale(MIDI_LEFT + 17), COLOR["dpcm"], (math.floor(((seed_change-1)/127)*3))}
else
return nil
end
end
end
end
function Draw()
if(emu.framecount() - previous_frame ~= 1) then Reset() end
previous_frame = emu.framecount()
gui.box(0,0,255,239,BACKGROUND_COLOR)
snd = sound.get().rp2a03
if(snd.square1.volume > 0) then
c1 = {Scale(snd.square1.midikey),COLOR[snd.square1.duty], WIDTH[math.floor(15*snd.square1.volume)]}
else
c1 = nil
end
if(snd.square2.volume > 0) then
c2 = {Scale(snd.square2.midikey),COLOR[snd.square2.duty], WIDTH[math.floor(15*snd.square2.volume)]}
else
c2 = nil
end
if((snd.triangle.volume > 0) and (snd.triangle.regs.frequency > 1)) then
c3 = {Scale(snd.triangle.midikey),COLOR["triangle"], WIDTH[8]}
else
c3 = nil
end
if(snd.noise.volume > 0) then
if(snd.noise.short) then
noise_key = Scale(snd.noise.midikey - SHORT_FIX_DOWN)
noise_color = COLOR["noise-short"]
else
noise_key = Scale(MIDI_LEFT + 16 - snd.noise.regs.frequency)
noise_color = COLOR["noise-long"]
end
c4 = {noise_key, noise_color, WIDTH[math.floor(15*snd.noise.volume)]}
else
c4 = nil
end
c5 = DPCM_Function()
table.insert(history, 1, {c1,c2,c3,c4,c5})
table.remove(history, SCROLL_SIZE)
-- draw keyboard
for i = MIDI_LEFT,MIDI_RIGHT do
fill = KEYBOARD_FILLS[i%12]
left = Scale(i - .5)
right = Scale(i + .5)
gui.box(left,KEYBOARD_TOP,right,KEYBOARD_BOTTOM,fill,"gray")
end
-- draw notes
for i = 1, #history do
for j = 1, 5 do
if(type(history[i][j]) ~= "nil") then
x = history[i][j][1]
y = SCROLL_BOTTOM - i
c = history[i][j][2]
w = history[i][j][3]
gui.box(x-w-1,y-1,x+w+1,y,"black")
gui.line(x-w,y,x+w,y,c)
end
end
end
end
Reset()
emu.registerafter(Draw)
emu.print( " blue = triangle gray = noise, long*")
emu.print( " cyan = pulse, 1/2 white = noise, short")
emu.print( " red = pulse, 1/4 dk gn = dpcm, non-periodic*")
emu.print( " yellow = pulse, 1/8 green = dpcm, periodic")
emu.print( "")
emu.print( "* percussive frequencies shown as 16 lowest pitches")