Is there a "simple" way to resample an AudioSampleBuffer? I tried playing with ResamplingAudioSource but I couldn't really figure out how to use it for a fixed buffer (not live).
What should I do or where should I look?
Is there a "simple" way to resample an AudioSampleBuffer? I tried playing with ResamplingAudioSource but I couldn't really figure out how to use it for a fixed buffer (not live).
What should I do or where should I look?
There's also the LagrangeInterpolator, which is a bit more low-level, if that's what you're looking for?
Thanks for the reply. I basically need to load a IR sample in a AudioSampleBuffer and stretch it according to the host samplerate and a stretch factor.
I tried the LagrangeInterpolator but there's something wrong with my implementation as it doesn't do exactly what it should (or at least what I think it should do).
When then I use the new buffer for the convolution if the stretch is < 1 it looks like the sample is slower (while it should be faster) and usually when it's > 1 i get strange repetitions only on left channel (and sometimes a huge click/pop and no audio anymore).
I am probably overthinking here, but I just need to change the speed of this AudioSampleBuffer according to the host samplerate and a stretch factor.
*bump*
Any help with this?
Here’s my interpretation of how to use the LagrangeInterpolator, but unfortunately it crashes with an exception on the second channel, any idea why? I really need this to work.
waveBuffer (AudioSampleBuffer) is the destination buffer that’s in the class…
void Buffer::fillBuffer(AudioFormatReader *reader, double currentSampleRate)
{
AudioSampleBuffer temp;
waveBuffer.clear();
temp.clear();
double ratio = currentSampleRate / reader->sampleRate;
temp.setSize((int)reader->numChannels, (int)reader->lengthInSamples);
waveBuffer.setSize((int)reader->numChannels, (int)((double)reader->lengthInSamples * ratio));
reader->read(&temp, 0, (int)reader->lengthInSamples, 0, true, true);
ScopedPointer<LagrangeInterpolator> resampler = new LagrangeInterpolator();
const float **inputs = temp.getArrayOfReadPointers();
float **outputs = waveBuffer.getArrayOfWritePointers();
for (int c = 0; c < waveBuffer.getNumChannels(); c++)
{
resampler->reset();
resampler->process(ratio, inputs[c], outputs[c], waveBuffer.getNumSamples());
}
}
OK I’ve discovered the ratio was 1/ the correct value but it still crashes when down-sampling, it seems to work fine when up-sampling. Is the LagrangeAlgorithm code broken?
The ‘in’ gets unreadable here:-
else
{
for (int i = numOut; --i >= 0;)
{
while (pos < actualRatio)
{
pushInterpolationSample (lastInputSamples, *in++);
pos += 1.0;
}
pos -= actualRatio;
*out++ = InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
}
}
OK I’ve got it now, there is no filtering in the Lagrange code but ho-hum, here’s the new version:
*Note I now divide the incoming length by the ratio.
AudioSampleBuffer temp;
sofar = 0;
waveBuffer.clear();
temp.clear();
double ratio = reader->sampleRate / hostSampleRate;
temp.setSize((int)reader->numChannels, (int)reader->lengthInSamples);
waveBuffer.setSize((int)reader->numChannels, (int)(((double)reader->lengthInSamples) / ratio));
reader->read(&temp, 0, (int)reader->lengthInSamples, 0, true, true);
ScopedPointer<LagrangeInterpolator> resampler = new LagrangeInterpolator();
const float **inputs = temp.getArrayOfReadPointers();
float **outputs = waveBuffer.getArrayOfWritePointers();
for (int c = 0; c < waveBuffer.getNumChannels(); c++)
{
resampler->reset();
resampler->process(ratio, inputs[c], outputs[c], waveBuffer.getNumSamples());
}
Just saw this today. The code works great, BUT, for each channel you need its own Lagrange object.
if you're resampling multiple channels, make sure each one uses its own object.
Yes of course.