Okay, there’s a couple of issues I can spot there.
First, the samples generated by the generate function need to be interleaved into the output buffer. The interleaved buffer format groups samples by channels, so the first n entries are the first sample for each of the n channels, the second n entries are the second sample for each of the channels, and so on. Another way to think of it is that the buffer is a sequence of sample frames where each frame is a single sample for each channel. The length parameter of the DSP process callback is the number of sample frames.
This diagram shows how three frames of sample data for 5.1 surround would be interleaved:
fmod_noise.cpp does have a comment mentioning this interleaving requirement, and the first loop which deals with gain ramping to avoid pops does explicitly interleave the output samples by iterating by samples then channels, but unfortunately it doesn’t demonstrate interleaving the generated signal for the main loop. Because it’s a noise generator it doesn’t bother to generate discrete signals for each channel.
It might be easier to understand if a generate function was evaluated for each channel. In your case to generate a sine wave:
for (unsigned int s = 0; s < length; ++s) // for each frame
{
for (unsigned int c = 0; c < channels; ++c) // for each channel
{
*outbuffer++ = sinf((2 * PI) * m_rotation);
}
m_rotation += m_frequency / sampleRate;
}
You might notice that I changed your evaluation code slightly there, introducing the variable m_rotation which is incremented for each sample frame. This brings me to the second problem I can see with your current implementation - your generator needs to keep track of its position as it generates so that successive calls to your DSP process function will generate sequential sample frames instead of just generating the first n sample frames each time it is called. After a frame is generated the rotation is incremented by the desired frequency of the sine wave (in degrees per second), divided by the system sample rate (in hertz). The system sample rate can be retrieved via the FMOD_DSP_STATE passed to the process callback:
// Get the system sample rate. Error result handling ommitted for clarity.
float sampleRate;
dsp->functions->getsamplerate(dsp, &sampleRate);
I hope this answer gets you unstuck, but please don’t hesitate to ask for more help if anything is unclear, this will help guide us in improving the quality of our documentation!
