I’m trying to use GenericInterpolator
(LinearInterpolator
) to resample and correct the speed of a sample. I started with the processBlock()
code from the Sampler tutorial, and then tried to add in the interpolator. It plays back correctly if the speed is 1 (i.e. if the sample and system bitrates match), but if the speed is less that 1, it comes out garbled. I’m really bad at this low level DSP code and it would be great if someone could help.
Here’s what I have so far:
void SingleSample::processBlock(juce::AudioBuffer<float>& outputBuffer)
{
if (!playing || sampleBuffer->getNumSamples() == 0) return;
auto numInputChannels = sampleBuffer->getNumChannels();
auto numOutputChannels = outputBuffer.getNumChannels();
auto outputSamplesRemaining = outputBuffer.getNumSamples();
auto outputSamplesOffset = 0;
const auto speed = thisSampleRate / systemSampleRate;
while (outputSamplesRemaining > 0)
{
auto bufferSamplesRemaining = sampleBuffer->getNumSamples() - position;
auto samplesThisTime = juce::jmin(outputSamplesRemaining, bufferSamplesRemaining);
for (auto channel = 0; channel < numOutputChannels; ++channel)
{
const auto chan = channel % numInputChannels;
auto interpolator = (*interpolators)[chan];
interpolator->process(speed, sampleBuffer->getReadPointer(chan, position),
resampleBuffer->getWritePointer(chan), samplesThisTime, bufferSamplesRemaining, 0);
outputBuffer.addFrom(channel,
outputSamplesOffset,
*resampleBuffer,
chan,
0,
samplesThisTime);
}
outputSamplesRemaining -= samplesThisTime;
outputSamplesOffset += samplesThisTime;
position += samplesThisTime;
if (position == sampleBuffer->getNumSamples())
{
position = 0;
playing = false;
}
}
}
A few notes:
–resampleBuffer
is initialized to have the default buffer size. My idea is that it will resample sampleBuffer
to the right speed, and then copy that across to outputBuffer
in the same pass. But I’m not really sure if this is correct or not.
–Someone might tell me that I don’t actually need GenericInterpolator
if all I’m doing is correcting for the sample’s bitrate. I’d be interested to hear this, but in my case I think I actually do want to use it, since I’m going to have more dynamic options for playback speed once I’ve gotten this basic version working.
–For now, let’s assume that I’ve got all threading issues solved (i.e. that’s not what I’m trying to work through here).