public static void TerminateAudioSampleNode(this DSPGraph graph, DSPNode node) { using (var block = graph.CreateCommandBlock()) { block.TerminateAudioSampleNode(node); } }
void Start() { var format = ChannelEnumConverter.GetSoundFormatFromSpeakerMode(AudioSettings.speakerMode); var channels = ChannelEnumConverter.GetChannelCountFromSoundFormat(format); AudioSettings.GetDSPBufferSize(out var bufferLength, out var numBuffers); var sampleRate = AudioSettings.outputSampleRate; m_Graph = DSPGraph.Create(format, channels, bufferLength, sampleRate); var driver = new DefaultDSPGraphDriver { Graph = m_Graph }; driver.AttachToDefaultOutput(); using (var block = m_Graph.CreateCommandBlock()) { m_NoiseFilter = block.CreateDSPNode <NoiseFilter.Parameters, NoiseFilter.Providers, NoiseFilter>(); block.AddOutletPort(m_NoiseFilter, 2); m_LowPass = StateVariableFilter.Create(block, StateVariableFilter.FilterType.Lowpass); block.Connect(m_NoiseFilter, 0, m_LowPass, 0); block.Connect(m_LowPass, 0, m_Graph.RootDSP, 0); } }
void Start() { var format = ChannelEnumConverter.GetSoundFormatFromSpeakerMode(AudioSettings.speakerMode); var channels = ChannelEnumConverter.GetChannelCountFromSoundFormat(format); AudioSettings.GetDSPBufferSize(out var bufferLength, out var numBuffers); var sampleRate = AudioSettings.outputSampleRate; m_Graph = DSPGraph.Create(format, channels, bufferLength, sampleRate); var driver = new DefaultDSPGraphDriver { Graph = m_Graph }; driver.AttachToDefaultOutput(); using (var block = m_Graph.CreateCommandBlock()) { m_SineWave = block.CreateDSPNode<SinWaveNode.Parameters, SinWaveNode.Providers, SinWaveNode>(); block.AddOutletPort(m_SineWave, 2, SoundFormat.Stereo); m_SawWave = block.CreateDSPNode<SawWaveNode.Parameters, SawWaveNode.Providers, SawWaveNode>(); block.AddOutletPort(m_SawWave, 2, SoundFormat.Stereo); m_MixNode = block.CreateDSPNode<MixNode.Parameters, MixNode.Providers, MixNode>(); block.AddInletPort(m_MixNode, 2, SoundFormat.Stereo); block.AddInletPort(m_MixNode, 2, SoundFormat.Stereo); block.AddOutletPort(m_MixNode, 2, SoundFormat.Stereo); block.Connect(m_SineWave, 0, m_MixNode, 0); block.Connect(m_SawWave, 0, m_MixNode, 1); block.Connect(m_MixNode, 0, m_Graph.RootDSP, 0); } }
public void ReleasingNode_InvalidatesHandle() { DSPNode node = default; using (var setup = new GraphSetup((graphSetup, graph, block) => { node = graphSetup.CreateDSPNode <NoParameters, NoProviders, LifecycleTracking>(); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(node, 0, graph.RootDSP, 0); graphSetup.CleanupNodes = false; })) { // Ensure that node is created setup.PumpGraph(); Assert.True(node.Valid); // Release node using (var block = setup.Graph.CreateCommandBlock()) block.ReleaseDSPNode(node); setup.PumpGraph(); // Ensure that node handle is no longer valid Assert.False(node.Valid); } }
public unsafe void InterpolatesEmptyRange() { DSPNode node = default; using (var setup = new GraphSetup((graphSetup, graph, block) => { node = graphSetup.CreateDSPNode <SingleParameterKernel.Parameters, NoProviders, SingleParameterKernel>(); })) { setup.PumpGraph(); long dspClock = 0; float4 value = 10.0f; // Get copy of node with populated fields node = setup.Graph.LookupNode(node.Handle); var nodeParameters = node.Parameters; var parameter = nodeParameters[(int)SingleParameterKernel.Parameters.Parameter]; var newKeyIndex = setup.Graph.AppendKey(parameter.KeyIndex, DSPParameterKey.NullIndex, dspClock, value); for (int sampleOffset = 0; sampleOffset < 10; ++sampleOffset) { Assert.AreEqual(value[0], DSPParameterInterpolator.Generate(sampleOffset, setup.Graph.ParameterKeys.UnsafeDataPointer, newKeyIndex, dspClock, float.MinValue, float.MaxValue, value)[0], 0.001f); } } }
public void EventWithIntHandler(DSPNode evNode, EventWithInt ev) { Debug.Log("EventWithIntHandler"); Assert.That(evNode, Is.EqualTo(Node)); Assert.That(ev.Value, Is.EqualTo(42)); ++EventWithIntCallCount; }
SpectrumRenderer SpawnSpectrumRenderer(DSPNode spectrumNode) { GameObject go = Instantiate(SpectrumRendererPrefab); SpectrumRenderer spectrum = go.GetComponent <SpectrumRenderer>(); spectrum.Init(_Graph, spectrumNode); return(spectrum); }
public void EnumEventHandler(DSPNode evNode, EnumEvent ev) { Debug.Log("EnumEventHandler"); Assert.That(evNode, Is.EqualTo(Node)); Assert.That(ev, Is.EqualTo(EnumEvent.EnumEvent1)); ++EnumEventCallCount; Debug.Log("EnumEventHandler call count: " + EnumEventCallCount); }
ScopeRenderer SpawnScopeRenderer(DSPNode scopeNode) { GameObject go = Instantiate(ScopeRendererPrefab); ScopeRenderer scope = go.GetComponent <ScopeRenderer>(); scope.Init(_Graph, scopeNode); return(scope); }
public void EventWithManyFieldsHandler(DSPNode evNode, EventWithManyFields ev) { Debug.Log("EventWithManyFieldsHandler"); Assert.That(evNode, Is.EqualTo(Node)); Assert.That(ev.IntValue, Is.EqualTo(42)); Assert.That(ev.BoolValue, Is.EqualTo(true)); Assert.That(ev.FloatValue, Is.EqualTo(3.1416F)); Assert.That(ev.CharValue, Is.EqualTo('x')); ++EventWithManyFieldsCallCount; }
public DSPNode CreateDSPNode <TParameters, TProviders, TAudioKernel>() where TParameters : unmanaged, Enum where TProviders : unmanaged, Enum where TAudioKernel : struct, IAudioKernel <TParameters, TProviders> { DSPNode node = Block.CreateDSPNode <TParameters, TProviders, TAudioKernel>(); m_CreatedNodes.Add(node); return(node); }
public static void TriggerAudioSample( this DSPCommandBlock block, DSPNode node, AudioSampleDataReader reader, Categories category = Categories.OneShot) { // Kick off playback. This will be done in a better way in the future. block.UpdateAudioKernel <StartPlayingAudioSample, Parameters, Providers, PlayAudioSampleReaderNode>( new StartPlayingAudioSample(reader, category), node ); }
public void AllocatingKernel_Works() { using (var setup = new GraphSetup((graphSetup, graph, block) => { DSPNode node = graphSetup.CreateDSPNode <NoParameters, NoProviders, AllocatingKernel>(); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(node, 0, graph.RootDSP, 0); })) { setup.PumpGraph(); } }
public void LeakyKernel_EmitsWarning() { using (var setup = new GraphSetup((graphSetup, graph, block) => { DSPNode node = graphSetup.CreateDSPNode <NoParameters, NoProviders, LeakyKernel>(); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(node, 0, graph.RootDSP, 0); })) { setup.PumpGraph(); LogAssert.Expect(LogType.Warning, "1 leaked DSP node allocations"); } }
public void Init(DSPGraph graph, DSPNode scopeNode) { _Graph = graph; _ScopeNode = scopeNode; _Initialized = true; var sm = FindObjectOfType <ScopeManager>(); if (sm != null) { sm.Register(this); } }
public static NodeData CreateGeneratorNode(DSPCommandBlock block, DSPNode consumer, int channelCount, SoundFormat soundFormat) { var node = block.CreateDSPNode <NoParameters, NoProviders, GenerateOne>(); block.AddOutletPort(node, channelCount, soundFormat); var connection = block.Connect(node, 0, consumer, 0); return(new NodeData { Node = node, Connection = connection }); }
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 LeakyGraph_DoesntCrash() { using (var setup = new GraphSetup((graphSetup, graph, block) => { DSPNode node = graphSetup.CreateDSPNode <NoParameters, NoProviders, LifecycleTracking>(); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(node, 0, graph.RootDSP, 0); })) { setup.CleanupNodes = false; LogAssert.Expect(LogType.Warning, kNodeLeakMessage); setup.PumpGraph(); } }
static int CountOutputConnections(DSPGraph graph, DSPNode node) { var connections = graph.Connections; int count = 0; var outputConnectionIndex = node.OutputConnectionIndex; while (outputConnectionIndex != DSPConnection.InvalidIndex) { ++count; outputConnectionIndex = connections[outputConnectionIndex].NextOutputConnectionIndex; } return(count); }
public void StateChange_InvokesLifecycleCallbacks() { using (var setup = new GraphSetup((graphSetup, graph, block) => { DSPNode node = graphSetup.CreateDSPNode <NoParameters, NoProviders, LifecycleTracking>(); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(node, 0, graph.RootDSP, 0); })) { setup.PumpGraph(); Assert.Greater(LifecycleTracking.Initialized, 0); Assert.Greater(LifecycleTracking.Executed, 0); Assert.AreEqual(LifecycleTracking.LifecyclePhase.Executing, LifecycleTracking.Phase); } Assert.AreEqual(LifecycleTracking.LifecyclePhase.Disposed, LifecycleTracking.Phase); }
public void AllocatingKernelMemory_DuringUpdateJob_Works() { var node = new DSPNode(); using (var setup = new GraphSetup((graphSetup, graph, block) => { node = graphSetup.CreateDSPNode <NoParameters, NoProviders, LifecycleTracking>(); block.AddOutletPort(node, kChannelCount, kSoundFormat); block.Connect(node, 0, graph.RootDSP, 0); })) { using (var block = setup.Graph.CreateCommandBlock()) block.CreateUpdateRequest <AllocatingUpdateJob, NoParameters, NoProviders, LifecycleTracking>(new AllocatingUpdateJob(), node, null); setup.PumpGraph(); } }
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); } } } }
private void ReleaseNode(DSPNode node, AudioSampleNodeCompleted @event) { if (@event.category != Categories.OneShot || !this._available.IsCreated) { return; } using (var block = this._graph.CreateCommandBlock()) { block.Disconnect( node, 0, this._graph.RootDSP, 0 ); } this._available.Enqueue(node); }
void Start() { var format = ChannelEnumConverter.GetSoundFormatFromSpeakerMode(AudioSettings.speakerMode); var channels = ChannelEnumConverter.GetChannelCountFromSoundFormat(format); AudioSettings.GetDSPBufferSize(out var bufferLength, out var numBuffers); var sampleRate = AudioSettings.outputSampleRate; m_Graph = DSPGraph.Create(format, channels, bufferLength, sampleRate); var driver = new DefaultDSPGraphDriver { Graph = m_Graph }; m_Output = driver.AttachToDefaultOutput(); // Add an event handler delegate to the graph for ClipStopped. So we are notified // of when a clip is stopped in the node and can handle the resources on the main thread. m_HandlerID = m_Graph.AddNodeEventHandler <ClipStopped>((node, evt) => { Debug.Log("Received ClipStopped event on main thread, cleaning resources"); }); // All async interaction with the graph must be done through a DSPCommandBlock. // Create it here and complete it once all commands are added. var block = m_Graph.CreateCommandBlock(); m_Node = block.CreateDSPNode <PlayClipNode.Parameters, PlayClipNode.SampleProviders, PlayClipNode>(); // Currently input and output ports are dynamic and added via this API to a node. // This will change to a static definition of nodes in the future. block.AddOutletPort(m_Node, 2, SoundFormat.Stereo); // Connect the node to the root of the graph. m_Connection = block.Connect(m_Node, 0, m_Graph.RootDSP, 0); // We are done, fire off the command block atomically to the mixer thread. block.Complete(); }
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); } } }
void AddProviderToNode <TKernel>(DSPCommandBlock block, DSPNode node, int index = -1, float value = kSignalValueA, Providers item = Providers.VariableSizeArray, bool insert = true) where TKernel : struct, IAudioKernel <NoParameters, Providers> { var provider = AudioSampleProvider.Create(kChannelCount, kSampleRate); provider.enableSilencePadding = false; var inputBuff = new NativeArray <float>(2 * kChannelCount * kDspBufferSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory); for (int i = 0; i < inputBuff.Length; ++i) { inputBuff[i] = value; } provider.QueueSampleFrames(inputBuff); inputBuff.Dispose(); if (insert) { block.InsertSampleProvider <NoParameters, Providers, TKernel>(provider.id, node, item, index); } else { block.SetSampleProvider <NoParameters, Providers, TKernel>(provider.id, node, item, index); } }
void ConfigureDSP() { AudioConfiguration audioConfig = AudioSettings.GetConfiguration(); Debug.LogFormat("BufferSize={0} SampleRate={1}", audioConfig.dspBufferSize, audioConfig.sampleRate); _MicrophoneClip = Microphone.Start(Microphone.devices[0], true, 1, audioConfig.sampleRate); Debug.LogFormat("Microphone Channels={0} Frequency={1} Samples={2} Ambisonic={3}", _MicrophoneClip.channels, _MicrophoneClip.frequency, _MicrophoneClip.samples, _MicrophoneClip.ambisonic); _MicrophoneBuffer = new NativeArray <float>(_MicrophoneClip.samples, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); _MicrophoneDataArray = new float[_MicrophoneClip.samples]; _Graph = DSPGraph.Create(SoundFormat.Stereo, 2, audioConfig.dspBufferSize, audioConfig.sampleRate); _Driver = new MyAudioDriver { Graph = _Graph }; _OutputHandle = _Driver.AttachToDefaultOutput(); // create graph structure using (var block = _Graph.CreateCommandBlock()) { // // create nodes // _Microphone = block.CreateDSPNode <MicrophoneNode.Parameters, MicrophoneNode.Providers, MicrophoneNode>(); block.AddOutletPort(_Microphone, 1, SoundFormat.Mono); _Scope = block.CreateDSPNode <ScopeNode.Parameters, ScopeNode.Providers, ScopeNode>(); block.AddInletPort(_Scope, 1, SoundFormat.Mono); _Spectrum = block.CreateDSPNode <SpectrumNode.Parameters, SpectrumNode.Providers, SpectrumNode>(); block.AddInletPort(_Spectrum, 1, SoundFormat.Mono); _MonoToStereo = block.CreateDSPNode <MonoToStereoNode.Parameters, MonoToStereoNode.Providers, MonoToStereoNode>(); block.AddInletPort(_MonoToStereo, 1, SoundFormat.Mono); // left block.AddInletPort(_MonoToStereo, 1, SoundFormat.Mono); // right block.AddOutletPort(_MonoToStereo, 2, SoundFormat.Stereo); // // connect nodes // block.Connect(_Microphone, 0, _MonoToStereo, 0); block.Connect(_Microphone, 0, _MonoToStereo, 1); block.Connect(_MonoToStereo, 0, _Graph.RootDSP, 0); block.Connect(_Microphone, 0, _Scope, 0); block.Connect(_Microphone, 0, _Spectrum, 0); // // set parameters // block.SetFloat <ScopeNode.Parameters, ScopeNode.Providers, ScopeNode>(_Scope, ScopeNode.Parameters.Time, 1f); block.SetFloat <ScopeNode.Parameters, ScopeNode.Providers, ScopeNode>(_Scope, ScopeNode.Parameters.TriggerTreshold, 0f); block.SetFloat <SpectrumNode.Parameters, SpectrumNode.Providers, SpectrumNode>(_Spectrum, SpectrumNode.Parameters.Window, (float)SpectrumNode.WindowType.Hamming); } _ScopeRenderer = SpawnScopeRenderer(_Scope); _ScopeRenderer.Height = 5.0f; _ScopeRenderer.Offset = 0.0f; _SpectrumRenderer = SpawnSpectrumRenderer(_Spectrum); StartCoroutine(InitMicCoroutine()); }
public NodeData CreateGeneratorNode(DSPNode consumer, int channelCount = DefaultChannelCount, SoundFormat soundFormat = DefaultSoundFormat) { using (var block = Graph.CreateCommandBlock()) return(CreateGeneratorNode(block, consumer, channelCount, soundFormat)); }
public static void TerminateAudioSampleNode(this DSPCommandBlock block, DSPNode node) { block.UpdateAudioKernel <TerminateAudioSampleNode, Parameters, Providers, PlayAudioSampleReaderNode>( new TerminateAudioSampleNode(), node); }