Resampling whole buffer vs small blocks

I have a situation where I’m streaming audio from one plugin to another which is in a different sample rate. If I wait for the whole sample to be sent and then I convert the buffer to the receivers sample rate, this works great and there are no issues.

However, I’d like for the receiver to be able to listen as the sample comes in. I’m sending “chunks” of the buffer at a time, so we’re resampling each chunk as it comes in and appending to the final buffer…

… and it doesn’t “quite” work, there’s some tiny crackling happening in the audio. I’m not exactly sure what’s happening but my theory is that the method of resampling that I’m using depends on the whole sound being there and it’s not made for converting chunks and putting them back together.

Does anyone have any ideas? Are there other ways of doing this? I’m really not an expect in this matter.

Here is the resampling code:

void SampleManager::ResampleBuffer(double p_dblRatio, AudioSampleBuffer& p_roBuffer, int p_iChannels)
{
	AudioSampleBuffer temp;
	temp.clear();
	temp.setSize(p_iChannels, (int)(p_roBuffer.getNumSamples() / p_dblRatio));

	const float** inputs = p_roBuffer.getArrayOfReadPointers();
	float** outputs = temp.getArrayOfWritePointers();
	for (int i = 0; i < temp.getNumChannels(); i++)
	{
		std::unique_ptr<LagrangeInterpolator> resampler(new LagrangeInterpolator());
		resampler->reset();
		resampler->process(p_dblRatio, inputs[i], outputs[i], temp.getNumSamples());
	}

	p_roBuffer = temp;
}

I think the ‘resampler’ needs to be different ones for each channel, setup in the constructor, or preparePlay, or anywhere it’s only called once. You appear to be creating new interpolators for every chunk!
And only call reset when you change stream, or enter a prepareToPlay. Think of each chunk as part of a continuous stream, calling reset will interrupt the current state, and introduce crackles.

1 Like

Hey, this worked!! Thanks a million for the tips!