Getting click when looping audio with xfade

I've implemented looping of audio samples with a cross fade of 22000 (somewhat arbitrarily chosen) samples. In doing this on a non-pitch shifted sample (so interpolation doesn't need to be accounted for for both parts of the sample), I can hear the cross-fading--it's very smooth, but every single time the loop starts over (after the cross fade ends), there is a tiny click, and I don't know why.

Basically, when the sample position reaches the loopEnd value minus the xfade_length, the crossfading begins. When the sample position reaches the loopEnd value, samplePosition is reassigned to loopStart + xfade_length. I even went so far as to check the actual output data to make sure things look correct:

Sample number of the loop start + xfade sample length: 30946 (when crossfading is over, samplePosition is reset to this number).

Output of the last value in the buffer before looping the sample: -0.00536969

Actual value of the raw 30945th sample (start of loop + xfade length - 1 -- i.e. the last sample before the loop starts over): -0.00537109

Why am I getting a click when the loop starts over when the actual output of the last sample of the crossfade is nearly identical to the actual raw data? The only reason the output of the last sample before the loop is SLIGHTLY different from the actual sample value of the 30945th sample is due to the VERY slight xfade that is still present on the last iteration of the crossfade. Surely the click is not due to this tiny discrepency in data.

Is this some sort of high frequency interference?




I don't think that it is a magic DSP issue like high frequency interference, but rather something profane like an off by one error when wrapping the loop. Try to disable the crossfade and check if the problem remains

I am going to implement looping in the next days myself, and will update my streaming sampler class, maybe it could be of some help for you.

Let me know if you run into the same issue yourself. I assumed, like you suggested, that it was an off-by-one error, so I was very dilligent in examining that possibility, but to no avail. There must be something that I'm still missing. If I figure it out I'll post the answer here.

And no, i didn't try it without the cross fade, because I would expect high frequency interference if the start and end points aren't snapped to a zero crossing.

I solved the problem. Although it wasn't an off-by-one error, it was rather profane:

            renderNextBlock(input, numSamples){
                for (int i=0; i<numSamples; i++){
                    if (inXFadeRange()){
                        //do crossfade
                    if (atLoopEndPoint()){
                        samplePosition = loopStart + xfade_length;
                        return; //don't return to fix the problem


My loop ranges and xfade were correct, but I was incorrect to return from the function at the loopEnd. This means that the rest of the audio buffer for that block are not going to be filled with data, causing noise. Sorry for posting topics like these. For some reason, I spend forever solving something stupid like this, and then once I post about it here, it accelerates me finding the answer -_-


For some reason, I spend forever solving something stupid like this, and then once I post about it here, it accelerates me finding the answer -_-

It's called "Rubber Duck Debugging"