FIR-LADSPA: A LADSPA plugin for FIR filtering
- By CharlieLaub
- PC Based
- 71 Replies
Several weeks ago I started to write code for implementing FIR filters under LADSPA, and mentioned it HERE.
LADSPA plugins were never intended to do intensive processing, or to have highly variable CPU loads between calls to the plugin by the LADSPA host. This means that implementing an FIR convolution inside the plugin itself is probably not advisable, or even possible. So I have taken a different approach:
The FIR convolution is performed in a separate process that is entirely independent of, and is running asynchronously from, the LADSPA plugin and host. I call it an "FIR engine". This separate process is launched using an operating system call as part of the LADSPA plugin setup process. Parameters and other info are passed from the plugin to the FIR engine using a "control" FIFO, and other FIFOs are used to pass unprocessed and processed data.
Performing the FIR convolution in a separate process has several advantages. The LADSPA plugin, once up and running, only needs to put/get data into/out of the FIFOs and this keeps it very computationally lightweight. The FIR convolution can only be performed when the desired length of data has been obtained via LADSPA. Because of the real-time nature of the audio processing, this takes Ndata/sample_rate seconds. For example, at 48kHz if you process 16384 data points per call it will require the FIR engine to collect incoming data for about 0.35 seconds before it can perform one convolution. During that time, the LADSPA plugin might have been called 16 times (given a typical frame of 1024 samples). The speed requirement of the convolution can therefore be as slow as 0.3 seconds or so, by which time the next 16384 samples have been collected and need to be processed. This can be helpful when using low powered Linux hardware such as a Raspberry Pi. Additionally, the OS is free to schedule the FIR engine process around other processes, and there is no need to run it at a high priority, etc.
As part of the set of of the plugin and FIR engine, a uniquely named directory is created in the tmpfs (files in memory) that comes with all Linuxes. The FIR engine collects and writes to this directory a file that lists the mean and longest "cycle time", that is the time to process the data and return it to the LADSPA plugin. The cycle time latency can be obtained in a test run for a given platform and FIR filter set, and then this is supplied to the LADSPA plugin as a parameter during normal use. This latency timing info is used to set up internal buffers so that underruns are prevented.
Because the FIR engine is a separate and independent process and because some LADSPA hosts do not correctly tear down the plugin (by calling deactivate, etc.) I have written the FIR engine to self-terminate and cleanup after itself. This includes deleting the tmpfs directory in which it was operating, and the FIFOs. Once this process is completed there is no sign that the FIR engine was ever there. A pair of error logs are written to the tmpfs and not deleted, however, on reboot the tmpfs filespace is wiped clean. The user can manually delete the error log files anytime. Since these only are used to record fatal error messages, it is not likely they will grow to any appreciable size.
I am currently coding up the FIR convolution using FFTW but have everything else functioning well using a dummy convolution function that simply passes input to output in the FIR engine. I hope to get a test version fully up and running in a week or so and will post updates as I have them.
LADSPA plugins were never intended to do intensive processing, or to have highly variable CPU loads between calls to the plugin by the LADSPA host. This means that implementing an FIR convolution inside the plugin itself is probably not advisable, or even possible. So I have taken a different approach:
The FIR convolution is performed in a separate process that is entirely independent of, and is running asynchronously from, the LADSPA plugin and host. I call it an "FIR engine". This separate process is launched using an operating system call as part of the LADSPA plugin setup process. Parameters and other info are passed from the plugin to the FIR engine using a "control" FIFO, and other FIFOs are used to pass unprocessed and processed data.
Performing the FIR convolution in a separate process has several advantages. The LADSPA plugin, once up and running, only needs to put/get data into/out of the FIFOs and this keeps it very computationally lightweight. The FIR convolution can only be performed when the desired length of data has been obtained via LADSPA. Because of the real-time nature of the audio processing, this takes Ndata/sample_rate seconds. For example, at 48kHz if you process 16384 data points per call it will require the FIR engine to collect incoming data for about 0.35 seconds before it can perform one convolution. During that time, the LADSPA plugin might have been called 16 times (given a typical frame of 1024 samples). The speed requirement of the convolution can therefore be as slow as 0.3 seconds or so, by which time the next 16384 samples have been collected and need to be processed. This can be helpful when using low powered Linux hardware such as a Raspberry Pi. Additionally, the OS is free to schedule the FIR engine process around other processes, and there is no need to run it at a high priority, etc.
As part of the set of of the plugin and FIR engine, a uniquely named directory is created in the tmpfs (files in memory) that comes with all Linuxes. The FIR engine collects and writes to this directory a file that lists the mean and longest "cycle time", that is the time to process the data and return it to the LADSPA plugin. The cycle time latency can be obtained in a test run for a given platform and FIR filter set, and then this is supplied to the LADSPA plugin as a parameter during normal use. This latency timing info is used to set up internal buffers so that underruns are prevented.
Because the FIR engine is a separate and independent process and because some LADSPA hosts do not correctly tear down the plugin (by calling deactivate, etc.) I have written the FIR engine to self-terminate and cleanup after itself. This includes deleting the tmpfs directory in which it was operating, and the FIFOs. Once this process is completed there is no sign that the FIR engine was ever there. A pair of error logs are written to the tmpfs and not deleted, however, on reboot the tmpfs filespace is wiped clean. The user can manually delete the error log files anytime. Since these only are used to record fatal error messages, it is not likely they will grow to any appreciable size.
I am currently coding up the FIR convolution using FFTW but have everything else functioning well using a dummy convolution function that simply passes input to output in the FIR engine. I hope to get a test version fully up and running in a week or so and will post updates as I have them.