214 lines
11 KiB
Lua
214 lines
11 KiB
Lua
|
---------------------------------------------------------------------------
|
||
|
-- Display Sound Channels data
|
||
|
-- by AnS, 2012
|
||
|
---------------------------------------------------------------------------
|
||
|
-- Showcases following functions:
|
||
|
-- * sound.get()
|
||
|
---------------------------------------------------------------------------
|
||
|
-- Usage:
|
||
|
-- The script allows you to observe data of 5 sound channels.
|
||
|
-- Analysing such info you can notice some regularities in how
|
||
|
-- the data oscillates/changes when ingame music plays.
|
||
|
-- Then you can write scripts similar to \taseditor\TrackNoise.lua
|
||
|
-- to facilitate synchronous dances in TAS movies.
|
||
|
---------------------------------------------------------------------------
|
||
|
|
||
|
square1 = {x=1, y=8, on=true};
|
||
|
square2 = {x=129, y=8, on=true};
|
||
|
triangle = {x=1, y=67, on=true};
|
||
|
noise = {x=129, y=67, on=true};
|
||
|
dpcm = {x=1, y=118, on=true};
|
||
|
|
||
|
semitones = {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"};
|
||
|
duty_ratio = {"12.5%", "25%", "50%", "75%"};
|
||
|
duty_color = {"purple", "magenta", "orange", "yellow"};
|
||
|
key_color = {"#000000FF", "#202020FF", "#205050FF", "#008080FF", "#00C0C0FF", "#00FFFFFF", "#FFFFFFFF", "#FFFF00FF", "#FFFFFFFF", "#FFFF00FF", "#FFFFFFFF", "#FFFF00FF", "#FFFFFFFF", "#FFFF00FF", "#FFFFFFFF"};
|
||
|
noise_color = {long="orange", short = "yellow"};
|
||
|
|
||
|
sample_names = {
|
||
|
-- Here you can specify custom names for DMC samples (to display name instead of just address)
|
||
|
-- For example, here are two samples for Contra(U) ROM
|
||
|
Sample_FC00 = {name="Kick", color="#C0C0C0FF"},
|
||
|
Sample_FCC0 = {name="Snare", color="#80C0FFFF"},
|
||
|
}
|
||
|
|
||
|
function everyframe()
|
||
|
snd = sound.get();
|
||
|
|
||
|
if (square1.on) then
|
||
|
gui.text(square1.x, square1.y, "SQUARE 1:");
|
||
|
|
||
|
Volume = snd.rp2a03.square1.volume;
|
||
|
gui.text(square1.x, square1.y + 8, "Volume:");
|
||
|
gui.box(square1.x + 32, square1.y + 7, square1.x + 32+15, square1.y + 15, "#006000FF", "black");
|
||
|
gui.box(square1.x + 32, square1.y + 7, square1.x + 32 + Volume * 15, square1.y + 15, "green", "clear");
|
||
|
gui.text(square1.x + 48, square1.y + 8, string.format("%g", Volume));
|
||
|
|
||
|
Frequency = snd.rp2a03.square1.frequency;
|
||
|
gui.text(square1.x, square1.y + 16, "Frequency: " .. string.format("%g", Frequency) .. "Hz");
|
||
|
|
||
|
Midikey = snd.rp2a03.square1.midikey;
|
||
|
gui.box(square1.x-1, square1.y + 23, square1.x + 127, square1.y + 31, "#008080FF", "black")
|
||
|
gui.box(square1.x-1, square1.y + 23, square1.x-1 + Midikey, square1.y + 31, "#00C0C0FF", "black")
|
||
|
Keycolor = key_color[math.floor(Volume * 15) + 1];
|
||
|
gui.box(square1.x-1 + Midikey-1, square1.y + 23, square1.x-1 + Midikey+1, square1.y + 31, "white", Keycolor)
|
||
|
Note = math.floor((Midikey - 21) % 12);
|
||
|
Octave = math.floor((Midikey - 12) / 12);
|
||
|
Semitone = tostring(semitones[Note + 1]) .. Octave;
|
||
|
gui.text(square1.x, square1.y + 32, "Note: " .. Semitone .. " ");
|
||
|
gui.text(square1.x + 50, square1.y + 32, "(" .. string.format("%g", Midikey) .. ")");
|
||
|
|
||
|
Period = snd.rp2a03.square1.regs.frequency;
|
||
|
IndicatorColor = "#" .. string.format("%x", Period % 256) .. "0000FF";
|
||
|
gui.text(square1.x, square1.y + 40, "Period:");
|
||
|
gui.box(square1.x + 31, square1.y + 39, square1.x + 39, square1.y + 47, IndicatorColor, "black");
|
||
|
gui.text(square1.x + 40, square1.y + 40, string.format("%g", Period));
|
||
|
|
||
|
Duty = snd.rp2a03.square1.duty;
|
||
|
gui.text(square1.x, square1.y + 48, "Duty #" .. Duty .. " (" .. duty_ratio[Duty + 1] .. ")", duty_color[Duty + 1]);
|
||
|
end
|
||
|
|
||
|
if (square2.on) then
|
||
|
gui.text(square2.x, square2.y, "SQUARE 2:");
|
||
|
|
||
|
Volume = snd.rp2a03.square2.volume;
|
||
|
gui.text(square2.x, square2.y + 8, "Volume:");
|
||
|
gui.box(square2.x + 32, square2.y + 7, square2.x + 32+15, square2.y + 15, "#006000FF", "black");
|
||
|
gui.box(square2.x + 32, square2.y + 7, square2.x + 32 + Volume * 15, square2.y + 15, "green", "clear");
|
||
|
gui.text(square2.x + 48, square2.y + 8, string.format("%g", Volume));
|
||
|
|
||
|
Frequency = snd.rp2a03.square2.frequency;
|
||
|
gui.text(square2.x, square2.y + 16, "Frequency: " .. string.format("%g", Frequency) .. "Hz");
|
||
|
|
||
|
Midikey = snd.rp2a03.square2.midikey;
|
||
|
gui.box(square2.x-1, square2.y + 23, square2.x + 127, square2.y + 31, "#008080FF", "black")
|
||
|
gui.box(square2.x-1, square2.y + 23, square2.x-1 + Midikey, square2.y + 31, "#00C0C0FF", "black")
|
||
|
Keycolor = key_color[math.floor(Volume * 15) + 1];
|
||
|
gui.box(square2.x-1 + Midikey-1, square2.y + 23, square2.x-1 + Midikey+1, square2.y + 31, "white", Keycolor)
|
||
|
Note = math.floor((Midikey - 21) % 12);
|
||
|
Octave = math.floor((Midikey - 12) / 12);
|
||
|
Semitone = tostring(semitones[Note + 1]) .. Octave;
|
||
|
gui.text(square2.x, square2.y + 32, "Note: " .. Semitone .. " ");
|
||
|
gui.text(square2.x + 50, square2.y + 32, "(" .. string.format("%g", Midikey) .. ")");
|
||
|
|
||
|
Period = snd.rp2a03.square2.regs.frequency;
|
||
|
IndicatorColor = "#" .. string.format("%x", Period % 256) .. "0000FF";
|
||
|
gui.text(square2.x, square2.y + 40, "Period:");
|
||
|
gui.box(square2.x + 31, square2.y + 39, square2.x + 39, square2.y + 47, IndicatorColor, "black");
|
||
|
gui.text(square2.x + 40, square2.y + 40, string.format("%g", Period));
|
||
|
|
||
|
Duty = snd.rp2a03.square2.duty;
|
||
|
gui.text(square2.x, square2.y + 48, "Duty #" .. Duty .. " (" .. duty_ratio[Duty + 1] .. ")", duty_color[Duty + 1]);
|
||
|
end
|
||
|
|
||
|
if (triangle.on) then
|
||
|
gui.text(triangle.x, triangle.y, "TRIANGLE:");
|
||
|
|
||
|
Volume = snd.rp2a03.triangle.volume;
|
||
|
gui.text(triangle.x, triangle.y + 8, "Volume:");
|
||
|
gui.box(triangle.x + 32, triangle.y + 7, triangle.x + 32+15, triangle.y + 15, "#006000FF", "black");
|
||
|
gui.box(triangle.x + 32, triangle.y + 7, triangle.x + 32 + Volume * 15, triangle.y + 15, "#00A000FF", "clear");
|
||
|
gui.text(triangle.x + 48, triangle.y + 8, string.format("%g", Volume));
|
||
|
|
||
|
Frequency = snd.rp2a03.triangle.frequency;
|
||
|
gui.text(triangle.x, triangle.y + 16, "Frequency: " .. string.format("%g", Frequency) .. "Hz");
|
||
|
|
||
|
Midikey = snd.rp2a03.triangle.midikey;
|
||
|
gui.box(triangle.x-1, triangle.y + 23, triangle.x + 127, triangle.y + 31, "#008080FF", "black")
|
||
|
gui.box(triangle.x-1, triangle.y + 23, triangle.x-1 + Midikey, triangle.y + 31, "#00C0C0FF", "black")
|
||
|
if (Volume ~= 0) then gui.box(triangle.x-1 + Midikey-1, triangle.y + 23, triangle.x-1 + Midikey+1, triangle.y + 31, "white", "black") end;
|
||
|
Note = math.floor((Midikey - 21) % 12);
|
||
|
Octave = math.floor((Midikey - 12) / 12);
|
||
|
Semitone = tostring(semitones[Note + 1]) .. Octave;
|
||
|
gui.text(triangle.x, triangle.y + 32, "Note: " .. Semitone .. " ");
|
||
|
gui.text(triangle.x + 50, triangle.y + 32, "(" .. string.format("%g", Midikey) .. ")");
|
||
|
|
||
|
Period = snd.rp2a03.triangle.regs.frequency;
|
||
|
IndicatorColor = "#" .. string.format("%x", Period % 256) .. "0000FF";
|
||
|
gui.text(triangle.x, triangle.y + 40, "Period:");
|
||
|
gui.box(triangle.x + 31, triangle.y + 39, triangle.x + 39, triangle.y + 47, IndicatorColor, "black");
|
||
|
gui.text(triangle.x + 40, triangle.y + 40, string.format("%g", Period));
|
||
|
end
|
||
|
|
||
|
if (noise.on) then
|
||
|
gui.text(noise.x, noise.y, "NOISE:");
|
||
|
|
||
|
Volume = snd.rp2a03.noise.volume;
|
||
|
gui.text(noise.x, noise.y + 8, "Volume:");
|
||
|
gui.box(noise.x + 32, noise.y + 7, noise.x + 32+15, noise.y + 15, "#006000FF", "black");
|
||
|
gui.box(noise.x + 32, noise.y + 7, noise.x + 32 + Volume * 15, noise.y + 15, "green", "clear");
|
||
|
gui.text(noise.x + 48, noise.y + 8, string.format("%g", Volume));
|
||
|
|
||
|
Frequency = snd.rp2a03.noise.frequency;
|
||
|
gui.text(noise.x, noise.y + 16, "Frequency: " .. string.format("%g", Frequency) .. "Hz");
|
||
|
|
||
|
Midikey = snd.rp2a03.noise.midikey;
|
||
|
gui.box(noise.x-1, noise.y + 23, noise.x + 127, noise.y + 31, "#008080FF", "black")
|
||
|
gui.box(noise.x-1, noise.y + 23, noise.x-1 + (Midikey/2), noise.y + 31, "#00C0C0FF", "black")
|
||
|
Keycolor = key_color[math.floor(Volume * 15) + 1];
|
||
|
gui.box(noise.x-1 + (Midikey/2)-1, noise.y + 23, noise.x-1 + (Midikey/2)+1, noise.y + 31, "white", Keycolor)
|
||
|
Note = math.floor((Midikey - 21) % 12);
|
||
|
Octave = math.floor((Midikey - 12) / 12);
|
||
|
Semitone = tostring(semitones[Note + 1]) .. Octave;
|
||
|
gui.text(noise.x, noise.y + 32, "Note: " .. Semitone .. " ");
|
||
|
gui.text(noise.x + 58, noise.y + 32, "(" .. string.format("%g", Midikey) .. ")");
|
||
|
|
||
|
Period = snd.rp2a03.noise.regs.frequency;
|
||
|
IndicatorColor = "#" .. string.format("%X", Period % 256) .. "0000FF";
|
||
|
gui.text(noise.x, noise.y + 40, "Period:");
|
||
|
gui.box(noise.x + 31, noise.y + 39, noise.x + 39, noise.y + 47, IndicatorColor, "black");
|
||
|
gui.text(noise.x + 40, noise.y + 40, string.format("%g", Period));
|
||
|
|
||
|
if (snd.rp2a03.noise.short) then
|
||
|
gui.text(noise.x, noise.y + 48, "Mode: short", noise_color.short);
|
||
|
else
|
||
|
gui.text(noise.x, noise.y + 48, "Mode: long", noise_color.long);
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if (dpcm.on) then
|
||
|
gui.text(dpcm.x, dpcm.y, "DPCM:");
|
||
|
|
||
|
Volume = snd.rp2a03.dpcm.volume;
|
||
|
gui.text(dpcm.x, dpcm.y + 8, "Volume:");
|
||
|
gui.box(dpcm.x + 32, dpcm.y + 7, dpcm.x + 32+15, dpcm.y + 15, "#006000FF", "black");
|
||
|
gui.box(dpcm.x + 32, dpcm.y + 7, dpcm.x + 32 + Volume * 15, dpcm.y + 15, "#00A000FF", "clear");
|
||
|
gui.text(dpcm.x + 48, dpcm.y + 8, string.format("%g", Volume));
|
||
|
|
||
|
Frequency = snd.rp2a03.dpcm.frequency;
|
||
|
gui.text(dpcm.x, dpcm.y + 16, "Frequency: " .. string.format("%g", Frequency) .. "Hz");
|
||
|
|
||
|
Midikey = snd.rp2a03.dpcm.midikey;
|
||
|
gui.box(dpcm.x-1, dpcm.y + 23, dpcm.x + 127, dpcm.y + 31, "#008080FF", "black")
|
||
|
gui.box(dpcm.x-1, dpcm.y + 23, dpcm.x-1 + (Midikey/2), dpcm.y + 31, "#00C0C0FF", "black")
|
||
|
if (Volume ~= 0) then gui.box(dpcm.x-1 + (Midikey/2)-1, dpcm.y + 23, dpcm.x-1 + (Midikey/2)+1, dpcm.y + 31, "white", "black") end;
|
||
|
Note = math.floor((Midikey - 21) % 12);
|
||
|
Octave = math.floor((Midikey - 12) / 12);
|
||
|
Semitone = tostring(semitones[Note + 1]) .. Octave;
|
||
|
gui.text(dpcm.x, dpcm.y + 32, "Note: " .. Semitone .. " ");
|
||
|
gui.text(dpcm.x + 50, dpcm.y + 32, "(" .. string.format("%g", Midikey) .. ")");
|
||
|
|
||
|
Period = snd.rp2a03.dpcm.regs.frequency;
|
||
|
IndicatorColor = "#" .. string.format("%x", Period % 256) .. "0000FF";
|
||
|
gui.text(dpcm.x, dpcm.y + 40, "Period:");
|
||
|
gui.box(dpcm.x + 31, dpcm.y + 39, dpcm.x + 39, dpcm.y + 47, IndicatorColor, "black");
|
||
|
gui.text(dpcm.x + 40, dpcm.y + 40, string.format("%g", Period));
|
||
|
|
||
|
if (snd.rp2a03.dpcm.dmcloop) then
|
||
|
gui.text(dpcm.x, dpcm.y + 48, "Sample: $" .. string.format("%X", snd.rp2a03.dpcm.dmcaddress) .. " (" .. snd.rp2a03.dpcm.dmcsize .. " bytes looped)", "orange");
|
||
|
else
|
||
|
gui.text(dpcm.x, dpcm.y + 48, "Sample: $" .. string.format("%X", snd.rp2a03.dpcm.dmcaddress) .. " (" .. snd.rp2a03.dpcm.dmcsize .. " bytes)");
|
||
|
end
|
||
|
|
||
|
Sample_id = "Sample_" .. string.format("%X", snd.rp2a03.dpcm.dmcaddress);
|
||
|
if (sample_names[Sample_id] ~= nil) then
|
||
|
gui.text(dpcm.x + 170, dpcm.y + 48, sample_names[Sample_id].name, sample_names[Sample_id].color);
|
||
|
end
|
||
|
|
||
|
gui.text(dpcm.x, dpcm.y + 56, "DMC seed: " .. string.format("%X", snd.rp2a03.dpcm.dmcseed));
|
||
|
end
|
||
|
end
|
||
|
|
||
|
emu.registerafter(everyframe);
|
||
|
|