Resampling and filtering glitches

Hi there !

I’m experimenting audio glitches when performing filtering (State Variable Filter) on audioTransportSource.

I noticed that when I use transport.setSource() the filtering works perfectly.

However, when I use transport.setSource() by adding an input sample rate corresponding to the file I’m playing back, problems arrive !
(I have to use this resampling process to allow any audio file as input, I don’t want its playback speed to change… If anyone has another way to avoid this…)

There might be a problem between sample rates adjustments. I tried to specify in the Process Spec the playback sample rate (normal) but also the input file sample rate to see if anything change. No change.

Let’s give some details …

As AudioSource, I implemented my own class “MonoSource” which inherits from PositionableAudioSource, and has members :

  • AudioFormatReaderSource : file audio Source
  • AudioTransportSource : the one to load and playback the audioFile
  • AudioSourcePlayer : whose source is set as the AudioTransportSource, and is called by the AudioDeviceManager in the addAudioCallback() function.

(The reason why I wrote this class is to manage multiple output channels easily)

File load :

auto* reader = formatManager.createReaderFor(filesArray[i]); // create reader for the audioFile
if(reader != nullptr){
                audioSource_Array.add(new MonoSource()); // create new playback AudioSource
                auto* t = audioSource_Array.getLast();

                deviceManager.addAudioCallback(&t->player); // add the callback to the device manager
                
                t->track.reset(new AudioFormatReaderSource(reader,true));
                t->transport.setSource(t, 0, nullptr, reader->sampleRate, 2);  
                t->transport.addChangeListener(this); 
                
                DBG("TRACK ADDED : " + tracksArray[i]);
            }

Audio Source :

void prepareToPlay (int samplesPerBlockExpected, double sampleRateToUse) override
    {
        bufferSize = samplesPerBlockExpected;
        sampleRate = sampleRateToUse;
        
        dsp::ProcessSpec spec;
        spec.sampleRate = sampleRateToUse;
        spec.maximumBlockSize = samplesPerBlockExpected;
        spec.numChannels = 2;

        filter.prepare(spec);
        
        //initial parameters
        filter.setType(dsp::StateVariableTPTFilterType::highpass);
        filter.setCutoffFrequency(100.0f);
        filter.setResonance( (float) 1 / sqrt(2));
    }
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) override
    {
        if (!transport.isPlaying()){bufferToFill.clearActiveBufferRegion();}
        else{
        
        track->getNextAudioBlock(bufferToFill);
        
        // ...
            
            // Filtering if set
            if (isFiltering)
            {
                dsp::AudioBlock<float> block(*bufferToFill.buffer);
                filter.process(dsp::ProcessContextReplacing<float> (block));
            }
        }
        
    }

Now I hope there are enough details for you to understand. Don’t hesitate to ask questions if not !

Thank you !

Hello!

Not sure to understand everything that is going on in your code since the object types are not standard. Have you tried to do the filter processing in getNextAudioBlock before the call to track->getNextAudioBlock(bufferToFill);? With the filter prepare function using the original file sample rate instead of the one provided in prepareToPlay?

Thanks Ivan for your help !
I just did what you proposed and it does exactly the same.

Maybe I could implement this using standard objects, however I’m not sure how to configure easily output channels, and I need it because I’m using multichannel setup and I load multiple tracks, each one playing through specific output channel(s).

I will investigate the use of ChannelRemappingAudioSource.