/// <summary>
    /// Raises the audio filter read event.
    /// </summary>
    /// <param name="data">Data.</param>
    /// <param name="channels">Channels.</param>
    void OnAudioFilterRead(float[] data, int channels)
    {
        // Do not spatialize if we are not initialized, or if there is no
        // audio source attached to game object
        if ((OVRVoiceMod.IsInitialized() != OVRVoiceMod.ovrVoiceModSuccess) || audioSource == null)
        {
            return;
        }

        // increase the gain of the input to get a better signal input
        for (int i = 0; i < data.Length; ++i)
        {
            data[i] = data[i] * gain;
        }

        // Send data into VoiceMod context for processing (if context is not 0)
        lock (this)
        {
            if (context != 0)
            {
                OVRVoiceMod.ProcessFrameInterleaved(context, data);
            }
        }

        // Turn off output (so that we don't get feedback from a mic too close to speakers)
        if (audioMute == true)
        {
            for (int i = 0; i < data.Length; ++i)
            {
                data[i] = data[i] * 0.0f;
            }
        }
    }
    // * * * * * * * * * * * * *
    // Public Functions

    /// <summary>
    /// Sends the parameter.
    /// </summary>
    /// <returns>The parameter.</returns>
    /// <param name="parameter">Parameter.</param>
    /// <param name="value">Value.</param>
    public int SendParameter(ovrVoiceModParams parameter, int value)
    {
        if (OVRVoiceMod.IsInitialized() != OVRVoiceMod.ovrVoiceModSuccess)
        {
            return((int)OVRVoiceMod.ovrVoiceModError.Unknown);
        }

        return(OVRVoiceMod.SendParameter(context, (int)parameter, value));
    }