How to play an AudioClip using OnAudioFilterRead()?

I want to build a reverb filter, using OnAudioFilterRead().

Here (Google Drive) is a link to a project file with a scene that uses my current code.

In my code I have a method which looks at the environment, and creates a list of delay values based on the positions of objects relative to the player. However, my current structure results in audio glitches, which I think might be caused by the fact that the methods Reflections() and OnAudioFilterRead() are not being called in sync.

I am currently using an InvokeRepeating() to call Reflections(), however I’d much rather be able to call the latter at a specific moment relative to OnAudioFilterRead(). But, because OnAudioFilterRead() apparantly runs on a seperate thread, I can’t call Reflections() from within OnAudioFilterRead().

If you know how to resolve my audio glitches, and perhaps can tell me something about their origin, I’d be very greatfull! :]

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class myReverb : MonoBehaviour 
{

	float[] myBuffer;
	Collider[] myObjects;
	List<int> myReflections = new List<int>();

	Vector3 myPosition;
	float myDistance;
	int myDelay;

	public float myRange;
	public float myVolume; 
	
	void Start() 
	{

		myBuffer = new float[40960];

		for (int h = 0; h < 40960; h++)
			
		{
			
			myBuffer <mark>= 0f;</mark>


}

//InvokeRepeating results in audio glitches, because it will not run synchronously with OnAudioFilterRead()…
InvokeRepeating (“Reflections”, 0f, 0.01f);

}

public void Reflections()
{

//Clear List…
myReflections.Clear();

//Map environment based on current location…
myPosition = transform.position;

myObjects = Physics.OverlapSphere(myPosition, myRange);

foreach (Collider _Object in myObjects)
{

if (_Object.gameObject.GetComponent())
{

//Convert distance to time, expressed in a number of samples…
myReflections.Add((int)((Vector3.Distance(myPosition, _Object.gameObject.transform.position) / 340.29f) * 44100));

}

}

}

void OnAudioFilterRead(float data, int channels)
{

//Buffer actions…
for (int a = 0; a < 38912; a++)
{

myBuffer[a] = myBuffer[a + 2048];

}

for (int b = 0; b < 2048; b++)
{

myBuffer[38912 + b] = data**;

}

//I’m not allowed to call a method from within OnAudioFilterRead()… :frowning:
//Reflections();

//Insert reflections into audio…
for (int c = 0; c < myReflections.Count; c++)
{

myDelay = myReflections**
```c
**;

			for (int d = 0; d < 2048; d++)
			{

				data[d] += myBuffer[38912 + d - myDelay] * myVolume;

			}

		}

	}

}

```

Hi,

About the pitch problem:
try to check AudioSettings.outputSampleRate to see if the value is matching your clip’s (44100), set the right value if necessary.

Haven’t really read all of the comments but I have wrote a library that plays audio clips by using OnAudioFilterRead, just leaving it below if here if anyone finds it useful.

Hi, Thanks for this great topic, as an audio programmer, i will try to summarise what i think is happening in OnAudioFilterRead.

It’s a on a seperate thread because it is running on the soundcard, or in soundcard time, So in fact it isnt a very programmeable function. The soundcard can only read and play data. trying to actually process DSP in this thread will cause bugs, i.e. reading writing the data to an external filter code.

The soundcard asks for a data of a set size every N seconds, i.e. 2048, depends what it’s latency MME / DX / ASIO buffer is set to.

So all the read ahead and timing management of audio should be done on the processor, and passed as a stream to the buffer, trick is to not let the game go over a certain framerate.

perhaps it’s possible to get the onaudioread to repeat the last buffer in case fps is too slow to maintain audio, will need to figure it out.

InvokeRepeating function is in the same timeframe as update, yield, etc, it is for shooting cannon things and so on but not for framerate independent stuff, if i get it right.

So the main rules with the audio function is that it reads many small buffers very fast, interleaves them on multiple channels, and it’s difficult and highly customizeable to send audio data to the sound card independent of the processor.