Hi all,
Sorry, long post coming up. I'm implementing some up and down resampling in a VST plugin, and I've noticed an issue with my results using ResamplingAudioSource. I can't be sure as to whether to put it down as an incorrect use of the class, or an inherent problem in the resampling algorithm. I'll try to describe what's happening below and hopefully somebody can shed some light; alternatively if anyone has code to share for a working implementation of ResamplingAudioSource, that would be amazing.
The problem is a 1/frequency magnitude decay. In this test i'm taking white noise, upsampling at a factor of 1/4, downsampling at a factor of 4, and recording the output. See below for a before/after FFT spectra:
Otherwise there's no audible discontiuities or distortions, just this low pass filtering effect.
So here's how I set the resamplers up (it's a multitrack plugin, but i'm just testing on 1 track (2 channels)):
// Set resampling ratios for (int trk = 0; trk < _numTracks; ++trk) { _resamplers[trk*2] ->setResamplingRatio(1.0f/_resamplingRatio); // upsampling _resamplers[trk*2+1]->setResamplingRatio(_resamplingRatio); // downsampling _resamplers[trk*2]->prepareToPlay(_numSamples, _sampleRate); _resamplers[trk*2+1]->prepareToPlay(_upNumSamples, _upSampleRate); } // Resampling buffer output info _upSampledBufferInfo.buffer = &_upSampledOriginalBuffer; _upSampledBufferInfo.startSample = 0; _upSampledBufferInfo.numSamples = _upNumSamples; _downSampledBufferInfo.buffer = &_currentTrackBuffer; _downSampledBufferInfo.startSample = 0; _downSampledBufferInfo.numSamples = _numSamples;
I wrote a VST audio source to act as the input to the resamplers:
//----------------------------------------------------------------------------- // void VSTAudioSource::SetDataPtrs(float ** audioData, int numChannels) { _data.allocate(numChannels,false); for (int i = 0; i < numChannels; ++i) { _data[i] = audioData[i]; } _startSample = 0; } //----------------------------------------------------------------------------- // void VSTAudioSource::prepareToPlay(int samplesPerBlockExpected, double sampleRate) { _numSamples = samplesPerBlockExpected; } //----------------------------------------------------------------------------- // void VSTAudioSource::releaseResources() { _numSamples = 0; _startSample = 0; } //----------------------------------------------------------------------------- // void VSTAudioSource::getNextAudioBlock(const AudioSourceChannelInfo& bufferToFill) { // Fill with data from VST buffer for (int sample = 0; sample < bufferToFill.numSamples; ++sample) { for (int chnl = 0; chnl < bufferToFill.buffer->getNumChannels(); ++chnl) { *bufferToFill.buffer->getSampleData (chnl,bufferToFill.startSample + sample) = _data[chnl][_startSample]; } _startSample = (_startSample + 1) % _numSamples; } }
Then in processBlock():
// UPSAMPLING _vstAudioSourceUp.SetDataPtrs(_origDataPtr,2); _resamplers[trk*2]->getNextAudioBlock(_upSampledBufferInfo); // DOWNSAMPLING _vstAudioSourceDown.SetDataPtrs(_upSampledSummedBuffer.getArrayOfChannels(),2); _resamplers[trk*2+1]->getNextAudioBlock(_downSampledBufferInfo);
Think that's it, all thoughts appreciated. Many thanks!
Stuart