sorry for the long post but I want to try and get all the details in here in hopes it will help.

I've been working on building a procedural audio system for use in XNA projects. First this is general structure of the procedural system.

WaveFragments: generate the actual wave forms for a specified duration, based on frequency using a phase accumulator.

Waves: complete wave forms, generated by joining wave fragments together.

DynamicWaves: use a wave fragment to generate small buffers of waveform data, which are pushed into a DynamicSoundEffectInstance to be played.

My problem is (I think) with my wave generation. At first it seems to work OK, but then after a certain time the sounds frequency alters slightly, and then back again later. for example a tone of C3 (130.81f) will increase frequency slightly (but noticeably) at around 20 seconds and then back again later on at 77 seconds. (I've not yet had the patience to see if it shifts again later, I've gone as far as 3 minutes without it shifting up again.

I'm going to assume its a issue with the way I'm generating the wave data with my phase accumulator.

Here is my generation of the PhaseDelta based on provided frequency.

 _PhaseDelta = (float)((Math.PI * 2 * _Frequency) / (float)samplesPerSecond);

and here is the calculation I use for the generation of the wave.

for (int i = 0; i < numSamples; i++)
     _PhaseAccumulator = MathHelper.Lerp(_PhaseAccumulator, _PhaseAccumulator+_PhaseDelta, _PhaseSmoothness);
     data[i] = (float)Math.Sin(_PhaseAccumulator) * _Amplitude;

Thanks in advance for any input that anyone might have. It may be the most glaringly obvious fix, but at this point after hours of dull single tones my brain is two melted to be getting anywhere with fixing this now.

Now I've tried it without lerping the accumulator (obviously produces the clicks at the start) but still produces the shift. I've also tried lerping the phase delta gradually to its new value, again to no avail. (EDIT: i have also tried throwing lerp out of the window and just adding the phase delta each sample, again no dice).

So, my question is, any ideas on why this weird pitch shift is happening? In practicality it isn't a huge issue, the system was only ever intended for short notes to be stacked together for old video game style music, or a tone that would likely change frequency often. But I'd feel more comfortable knowing that the wave generation is accurate and wasn't accumulating some error somewhere sending it way of track.

  • 1
    $\begingroup$ I would be more complete and show all of your code. A plot of the data showing where the changes occur could help. Also I would be more clear that "lerping" is an abbreviation for "linearly interpolating". Why do you feel like you need to interpolate the phase accumulator? An advantage of using an NCO-based structure is that you shouldn't need to interpolate, especially if you have full-precision transcendental functions like you've shown. The phase resolution is related to the precision in the accumulator numeric type. $\endgroup$ – Jason R Mar 27 '12 at 15:14
  • $\begingroup$ The lerping was in place to smooth the change as the delta changed, when the frequency is set the delta can change considerably, but that creates a sound which changes too harshly. granted it would probably be better practice to lerp the delta not the accumulator, that's my bad. But thanks for the input. $\endgroup$ – Fat-Wednesday Mar 27 '12 at 15:31

I suspect that the accumulator value is growing very large, which causes the float's resolution to degrade. To avoid this you need to occasionally reduce the accumulator to manageable levels. One way to do that is to subtract by 2*pi whenever you exceed 2*pi.

  • 1
    $\begingroup$ Wow, it seems so obvious now. I had thought to check if it was a problem with the float wrapping around when it got too big, but I hadn't thought to consider the loss of precision as it got larger. This seems to have done the trick. Thanks very much for your help. $\endgroup$ – Fat-Wednesday Mar 27 '12 at 15:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.