Hello again everyone.
This post is related to this other post http://www.gamedev.net/topic/682978-audio-system/#entry5314425 i made a few weeks ago. The link is just for reference.
In short, i'm working on the development of a 3D audio system. It's a personal project and i'm still at the protorype and experimentation phase. I have been mostly working on the algorithms for 3D sound rendering so far. Doppler shift and distance model are the next things.
My problem is with the way the host application comminicates with the mixer thread. Here are the basic objects involved in this part :
- AudioSource : It is a struct that contains the mixing parameters that can be updated by the application (position, speed, orientation, state : play, pause, stop, etc). This is a very light weight object (64 bytes each). This a POD in the most simple sens.
- MixerSource : This is an internal representation of a source containing data that are accessed only by the mixer (the current playback position, a pointer to the audio data buffer, etc). These informations are persistent for a source accross updates. An AudioSource has a pointer to this structure (it could eventually be a handle of some sort to make it more opaque).
- AudioBuffer : This object contains the audio pcm data to be played by the source and its parameters (sample rate, etc). A buffer can be shared by multiple sources and they are accessed in read only by the mixer. It basically loads and process like 2.5 or 3ms worth of data every cycle.
So the application will call an update method that takes an array of AudioSources, a Listener and the number of AudioSources in the array. This represents an update of the sound configurations in the scene that can be done every frame or every few frames. A copy of this array is then made into a circular queue of AudioSource arrays (copying 64 sources takes less then a microsecond with memcpy) and the mixer thread just process them. The goal of this method is to reduce the amount of synchronization between the two threads. When the mixer starts working on an update (a list of sources), it is working on its own copy.
For synchronization, i'm using a classic critical section/condition variable pair for now and it works great. (CRITICAL_SECTION / CONDITION_VARIABL pair on Windows and a pthread_mutex_t / pthread_cond_t on Linux).
The problem i have is when deleting a source or a buffer. Adding is not a problem because a source will be part of an update only after it has been added. When a source is deleted is another story. If the application wants to remove a source, it needs to synchronise and delete the source but there are some copy (updates) of the source in the queue that still have a pointer to this source. There are different ways i could manage this, but i'm not really foud of any of them.
I would like to know your thoughts about this.