So AddVoiceData is being called every time new samples become available from Steam? If this is the case, then the reason for the crackling and pops would be due to short gaps of time between AddVoiceData calls when the FMOD::Sound has finished playing and there are no more samples to play, so it outputs silence. This is could loosely be described as “buffer starvation”, and the way to avoid it is to do three things:
- Rather than playing a new
FMOD::Soundevery time samples become available, useAddVoiceDatato write your samples to an intermediate ring buffer, then in yourUpdateloop read from the buffer and add it to yourFMOD::SoundusingSound::lock/Sound::unlock. This will ensure samples are being given to theFMOD::Soundwithout any gaps. - Introduce some latency to give yourself a little more time for samples to become available. You can do this by waiting for the write position of your buffer to reach some value before starting to read from it and filling your
FMOD::Sound. - Keep track of the distance between your read and write positions, and when the distance is greater than your target latency, use
Channel::setFrequencyto speed-up the sample rate of yourFMOD::Channelto get theFMOD::Soundto consume samples faster. Likewise when the distance is less than your target latency, reduce the sample rate of yourFMOD::Channeluntil you get back to your target latency. This will account for any irregularities in the rate at which samples arrive fromAddVoiceData, and will ensure you never run out of samples to play. If you speed up or slow down too quickly however you will get pitch distortions, so only make very small changes to the sample rate.
I recently wrote an example which applies this approach to hook into a Video’s audio source in Unity and get it playing through FMOD- it is the same concept and should help demonstrate how to avoid buffer starvation.