Skip to content

Instantly share code, notes, and snippets.

@Hyp-X
Forked from mzandvliet/DspApplication.cs
Last active August 6, 2019 19:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hyp-X/a5df43224f09a3ccb8faee57c7220e53 to your computer and use it in GitHub Desktop.
Save Hyp-X/a5df43224f09a3ccb8faee57c7220e53 to your computer and use it in GitHub Desktop.
A quick example of how to play a mouse-controlled sine wave using the DSPGraph preview package
using UnityEngine;
using Unity.Collections;
using Unity.Audio;
using Unity.Mathematics;
using Unity.Burst;
/*
For allocations inside AudioKernels, use Allocator.AudioKernel
*/
public class DspApplication : MonoBehaviour {
private DSPGraph _graph;
private AudioOutputHandle _outputHandle;
private DSPNode _node;
private const int SAMPLERATE = 48000;
private const int NUMFRAMES = 1024;
private const int NUMCHANNELS = 2;
private bool _isRunning;
private void Awake() {
var audioConfig = AudioSettings.GetConfiguration();
Debug.Log("Unity Audio Config:");
Debug.Log(audioConfig.sampleRate);
Debug.Log(audioConfig.dspBufferSize);
Debug.Log(audioConfig.speakerMode);
_graph = DSPGraph.Create(SoundFormat.Stereo, NUMCHANNELS, NUMFRAMES, SAMPLERATE);
// Create a driver that just drives the graph mix based on when the system wants samples
var driver = new DefaultDspGraphDriver { _graph = _graph };
// Attach this driver and graph to the audio output that's configured in Unity
_outputHandle = driver.AttachToDefaultOutput();
var cmd = _graph.CreateCommandBlock();
_node = cmd.CreateDSPNode<OscParams, OscProviders, Osc>();
cmd.AddOutletPort(_node, NUMCHANNELS, SoundFormat.Stereo);
cmd.Connect(_node, 0, _graph.RootDSP, 0);
cmd.SetFloat<OscParams, OscProviders, Osc>(_node, OscParams.Frequency, 440f);
cmd.Complete();
}
private void OnDestroy() {
var cmd = _graph.CreateCommandBlock();
cmd.ReleaseDSPNode(_node);
cmd.Complete();
_outputHandle.Dispose();
}
private void Update() {
var cmd = _graph.CreateCommandBlock();
float pitch = 440f + 220f * Input.GetAxis("Mouse Y");
cmd.SetFloat<OscParams, OscProviders, Osc>(_node, OscParams.Frequency, pitch);
cmd.Complete();
}
private const float TWOPI = math.PI * 2f;
private enum OscParams {
Frequency
}
private enum OscProviders {
Provider
}
[BurstCompile]
private struct Osc : IAudioKernel<OscParams, OscProviders> {
private float _phase;
private float _phaseStep;
private float _freq;
public void Initialize() {}
public void Dispose() {}
public void Execute(ref ExecuteContext<OscParams, OscProviders> context) {
for (int outIdx = 0; outIdx < context.Outputs.Count; outIdx++) {
var sampleBuffer = context.Outputs.GetSampleBuffer(outIdx);
var buffer = sampleBuffer.Buffer;
for (int i = 0; i < NUMFRAMES; i++) {
/*
Manually interpolate frequency parameter (have not yet been able to get the
automatic parameter interpolation system to behave yet)
*/
_freq = math.lerp(_freq, context.Parameters.GetFloat(OscParams.Frequency, i), 0.001f);
_phaseStep = (TWOPI * _freq) / (float)SAMPLERATE;
buffer[i*NUMCHANNELS] = math.sin(_phase);
buffer[i*NUMCHANNELS+1] = buffer[i * NUMCHANNELS];
_phase += _phaseStep;
if (_phase > TWOPI) {
_phase -= TWOPI;
}
}
}
}
}
}
[BurstCompile]
public struct DefaultDspGraphDriver : IAudioOutput {
public DSPGraph _graph;
private int _channelCount;
public void Initialize(int channelCount, SoundFormat format, int sampleRate, long dspBufferSize) {
_channelCount = channelCount;
}
public void BeginMix(int frameCount) {
_graph.BeginMix(frameCount);
}
public void EndMix(NativeArray<float> output, int frames) {
_graph.ReadMix(output, frames, _channelCount);
}
public void Dispose() {
_graph.Dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment