mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
115 lines
3.4 KiB
Lua
115 lines
3.4 KiB
Lua
-- ../pokecrystal/audio/engine.asm:1987
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
local check, eq = T.check, T.eq
|
|
|
|
love = require("tests.love_stub")
|
|
|
|
local bit = require("bit")
|
|
local ChipAsm = require("src.audio.ChipAsm")
|
|
local ChipSynth = require("src.core.ChipSynth")
|
|
|
|
local SAMPLES = 4096
|
|
|
|
local song = ChipAsm.song{
|
|
channels = {
|
|
{ hw = 1, program = {
|
|
{ notetype = { speed = 8, volume = 12, fade = 2 } },
|
|
{ octave = 4 },
|
|
{ note = "C", len = 6 },
|
|
{ note = "E", len = 6 },
|
|
{ loop = { count = 0, to = 1 } },
|
|
} },
|
|
{ hw = 2, program = {
|
|
{ notetype = { speed = 6, volume = 10, fade = 1 } },
|
|
{ octave = 3 },
|
|
{ note = "G", len = 4 },
|
|
{ note = "A", len = 8 },
|
|
{ loop = { count = 0, to = 1 } },
|
|
} },
|
|
},
|
|
}
|
|
song.generation = 2
|
|
|
|
local data = { audio = { generation = 2 } }
|
|
|
|
local function render(fastPath)
|
|
ChipSynth._setMonoFastPathForTest(fastPath)
|
|
local engine = ChipSynth.newEngine(data, song, { allowLoops = true })
|
|
local frames = {}
|
|
for index = 1, SAMPLES do
|
|
local left, right = engine:sampleStereo()
|
|
frames[index] = { left, right }
|
|
end
|
|
return frames, engine
|
|
end
|
|
|
|
ChipSynth.setStereo(false)
|
|
|
|
local general = render(false)
|
|
local fast, fastEngine = render(true)
|
|
|
|
check(fastEngine.monoMix,
|
|
"a Gen 2 engine built with SOUND off takes the mono fast path")
|
|
|
|
local mismatches, sounding = 0, 0
|
|
for index = 1, SAMPLES do
|
|
if fast[index][1] ~= general[index][1]
|
|
or fast[index][2] ~= general[index][2] then
|
|
mismatches = mismatches + 1
|
|
end
|
|
if general[index][1] ~= 0 then sounding = sounding + 1 end
|
|
end
|
|
eq(mismatches, 0, "the mono fast path is bit-identical to the general path")
|
|
check(sounding > SAMPLES / 2,
|
|
"and the comparison ran against a song that is actually sounding")
|
|
|
|
local split = 0
|
|
for index = 1, SAMPLES do
|
|
if fast[index][1] ~= fast[index][2] then split = split + 1 end
|
|
end
|
|
eq(split, 0, "every mono frame carries the same value in both speakers")
|
|
|
|
eq(fastEngine.hpfCapRight, fastEngine.hpfCapLeft,
|
|
"the fast path keeps the right-hand HPF state in step")
|
|
eq(fastEngine.lpfRight, fastEngine.lpfLeft,
|
|
"and the right-hand LPF state too")
|
|
|
|
ChipSynth._setMonoFastPathForTest(true)
|
|
local forced = ChipSynth.newEngine(data, song, { allowLoops = true })
|
|
check(forced.monoMix, "the engine starts on the fast path")
|
|
local channel = forced.channels[2]
|
|
local mask = bit.lshift(1, channel.hardware - 1)
|
|
channel.tracks = bit.lshift(mask, 4)
|
|
channel.forcePanning = true
|
|
forced:refreshMonoMix()
|
|
check(not forced.monoMix,
|
|
"a force_stereo_panning channel drops the engine off the fast path")
|
|
local function spread(engine, count)
|
|
local left, right = 0, 0
|
|
for _ = 1, count do
|
|
local l, r = engine:sampleStereo()
|
|
left, right = left + math.abs(l), right + math.abs(r)
|
|
end
|
|
return left, right
|
|
end
|
|
|
|
local forcedLeft, forcedRight = spread(forced, SAMPLES)
|
|
check(forcedLeft ~= forcedRight,
|
|
"and the general path pans that channel to one speaker")
|
|
|
|
ChipSynth.setStereo(true)
|
|
local stereo = ChipSynth.newEngine(data, song, { allowLoops = true })
|
|
check(not stereo.monoMix, "STEREO never takes the mono fast path")
|
|
stereo.channels[2].tracks = bit.lshift(1, stereo.channels[2].hardware - 1)
|
|
local stereoLeft, stereoRight = spread(stereo, SAMPLES)
|
|
check(stereoLeft ~= stereoRight,
|
|
"a right-only track mixes differently into each speaker")
|
|
|
|
ChipSynth.setStereo(false)
|
|
ChipSynth._setMonoFastPathForTest(true)
|
|
|
|
T.finish("chip mono fast path")
|