FL Studio likes to change buffer sizes, messes up DSP filters


#1

Hello!

So as I finally thought I managed to create a proper, basic LP-filter functionality with the dsp-module, there comes the FL Studio and crushes my dreams. So, pretty much all DAW’s seem to keep buffersize constant during playback, but not so with FL Studio. It has variable buffersize by default with plugins and that in turn makes glitches in my filter, which assumes that the buffer size stays the same during playback. It allows buffersize to be changed… but if it happens during the playback, there’ll be a glitch since the filter needs preparing and resetting each time buffersize is changed.

Any ideas how to overcome this? How do I change the IIR-filter buffersize without resetting it’s state and “last known sample” in order to prevent the glitches that happen? This feels like totally off-standard behaviour but Image Line justifies this by telling that the VST standard “makes it possible to change buffersize whenever wanted, so make your plugin work with it.” :frowning:


#2

Unfortunately that’s just the reality. The block size provided in prepare() is only the maximum guaranteed block size to make sure you know ahead of time the most number of samples you’ll be expected to work with. It’s not just VST either, I know AU does this, and I know many hosts other than FL use smaller block sizes in order to smooth automation.

You’ll need to make your DSP work with variable block sizes. A technique I use when I have to have a certain block size (say, for doing FFT work) is to keep a rolling buffer (basically a ringbuffer that overwrites the head as data is added to the tail) at the buffer size I want and just add data to it as it comes in at whatever block size/rate it comes in, and process as needed.

I can’t think of a single type of HP/LP filter that requires a fixed block size, since they all just generally work with a variable number of coefficients and only care about the sample rate (which will NOT change without a prepare() call). Willing to share any code?


#3

Ok! So, my AudioProcessor’s processBlock checks each time if the buffersize has changed and sends a call to synthesizervoice’s LP-filters to prepare and reset. So it’s quite obvious it’s going to produce glitches if the buffer size varies during playback, since the reset happens. This is because PrepareToPlay-method doesn’t get called on Logic X before each playback start, so I had to include the check on the processBlock, otherwise there’ll be glitches on Logic too hah.

I can share some code but I’m not sure it’s going to help.

I’m not 100% sure even how the LP-filter works in JUCE dsp-module, since I’m afraid I’m not a pro in signal processing. I had a “feeling” that it needs to store the last known sample in the last buffer in order to calculate the next buffer’s first sample’s filtering, am I right? So If I reset or prepare the filter, it will lose that information, OR, it never registers the correct sample in the first place if the buffer ends up being smaller than anticipated (never reaches the last sample of the real buffer size that it then stores) ?? How do I overcome this? Write the buffer with the last known sample to the end everytime buffer gets written? That’ll be propably a bit too tough on the CPU since there’s quite many synthesiser voice objects in the sampler I’m developing, and those would be doing that thing a lot, even multiple times during a single buffer because how the juce synthesizer works in conjunction with midibuffers (each midimessage splits the buffer and each time I’ll have to process the part of the buffer and not knowing when it’ll end in reality, so I’d have to write the buffer end each time or something…) :S


#4

You have to accomodate variable buffer size. The obvious reason is that you can have a parameter change at any time (automation). So you have to be able to process 2 samples, then 1000, then 1…


#5

Ok yeah, I got it. :slight_smile:

I wonder, how to do it with JUCE dsp-module since there’s not much else than process, prepare, reset and state methods/variables present, and why, if, it’s not already taken into account with juce library if it’s so common behaviour for DAW’s? :thinking:


#6

No, you only have to set the maximum blocksize at the beginning (never in the processBlock class itself). If dsp process() methods can’t handle variable blocksizes, than they are problably wrong. If you call reset, the current audio-state resets, which may result in clicks in the audio stream with LP Filters.


#7

Thank you, I’ll check this option out! :slight_smile: