94 lines
3.0 KiB
Lua
94 lines
3.0 KiB
Lua
local createLibTest = require('/apis/libtest');
|
|
local createAudio = require('/apis/libaudio');
|
|
|
|
local testlib = createLibTest({ ... });
|
|
|
|
local function constant(value, n)
|
|
local buf = {};
|
|
for i = 1, n do buf[i] = value; end
|
|
return buf;
|
|
end
|
|
|
|
local function impulse(value, n)
|
|
local buf = constant(0, n);
|
|
buf[1] = value;
|
|
return buf;
|
|
end
|
|
|
|
local function allInRange(buf)
|
|
for i = 1, #buf do
|
|
if buf[i] < -128 or buf[i] > 127 or buf[i] ~= math.floor(buf[i]) then
|
|
return false;
|
|
end
|
|
end
|
|
return true;
|
|
end
|
|
|
|
testlib.test('low-pass passes DC and stays in range, rising toward the input', function()
|
|
local audio = createAudio();
|
|
local lp = audio.lowPass();
|
|
local out = lp.process(constant(127, 2000));
|
|
testlib.assertTrue(allInRange(out), 'samples must be valid 8-bit integers');
|
|
testlib.assertTrue(out[#out] > out[1], 'output should rise toward the DC level');
|
|
testlib.assertTrue(out[#out] <= 127, 'output must not exceed the DC level');
|
|
end);
|
|
|
|
testlib.test('high-pass blocks DC: a constant decays toward zero', function()
|
|
local audio = createAudio();
|
|
local hp = audio.highPass();
|
|
local out = hp.process(constant(100, 200));
|
|
testlib.assertTrue(allInRange(out), 'samples must be valid 8-bit integers');
|
|
testlib.assertTrue(math.abs(out[#out]) < math.abs(out[1]), 'DC component should decay');
|
|
testlib.assertTrue(math.abs(out[#out]) <= 1, 'DC should fall close to zero');
|
|
end);
|
|
|
|
testlib.test('set changes the response and reset clears state', function()
|
|
local audio = createAudio();
|
|
local lp = audio.lowPass();
|
|
|
|
lp.set(200);
|
|
local low = lp.process(constant(127, 1))[1];
|
|
lp.reset();
|
|
lp.set(5000);
|
|
local high = lp.process(constant(127, 1))[1];
|
|
testlib.assertTrue(low ~= high, 'different cutoffs should give a different first sample');
|
|
|
|
-- reset must make a repeated run identical
|
|
lp.reset();
|
|
local a = lp.process(constant(50, 16));
|
|
lp.reset();
|
|
local b = lp.process(constant(50, 16));
|
|
testlib.assertEquals(a[#a], b[#b]);
|
|
end);
|
|
|
|
testlib.test('set clamps the param to the spec range', function()
|
|
local audio = createAudio();
|
|
local rv = audio.reverb();
|
|
rv.set(10);
|
|
testlib.assertEquals(rv.get(), 0.9);
|
|
rv.set(-5);
|
|
testlib.assertEquals(rv.get(), 0);
|
|
end);
|
|
|
|
testlib.test('delay re-emits the dry signal after the ring length', function()
|
|
local audio = createAudio({ sampleRate = 8 });
|
|
local d = audio.delay(1000); -- 1000ms * 8/s = 8-sample ring
|
|
local out = d.process(impulse(100, 10));
|
|
|
|
testlib.assertTrue(allInRange(out), 'samples must be valid 8-bit integers');
|
|
testlib.assertEquals(out[1], 60); -- 100 * 0.6 dry
|
|
testlib.assertEquals(out[9], 40); -- 100 * 0.4 delayed by 8 samples
|
|
testlib.assertEquals(out[5], 0); -- nothing in between
|
|
end);
|
|
|
|
testlib.test('reverb stays bounded for a loud impulse', function()
|
|
local audio = createAudio();
|
|
local rv = audio.reverb(0.8);
|
|
local buf = constant(0, 4000);
|
|
for i = 1, 200 do buf[i] = 127; end
|
|
local out = rv.process(buf);
|
|
testlib.assertTrue(allInRange(out), 'reverb output must never clip past 8-bit range');
|
|
end);
|
|
|
|
testlib.run();
|