HOME/Articles/

Play Signal without AudioClip

Article Outline

OnAudioFilterRead

By using OnAudioFilterRead method of MonoBehaviour class, you can apply a custom filter to the playing audio or generate a waveform. If you attach a component that implements OnAudioFilterRead to a GameObject that has an AudioSource, you can filter the sound that comes from that AudioSource.

For example, the following code halves the audio signal level:

void OnAudioFilterRead(float[] data, int channels)
{
    var samples = data.Length / channels;

    for (var i = 0; i < samples; ++i)
    {
        for (var ch = 0; ch < channels; ++ch)
        {
            var di = i * channels + ch;
            data[di] = 0.5f * data[di];
        }
    }
}

The data array is formatted as:

index value
0 1st channel (L)
1 2nd channel (R)
2 1st channel (L)
3 2nd channel (R)
... ...

Generate Sine-wave

using UnityEngine;

public class SineGenerator : MonoBehaviour
{
    private AudioSource AudioSource;

    [SerializeField, Range(0, 1)]
    private float Volume = 1;

    [SerializeField, Range(100, 1000)]
    private int Frequency = 440;

    private const float PI_2 = 2 * Mathf.PI;
    private int SampleRate;
    private float Phase;

    private void Awake()
    {
        AudioSource = gameObject.AddComponent<AudioSource>();
        SampleRate = AudioSettings.outputSampleRate;
    }

    private void OnAudioFilterRead(float[] data, int channels)
    {
        var samples = data.Length / channels;

        for (var i = 0; i < samples; ++i)
        {
            var value = GetNextSample();

            for (var ch = 0; ch < channels; ++ch)
            {
                data[i * channels + ch] = value;
            }
        }
    }

    private float GetNextSample()
    {
        Phase += Frequency * PI_2 / SampleRate;
        Phase %= PI_2;
        return Mathf.Sin(Phase) * Volume;
    }
}

Sine Generator

Samples

See the source code here, unity-sine-generator.