public RayGun()
            {
                //audio nodes
                m_sawTooth = new SawtoothWaveGenerator();
                m_position = new Clock();
                m_envelope = new ADSREnvelope();
                m_envelope.sustainLevel = 0f; // decay should fade to sustain of 0
                m_envelope.AttackMS = 10; //fade in duration (a little fade in to prevent 'clicks')
                m_envelope.DecayMS = 1000; //fade out duration

                m_gainer = new Gain();
                m_gainer.drive = 1.0;

                //connect our nested graph
                //note how the sample output from the clock can be used to control the envelope position
                m_position.SampleGenerated += (sample) => m_envelope.Position = m_position.GetSample();
                m_gainer.InputNode = m_sawTooth;
            }
        /// <summary>
        /// When Awake is called by the Unity Engine we build our simple audio graph,
        /// and attach the root node of our graph to the driver.
        /// </summary>
        void Awake()
        {
            //context
            Driver.sampleRate = 48000;
            m_driver = new Driver();

            //audio nodes
            m_sineWave = new SineWaveGenerator();
            m_gainer = new Gain();
            m_gainer.drive = 1.5;
            var customAudioNode = new VolumeLimiter();
            m_mixer = new MonoMixer();
            m_mixer.masterOutputLevel = 0.5;

            //connect our graph
            m_gainer.InputNode = m_sineWave;
            customAudioNode.inputNode = m_gainer;
            m_mixer.AddInput(customAudioNode);
            m_driver.rootNode = m_mixer;
        }