forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
95
lib/aura/Tests/auratests/channels/TestBaseChannelHandle.hx
Normal file
95
lib/aura/Tests/auratests/channels/TestBaseChannelHandle.hx
Normal file
@ -0,0 +1,95 @@
|
||||
package auratests.channels;
|
||||
|
||||
import utest.Assert;
|
||||
|
||||
import aura.Aura;
|
||||
import aura.channels.MixChannel;
|
||||
import aura.channels.UncompBufferResamplingChannel;
|
||||
|
||||
class TestBaseChannelHandle extends utest.Test {
|
||||
var handle: BaseChannelHandle;
|
||||
var channel: UncompBufferResamplingChannel;
|
||||
var data = new kha.arrays.Float32Array(8);
|
||||
|
||||
function setup() {
|
||||
channel = new UncompBufferResamplingChannel(data, false, 44100);
|
||||
handle = new BaseChannelHandle(channel);
|
||||
}
|
||||
|
||||
function teardown() {}
|
||||
|
||||
function test_setMixChannelAddsInputIfNotYetExisting() {
|
||||
final handle1 = new MixChannelHandle(new MixChannel());
|
||||
final handle2 = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.equals(1, handle2.getNumInputs());
|
||||
}
|
||||
|
||||
function test_setMixChannelDoesntAddAlreadyExistingInput() {
|
||||
final handle1 = new MixChannelHandle(new MixChannel());
|
||||
final handle2 = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.equals(1, handle2.getNumInputs());
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.equals(1, handle2.getNumInputs());
|
||||
}
|
||||
|
||||
function test_setMixChannelNullRemovesInputIfExisting() {
|
||||
final handle1 = new MixChannelHandle(new MixChannel());
|
||||
final handle2 = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
Assert.isTrue(handle1.setMixChannel(null));
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.equals(1, handle2.getNumInputs());
|
||||
|
||||
Assert.isTrue(handle1.setMixChannel(null));
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
}
|
||||
|
||||
function test_setMixChannelSwitchingMixChannelCorrectlyChangesInputs() {
|
||||
final handle1 = new MixChannelHandle(new MixChannel());
|
||||
final handle2 = new MixChannelHandle(new MixChannel());
|
||||
final handle3 = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
Assert.equals(0, handle3.getNumInputs());
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.equals(1, handle2.getNumInputs());
|
||||
Assert.equals(0, handle3.getNumInputs());
|
||||
|
||||
Assert.isTrue(handle1.setMixChannel(handle3));
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
Assert.equals(1, handle3.getNumInputs());
|
||||
}
|
||||
|
||||
function test_setMixChannelSelfReferenceReturnsFalseAndRemovesInput() {
|
||||
final handle1 = new MixChannelHandle(new MixChannel());
|
||||
final handle2 = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.equals(1, handle2.getNumInputs());
|
||||
|
||||
Assert.isFalse(handle1.setMixChannel(handle1));
|
||||
Assert.equals(0, handle2.getNumInputs());
|
||||
}
|
||||
|
||||
function test_setMixChannelCircularDependencyReturnsFalseAndRemovesInput() {
|
||||
final handle1 = new MixChannelHandle(new MixChannel());
|
||||
final handle2 = new MixChannelHandle(new MixChannel());
|
||||
final handle3 = new MixChannelHandle(new MixChannel());
|
||||
final handle4 = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.isTrue(handle3.setMixChannel(handle4));
|
||||
|
||||
Assert.isTrue(handle1.setMixChannel(handle2));
|
||||
Assert.isTrue(handle2.setMixChannel(handle3));
|
||||
Assert.isFalse(handle3.setMixChannel(handle1));
|
||||
Assert.equals(0, handle4.getNumInputs());
|
||||
}
|
||||
}
|
41
lib/aura/Tests/auratests/channels/TestMixChannel.hx
Normal file
41
lib/aura/Tests/auratests/channels/TestMixChannel.hx
Normal file
@ -0,0 +1,41 @@
|
||||
package auratests.channels;
|
||||
|
||||
import utest.Assert;
|
||||
|
||||
import aura.channels.MixChannel;
|
||||
|
||||
@:access(aura.channels.MixChannel)
|
||||
class TestMixChannel extends utest.Test {
|
||||
var mixChannel: MixChannel;
|
||||
var mixChannelHandle: MixChannelHandle;
|
||||
|
||||
function setupClass() {}
|
||||
|
||||
function setup() {
|
||||
mixChannel = new MixChannel();
|
||||
mixChannelHandle = new MixChannelHandle(mixChannel);
|
||||
}
|
||||
|
||||
function teardown() {}
|
||||
|
||||
function test_startUnpausedAndUnfinished() {
|
||||
// Regression test for https://github.com/MoritzBrueckner/aura/issues/7
|
||||
|
||||
final inputHandle = new MixChannelHandle(new MixChannel());
|
||||
|
||||
Assert.isFalse(mixChannel.paused);
|
||||
Assert.isFalse(mixChannel.finished);
|
||||
}
|
||||
|
||||
function test_isNotPlayable_ifNoInputChannelExists() {
|
||||
Assert.isFalse(mixChannel.isPlayable());
|
||||
}
|
||||
|
||||
function test_isPlayable_ifInputChannelExists() {
|
||||
final inputHandle = new MixChannelHandle(new MixChannel());
|
||||
|
||||
inputHandle.setMixChannel(mixChannelHandle);
|
||||
|
||||
Assert.isTrue(mixChannel.isPlayable());
|
||||
}
|
||||
}
|
218
lib/aura/Tests/auratests/channels/TestUncompBufferChannel.hx
Normal file
218
lib/aura/Tests/auratests/channels/TestUncompBufferChannel.hx
Normal file
@ -0,0 +1,218 @@
|
||||
package auratests.channels;
|
||||
|
||||
import utest.Assert;
|
||||
|
||||
import kha.arrays.Float32Array;
|
||||
|
||||
import aura.Types.Balance;
|
||||
import aura.channels.UncompBufferChannel;
|
||||
import aura.dsp.sourcefx.SourceEffect;
|
||||
import aura.types.AudioBuffer;
|
||||
|
||||
@:access(aura.channels.UncompBufferChannel)
|
||||
class TestUncompBufferChannel extends utest.Test {
|
||||
static inline var channelLength = 16;
|
||||
|
||||
var audioChannel: UncompBufferChannel;
|
||||
var sourceFX1: SourceFXDummy;
|
||||
var sourceFX2: SourceFXDummy;
|
||||
|
||||
final data = new Float32Array(2 * channelLength);
|
||||
|
||||
function setupClass() {}
|
||||
|
||||
function setup() {
|
||||
audioChannel = new UncompBufferChannel(data, false);
|
||||
sourceFX1 = new SourceFXDummy();
|
||||
sourceFX2 = new SourceFXDummy();
|
||||
|
||||
audioChannel.addSourceEffect(sourceFX1);
|
||||
audioChannel.addSourceEffect(sourceFX2);
|
||||
}
|
||||
|
||||
function teardown() {}
|
||||
|
||||
function test_optionallyApplySourceEffects_isAppliedOnFirstPlay_ifNoEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(false);
|
||||
|
||||
Assert.isFalse(sourceFX1.wasProcessCalled);
|
||||
Assert.isFalse(sourceFX2.wasProcessCalled);
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isTrue(sourceFX1.wasProcessCalled);
|
||||
Assert.isTrue(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isAppliedOnFirstPlay_ifAnyEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(true);
|
||||
|
||||
Assert.isFalse(sourceFX1.wasProcessCalled);
|
||||
Assert.isFalse(sourceFX2.wasProcessCalled);
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isTrue(sourceFX1.wasProcessCalled);
|
||||
Assert.isTrue(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
|
||||
function test_optionallyApplySourceEffects_isNotAppliedOnSecondPlayAfterFinish_ifNoEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(false);
|
||||
|
||||
audioChannel.play(false);
|
||||
audioChannel.stop();
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isFalse(sourceFX1.wasProcessCalled);
|
||||
Assert.isFalse(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isAppliedOnSecondPlayAfterFinish_ifAnyEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(true);
|
||||
|
||||
audioChannel.play(false);
|
||||
audioChannel.stop();
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isTrue(sourceFX1.wasProcessCalled);
|
||||
Assert.isTrue(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isNotAppliedOnPlayAfterPause_ifNoEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(false);
|
||||
|
||||
audioChannel.play(false);
|
||||
audioChannel.pause();
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isFalse(sourceFX1.wasProcessCalled);
|
||||
Assert.isFalse(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isNotAppliedOnPlayAfterPause_ifAnyEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(true);
|
||||
|
||||
audioChannel.play(false);
|
||||
audioChannel.pause();
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isFalse(sourceFX1.wasProcessCalled);
|
||||
Assert.isFalse(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isNotAppliedOnRetrigger_ifNoEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(false);
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.play(true);
|
||||
|
||||
Assert.isFalse(sourceFX1.wasProcessCalled);
|
||||
Assert.isFalse(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isAppliedOnRetrigger_ifAnyEffectIsConfiguredToApplyOnReplay() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(true);
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.play(true);
|
||||
|
||||
Assert.isTrue(sourceFX1.wasProcessCalled);
|
||||
Assert.isTrue(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_optionallyApplySourceEffects_isAppliedOnConsecutivePlays_ifEffectsHaveChanged() {
|
||||
sourceFX1.applyOnReplay.store(false);
|
||||
sourceFX2.applyOnReplay.store(false);
|
||||
|
||||
audioChannel.play(false);
|
||||
audioChannel.stop();
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
final tempSourceFX = new SourceFXDummy();
|
||||
audioChannel.addSourceEffect(tempSourceFX);
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isTrue(sourceFX1.wasProcessCalled);
|
||||
Assert.isTrue(sourceFX2.wasProcessCalled);
|
||||
|
||||
audioChannel.stop();
|
||||
|
||||
sourceFX1.wasProcessCalled = false;
|
||||
sourceFX2.wasProcessCalled = false;
|
||||
|
||||
audioChannel.removeSourceEffect(tempSourceFX);
|
||||
|
||||
audioChannel.play(false);
|
||||
|
||||
Assert.isTrue(sourceFX1.wasProcessCalled);
|
||||
Assert.isTrue(sourceFX2.wasProcessCalled);
|
||||
}
|
||||
|
||||
function test_nextSamples_onLoop_ApplySourceEffectsOnce() {
|
||||
audioChannel.looping = true;
|
||||
|
||||
Assert.equals(0, sourceFX1.numProcessCalled);
|
||||
Assert.equals(0, sourceFX2.numProcessCalled);
|
||||
|
||||
final outBuffer = new AudioBuffer(2, channelLength + 1);
|
||||
audioChannel.nextSamples(outBuffer, 1000);
|
||||
|
||||
// Make sure process is only called once for _all_ channels
|
||||
Assert.equals(1, sourceFX1.numProcessCalled);
|
||||
Assert.equals(1, sourceFX2.numProcessCalled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class SourceFXDummy extends SourceEffect {
|
||||
public var wasProcessCalled = false;
|
||||
public var numProcessCalled = 0;
|
||||
|
||||
public function new() {}
|
||||
|
||||
function calculateRequiredChannelLength(srcChannelLength: Int): Int {
|
||||
return srcChannelLength;
|
||||
}
|
||||
|
||||
function process(srcBuffer: AudioBuffer, srcChannelLength: Int, dstBuffer: AudioBuffer): Int {
|
||||
wasProcessCalled = true;
|
||||
numProcessCalled++;
|
||||
return srcChannelLength;
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package auratests.channels;
|
||||
|
||||
import utest.Assert;
|
||||
|
||||
import kha.arrays.Float32Array;
|
||||
|
||||
import aura.Types.Balance;
|
||||
import aura.channels.UncompBufferResamplingChannel;
|
||||
import aura.dsp.sourcefx.SourceEffect;
|
||||
import aura.types.AudioBuffer;
|
||||
|
||||
@:access(aura.channels.UncompBufferResamplingChannel)
|
||||
class TestUncompBufferResamplingChannel extends utest.Test {
|
||||
static inline var channelLength = 16;
|
||||
|
||||
var audioChannel: UncompBufferResamplingChannel;
|
||||
|
||||
final rampLeft = new Array<Float>();
|
||||
final rampRight = new Array<Float>();
|
||||
final data = new Float32Array(2 * channelLength); // interleaved stereo
|
||||
|
||||
function setupClass() {
|
||||
rampLeft.resize(channelLength);
|
||||
rampRight.resize(channelLength);
|
||||
|
||||
for (i in 0...channelLength) { // Fill data with a value ramp
|
||||
final val = (i + 1) / channelLength;
|
||||
|
||||
data[i * 2 + 0] = rampLeft[i] = val;
|
||||
data[i * 2 + 1] = rampRight[i] = -val;
|
||||
}
|
||||
}
|
||||
|
||||
function setup() {
|
||||
audioChannel = new UncompBufferResamplingChannel(data, false, 1000);
|
||||
}
|
||||
|
||||
function teardown() {}
|
||||
|
||||
function test_dataConversion() {
|
||||
for (i in 0...channelLength) {
|
||||
Assert.floatEquals(rampLeft[i], audioChannel.data.getChannelView(0)[i]);
|
||||
Assert.floatEquals(rampRight[i], audioChannel.data.getChannelView(1)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function test_nextSamples() {
|
||||
final outBuffer = new AudioBuffer(2, channelLength);
|
||||
|
||||
audioChannel.nextSamples(outBuffer, 1000);
|
||||
|
||||
for (i in 0...channelLength) {
|
||||
Assert.floatEquals(rampLeft[i], outBuffer.getChannelView(0)[i]);
|
||||
Assert.floatEquals(rampRight[i], outBuffer.getChannelView(1)[i]);
|
||||
}
|
||||
|
||||
// Now the channel has processed all data and will reset position to 0
|
||||
Assert.equals(0, audioChannel.playbackPosition);
|
||||
Assert.floatEquals(0.0, audioChannel.floatPosition);
|
||||
|
||||
// No looping, but request more samples
|
||||
final longOutBuffer = new AudioBuffer(2, channelLength + 4);
|
||||
audioChannel.nextSamples(longOutBuffer, 1000);
|
||||
for (i in 0...channelLength) {
|
||||
Assert.floatEquals(rampLeft[i], longOutBuffer.getChannelView(0)[i]);
|
||||
Assert.floatEquals(rampRight[i], longOutBuffer.getChannelView(1)[i]);
|
||||
}
|
||||
for (i in channelLength...channelLength + 4) {
|
||||
Assert.floatEquals(0.0, longOutBuffer.getChannelView(0)[i]);
|
||||
Assert.floatEquals(0.0, longOutBuffer.getChannelView(1)[i]);
|
||||
}
|
||||
|
||||
// Now change the sample rate, second half should be zero
|
||||
audioChannel.playbackPosition = 0;
|
||||
audioChannel.floatPosition = 0.0;
|
||||
audioChannel.nextSamples(outBuffer, 500);
|
||||
for (i in Std.int(channelLength / 2)...channelLength) {
|
||||
Assert.floatEquals(0.0, outBuffer.getChannelView(0)[i]);
|
||||
Assert.floatEquals(0.0, outBuffer.getChannelView(1)[i]);
|
||||
}
|
||||
|
||||
// Now with looping
|
||||
audioChannel.playbackPosition = 0;
|
||||
audioChannel.floatPosition = 0.0;
|
||||
audioChannel.looping = true;
|
||||
audioChannel.nextSamples(outBuffer, 500);
|
||||
final halfChannelLength = Std.int(channelLength / 2);
|
||||
for (i in 0...halfChannelLength) {
|
||||
Assert.floatEquals(outBuffer.getChannelView(0)[i], outBuffer.getChannelView(0)[halfChannelLength + i], null, '$i');
|
||||
Assert.floatEquals(outBuffer.getChannelView(1)[i], outBuffer.getChannelView(1)[halfChannelLength + i], null, '$i');
|
||||
}
|
||||
|
||||
// TODO: check sample precise looping without gaps with unusual sample rates?
|
||||
}
|
||||
|
||||
function test_nextSamples_onLoop_ApplySourceEffectsOnce() {
|
||||
audioChannel.looping = true;
|
||||
|
||||
final sourceFX = new SourceFXDummy();
|
||||
|
||||
audioChannel.addSourceEffect(sourceFX);
|
||||
|
||||
Assert.equals(0, sourceFX.numProcessCalled);
|
||||
|
||||
final outBuffer = new AudioBuffer(2, channelLength + 1);
|
||||
audioChannel.nextSamples(outBuffer, 1000);
|
||||
|
||||
// Make sure process is only called once for _all_ channels
|
||||
Assert.equals(1, sourceFX.numProcessCalled);
|
||||
}
|
||||
}
|
||||
|
||||
private class SourceFXDummy extends SourceEffect {
|
||||
public var numProcessCalled = 0;
|
||||
|
||||
public function new() {}
|
||||
|
||||
function calculateRequiredChannelLength(srcChannelLength: Int): Int {
|
||||
return srcChannelLength;
|
||||
}
|
||||
|
||||
function process(srcBuffer: AudioBuffer, srcChannelLength: Int, dstBuffer: AudioBuffer): Int {
|
||||
numProcessCalled++;
|
||||
return srcChannelLength;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user