public void DisconnectionByHandle_ProducesDefaultSamples_InInputPorts(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(true, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) { var channelCount = 1; var attenuation1 = 0.5F; testData.Attenuate(testData.Connection, attenuation1); var nodeData = testData.CreateGeneratorNode(); var attenuation2 = 0.25F; testData.Attenuate(nodeData.Connection, attenuation2); using (var buff = new NativeArray <float>(TestData.DefaultBufferSize * channelCount, Allocator.Temp)) testData.Mix(buff, buff.Length / channelCount, channelCount); using (var block = testData.Graph.CreateCommandBlock()) block.Disconnect(testData.Connection); testData.CheckMix(attenuation2); using (var block = testData.Graph.CreateCommandBlock()) block.Disconnect(nodeData.Connection); testData.CheckMix(0.0F); testData.RemoveNode(nodeData.Node); } }
public void UncompletedBlock_IsNotExecuted(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup()) { var block = setup.Graph.CreateCommandBlock(); var node = block.CreateDSPNode <NoParameters, NoProviders, GenerateOne>(); block.AddOutletPort(node, GraphSetup.ChannelCount, GraphSetup.SoundFormat); block.Connect(node, 0, setup.Graph.RootDSP, 0); using (var buffer = new NativeArray <float>(setup.Graph.DSPBufferSize * GraphSetup.ChannelCount, Allocator.Temp, NativeArrayOptions.ClearMemory)) { setup.Graph.BeginMix(setup.Graph.DSPBufferSize, executionMode); setup.Graph.ReadMix(buffer, setup.Graph.DSPBufferSize, GraphSetup.ChannelCount); foreach (var sample in buffer) { Assert.AreEqual(0.0f, sample, 0.001f); } block.Complete(); setup.Graph.BeginMix(setup.Graph.DSPBufferSize, executionMode); setup.Graph.ReadMix(buffer, setup.Graph.DSPBufferSize, GraphSetup.ChannelCount); foreach (var sample in buffer) { Assert.AreEqual(1.0f, sample, 0.001f); } using (block = setup.Graph.CreateCommandBlock()) block.ReleaseDSPNode(node); } } }
public void InvalidExecutionMode_Throws(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(false, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) { Assert.Throws <ArgumentException>(() => testData.CheckMix(0.0F)); } }
public void ReadSampleProvider_PlaysSignal(DSPGraph.ExecutionMode executionMode) { using (var testData = CreateTestData <ReadSampleProviderKernel, Providers>( (block, node) => AddProviderToNode <ReadSampleProviderKernel>(block, node))) { CheckOutputBuffer(testData.Graph, (buffer) => CheckBufferHasValue(buffer, kSignalValueA), executionMode); } }
public void AttenuatedInput_ProducesAttenuatedResults_InInputPorts(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(true, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) { var attenuation = 0.5F; testData.Attenuate(testData.Connection, attenuation); testData.CheckMix(attenuation); } }
public void AttenuatedInput_ProducesMultiChannelAttenuatedResults_InInputPorts(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(true, 2, SoundFormat.Stereo, executionMode)) { var attenuationLeft = 0.3F; var attenuationRight = 0.7F; testData.Attenuate(testData.Connection, 0, attenuationLeft, attenuationRight); testData.CheckMix(attenuationLeft, attenuationRight); } }
public void ReadOverwrittenSampleProvider_PlaysNewSignal(DSPGraph.ExecutionMode executionMode) { using (var testData = CreateTestData <ReadSampleProviderKernel, Providers>( (block, node) => AddProviderToNode <ReadSampleProviderKernel>(block, node))) { using (var block = testData.Graph.CreateCommandBlock()) AddProviderToNode <ReadSampleProviderKernel>(block, testData.Node, 0, kSignalValueB); CheckOutputBuffer(testData.Graph, (buffer) => CheckBufferHasValue(buffer, kSignalValueB), executionMode); } }
public void DSPClockIncrementsByLength(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup()) { for (int i = 0; i < 10; ++i) { Assert.AreEqual(i * setup.Graph.DSPBufferSize, setup.Graph.DSPClock); setup.PumpGraph(); } } }
public void CancelingBlock_InvalidatesHandle(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup()) { var block = setup.Graph.CreateCommandBlock(); var node = block.CreateDSPNode <NoParameters, NoProviders, GenerateOne>(); block.AddOutletPort(node, GraphSetup.ChannelCount, GraphSetup.SoundFormat); block.Connect(node, 0, setup.Graph.RootDSP, 0); block.Cancel(); Assert.False(block.Valid); } }
public void MultiAttenuatedInput_ProducesSummedAttenuatedResults_InInputPorts(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(true, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) { var attenuation1 = 0.5F; testData.Attenuate(testData.Connection, attenuation1); var nodeData = testData.CreateGeneratorNode(); var attenuation2 = 0.25F; testData.Attenuate(nodeData.Connection, attenuation2); testData.CheckMix(attenuation1 + attenuation2); testData.RemoveNode(nodeData.Node); } }
public void DSPNode_WithNoInputsOrOutputs_IsNotExecuted(DSPGraph.ExecutionMode executionMode) { DSPNode node = default; using (var setup = new GraphSetup((graphSetup, graph, block) => { node = graphSetup.CreateDSPNode <NoParameters, NoProviders, LifecycleTracking>(); })) { setup.PumpGraph(); Assert.AreEqual(0, LifecycleTracking.Executed); } }
public void MultipleBeginMix_Works(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup()) { using (var buffer = new NativeArray <float>(setup.Graph.DSPBufferSize * GraphSetup.ChannelCount, Allocator.Temp)) { int i; for (i = 0; i < 10; ++i) { setup.Graph.BeginMix(setup.Graph.DSPBufferSize); } setup.Graph.ReadMix(buffer, setup.Graph.DSPBufferSize, GraphSetup.ChannelCount); Assert.AreEqual(i * setup.Graph.DSPBufferSize, setup.Graph.DSPClock); } } }
public void Connect_WithInterleavedBlocks_DoesntCrash(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup()) { using (var outerBlock = setup.Graph.CreateCommandBlock()) { var node = outerBlock.CreateDSPNode <NoParameters, NoProviders, NullAudioKernel>(); using (var innerBlock = setup.Graph.CreateCommandBlock()) { innerBlock.AddOutletPort(node, GraphSetup.ChannelCount, GraphSetup.SoundFormat); innerBlock.Connect(node, 0, setup.Graph.RootDSP, 0); } } LogAssert.Expect(LogType.Exception, kArgumentException); } }
public void MultiNoopInput_ProducesSummedAttenuatedResults_InInputPorts(DSPGraph.ExecutionMode executionMode) { // This test covers buffer stealing when inputs are noop (i.e. having a 1.0 non-animated attenuation). // Because buffer stealing is only applicable to inputs that don't belong to the root node, we // use an intermediate pass-through node (hence passing false to Create in order for it to not create the // generator that it normally creates and create a PassThrough instead). using (var testData = TestData.Create(false, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) { var generator1 = testData.CreateGeneratorNode(testData.Node); var attenuation1 = 1.0F; testData.Attenuate(generator1.Connection, attenuation1); var generator2 = testData.CreateGeneratorNode(testData.Node); var attenuation2 = 0.25F; testData.Attenuate(generator2.Connection, attenuation2); testData.CheckMix(attenuation1 + attenuation2); testData.RemoveNode(generator1.Node); testData.RemoveNode(generator2.Node); } }
public void ReleasingDSPNode_InChain_KillsSignal(DSPGraph.ExecutionMode executionMode) { DSPNode generator = default; DSPNode passthrough = default; using (var setup = new GraphSetup((graphSetup, graph, block) => { generator = block.CreateDSPNode <NoParameters, NoProviders, GenerateOne>(); block.AddOutletPort(generator, GraphSetup.ChannelCount, GraphSetup.SoundFormat); passthrough = block.CreateDSPNode <NoParameters, NoProviders, PassThrough>(); block.AddInletPort(passthrough, GraphSetup.ChannelCount, GraphSetup.SoundFormat); block.AddOutletPort(passthrough, GraphSetup.ChannelCount, GraphSetup.SoundFormat); block.Connect(generator, 0, passthrough, 0); block.Connect(passthrough, 0, graph.RootDSP, 0); })) { using (var buffer = new NativeArray <float>(setup.Graph.DSPBufferSize * GraphSetup.ChannelCount, Allocator.Temp)) { setup.Graph.BeginMix(setup.Graph.DSPBufferSize); setup.Graph.ReadMix(buffer, setup.Graph.DSPBufferSize, GraphSetup.ChannelCount); foreach (var sample in buffer) { Assert.AreEqual(1.0f, sample, 0.001f); } using (var block = setup.Graph.CreateCommandBlock()) block.ReleaseDSPNode(passthrough); setup.Graph.BeginMix(setup.Graph.DSPBufferSize); setup.Graph.ReadMix(buffer, setup.Graph.DSPBufferSize, GraphSetup.ChannelCount); foreach (var sample in buffer) { Assert.AreEqual(0.0f, sample, 0.001f); } using (var block = setup.Graph.CreateCommandBlock()) block.ReleaseDSPNode(generator); } } }
public void MixOverwritesData(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup((graphSetup, graph, block) => { DSPNode node = graphSetup.CreateDSPNode <NoParameters, NoProviders, GenerateOne>(); block.AddOutletPort(node, GraphSetup.ChannelCount, GraphSetup.SoundFormat); block.Connect(node, 0, graph.RootDSP, 0); })) { using (var buffer = new NativeArray <float>(setup.Graph.DSPBufferSize * GraphSetup.ChannelCount, Allocator.Temp, NativeArrayOptions.ClearMemory)) { setup.Graph.BeginMix(setup.Graph.DSPBufferSize, executionMode); setup.Graph.ReadMix(buffer, setup.Graph.DSPBufferSize, GraphSetup.ChannelCount); foreach (var sample in buffer) { Assert.AreEqual(1.0f, sample, 0.001f); } } } }
public void UpdateRequestCallsDelegate(DSPGraph.ExecutionMode executionMode) { var channelCount = 2; var soundFormat = SoundFormat.Stereo; using (var graph = DSPGraph.Create(soundFormat, channelCount, 100, 1000)) { DSPNode node; using (var block = graph.CreateCommandBlock()) { node = block.CreateDSPNode <NoParameters, NoProviders, NullAudioKernel>(); block.AddOutletPort(node, channelCount, soundFormat); block.Connect(node, 0, graph.RootDSP, 0); } using (var buff = new NativeArray <float>(200, Allocator.Temp)) { graph.BeginMix(0, executionMode); graph.ReadMix(buff, buff.Length / channelCount, channelCount); var called = false; DSPNodeUpdateRequest <NullAudioKernelUpdater, NoParameters, NoProviders, NullAudioKernel> updateRequest; using (var block = graph.CreateCommandBlock()) updateRequest = block.CreateUpdateRequest <NullAudioKernelUpdater, NoParameters, NoProviders, NullAudioKernel>( new NullAudioKernelUpdater(), node, req => { called = true; }); graph.BeginMix(0, executionMode); graph.ReadMix(buff, buff.Length / channelCount, channelCount); Assert.False(called); graph.Update(); Assert.True(called); updateRequest.Dispose(); } using (var block = graph.CreateCommandBlock()) block.ReleaseDSPNode(node); } }
public void WritingToInputBuffer_Throws(DSPGraph.ExecutionMode executionMode) { using (var setup = new GraphSetup((graphSetup, graph, block) => { DSPNode generator = graphSetup.CreateDSPNode <NoParameters, NoProviders, GenerateOne>(); block.AddOutletPort(generator, kChannelCount, kSoundFormat); DSPNode node = graphSetup.CreateDSPNode <NoParameters, NoProviders, WritingToInputBufferKernel>(); block.AddInletPort(node, kChannelCount, kSoundFormat); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(generator, 0, node, 0); block.Connect(node, 0, graph.RootDSP, 0); })) { using (var buff = new NativeArray <float>(200, Allocator.TempJob)) { setup.Graph.BeginMix(0, executionMode); setup.Graph.ReadMix(buff, 200 / kChannelCount, kChannelCount); } } }
public void AttenuatedInterpolatedInput_ProducesInterpolatedResults_InInputPorts(DSPGraph.ExecutionMode executionMode) { var channelCount = 2; var soundFormat = SoundFormat.Stereo; using (var testData = TestData.Create(true, channelCount, soundFormat, executionMode)) { var attenuation = 0.0F; testData.Attenuate(testData.Connection, attenuation, TestData.DefaultBufferSize); using (var buff = new NativeArray <float>(TestData.DefaultBufferSize * channelCount, Allocator.Temp)) { testData.Mix(buff, buff.Length / channelCount, channelCount); VerifyInterpolatedAttenuation(buff, 0, TestData.DefaultBufferSize, channelCount, new[] { DSPConnection.DefaultAttenuation, DSPConnection.DefaultAttenuation }, new [] { -1.0f / (TestData.DefaultBufferSize - 1), -1.0f / (TestData.DefaultBufferSize - 1), }); } } }
public void SustainedAttenuation_ProducesSameAttenuation_InInputPorts(DSPGraph.ExecutionMode executionMode) { var channelCount = 2; var soundFormat = SoundFormat.Stereo; var baseAttenuation = new[] { 0.0f, 0.0f }; using (var testData = TestData.Create(true, channelCount, soundFormat, executionMode)) { using (var block = testData.Graph.CreateCommandBlock()) { block.SetAttenuation(testData.Connection, baseAttenuation[0]); block.AddAttenuationKey(testData.Connection, 49, 100.0f); block.SustainAttenuation(testData.Connection, 99); } using (var buff = new NativeArray <float>(TestData.DefaultBufferSize * channelCount, Allocator.Temp)) { testData.Mix(buff, buff.Length / channelCount, channelCount); VerifyInterpolatedAttenuation(buff, 0, 50, channelCount, baseAttenuation, new [] { 100.0f / 49, 100.0f / 49, }); VerifyInterpolatedAttenuation(buff, 50, 50, channelCount, new[] { 100.0f, 100.0f, }, new [] { 0.0f, 0.0f, }); } } }
public void UpdateValueFromKernel(DSPGraph.ExecutionMode executionMode) { var channelCount = 2; var soundFormat = SoundFormat.Stereo; using (var graph = DSPGraph.Create(soundFormat, channelCount, 100, 1000)) { DSPNode node; using (var block = graph.CreateCommandBlock()) { node = block.CreateDSPNode <NoParameters, NoProviders, TestUpdateKernel>(); block.AddOutletPort(node, channelCount, soundFormat); block.Connect(node, 0, graph.RootDSP, 0); } using (var buff = new NativeArray <float>(200, Allocator.Temp)) { graph.BeginMix(0, executionMode); graph.ReadMix(buff, buff.Length / channelCount, channelCount); using (var block = graph.CreateCommandBlock()) { var kernelUpdater = new TestValueKernelUpdater { ValueToDrop = 69.0f }; block.UpdateAudioKernel <TestValueKernelUpdater, NoParameters, NoProviders, TestUpdateKernel>(kernelUpdater, node); } graph.BeginMix(0, executionMode); graph.ReadMix(buff, buff.Length / channelCount, channelCount); } using (var block = graph.CreateCommandBlock()) block.ReleaseDSPNode(node); } }
public void UnattachedSubtreesAreNotExecutedWithModeDisabled(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(false, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) { DSPNode unattachedNode; using (var block = testData.Graph.CreateCommandBlock()) { // Create a node that doesn't have an output path to the root of the graph unattachedNode = block.CreateDSPNode <NoParameters, NoProviders, LifecycleTracking>(); block.AddOutletPort(testData.Node, TestData.DefaultChannelCount, TestData.DefaultSoundFormat); block.AddInletPort(unattachedNode, TestData.DefaultChannelCount, TestData.DefaultSoundFormat); block.AddOutletPort(unattachedNode, TestData.DefaultChannelCount, TestData.DefaultSoundFormat); block.Connect(testData.Node, 1, unattachedNode, 0); } testData.CheckMix(0.0F); // The lifecycle node should not be executing Assert.AreEqual(LifecycleTracking.LifecyclePhase.Initialized, LifecycleTracking.Phase); using (var block = testData.Graph.CreateCommandBlock()) block.ReleaseDSPNode(unattachedNode); } }
public void InterruptedAttenuation_ContinuesWithAttenuatedValue(DSPGraph.ExecutionMode executionMode) { var channelCount = 2; var soundFormat = SoundFormat.Stereo; using (var testData = TestData.Create(true, channelCount, soundFormat, executionMode)) { var attenuation = 0.0f; var attenuationLength = 2 * TestData.DefaultBufferSize; testData.Attenuate(testData.Connection, attenuation, attenuationLength); using (var buff = new NativeArray <float>(TestData.DefaultBufferSize * channelCount, Allocator.Temp)) { float[] baseAttenuationValue = { DSPConnection.DefaultAttenuation, DSPConnection.DefaultAttenuation }; float[] attenuationDelta = { (-1 / ((float)(TestData.DefaultBufferSize * 2) - 1)), (-1 / ((float)(TestData.DefaultBufferSize * 2) - 1)) }; testData.Mix(buff, buff.Length / channelCount, channelCount); VerifyInterpolatedAttenuation(buff, 0, TestData.DefaultBufferSize, channelCount, baseAttenuationValue, attenuationDelta); // Lookup updated connection from graph var connection = testData.Graph.LookupConnection(testData.Connection.Handle); baseAttenuationValue = new[] { connection.Attenuation.Value[0], connection.Attenuation.Value[1] }; Assert.AreEqual(buff[(TestData.DefaultBufferSize * channelCount) - 1], baseAttenuationValue[0], 0.0001); testData.Attenuate(testData.Connection, DSPConnection.DefaultAttenuation, TestData.DefaultBufferSize); testData.Mix(buff, buff.Length / channelCount, channelCount); attenuationDelta = new[] { (DSPConnection.DefaultAttenuation - baseAttenuationValue[0]) / (TestData.DefaultBufferSize - 1), (DSPConnection.DefaultAttenuation - baseAttenuationValue[1]) / (TestData.DefaultBufferSize - 1), }; VerifyInterpolatedAttenuation(buff, 0, TestData.DefaultBufferSize, channelCount, baseAttenuationValue, attenuationDelta); connection = testData.Graph.LookupConnection(testData.Connection.Handle); Assert.AreEqual(DSPConnection.DefaultAttenuation, connection.Attenuation.Value[0]); } } }
void CheckOutputBuffer(DSPGraph graph, Action <NativeArray <float> > check = null, DSPGraph.ExecutionMode executionMode = DSPGraph.ExecutionMode.Jobified) { using (var buffer = new NativeArray <float>(kChannelCount * kDspBufferSize, Allocator.Temp)) { graph.BeginMix(0, executionMode); graph.ReadMix(buffer, kDspBufferSize, kChannelCount); check?.Invoke(buffer); } }
public void ConnectNodes_ProducesResults_InInputPorts(DSPGraph.ExecutionMode executionMode) { using (var testData = TestData.Create(true, TestData.DefaultChannelCount, TestData.DefaultSoundFormat, executionMode)) testData.CheckMix(1.0F); }
public static TestData Create(bool createGenerator = true, int channelCount = DefaultChannelCount, SoundFormat soundFormat = DefaultSoundFormat, DSPGraph.ExecutionMode executionMode = DSPGraph.ExecutionMode.Jobified) { var graph = DSPGraph.Create(soundFormat, channelCount, DefaultBufferSize, 1000); NodeData nodeData; using (var block = graph.CreateCommandBlock()) nodeData = createGenerator ? CreateGeneratorNode(block, graph.RootDSP, channelCount, soundFormat) : CreatePassthroughNode(block, graph, channelCount, soundFormat); return(new TestData { Graph = graph, Node = nodeData.Node, Connection = nodeData.Connection, ExecutionMode = executionMode, }); }