Hacker Guide/Audio Filters
Writing an audio filter
static int Open ( vlc_object_t *p_this ); static void Close ( vlc_object_t *p_this ); static void DoWork ( aout_instance_t *p_aout, aout_filter_t *p_filter, aout_buffer_t *p_in_buf, aout_buffer_t *p_out_buf ); vlc_module_begin(); set_description( N_("audio filter x") ); set_shortname( N_("audio filter x") ); set_category( CAT_AUDIO ); set_subcategory( SUBCAT_AUDIO_AFILTER ); add_shortcut( "afx" ); set_capability( "audio filter", 0 ); set_callbacks( Open, Close ); vlc_module_end();
Data comes in and out the plugin in an aout_buffer_t, one sample at a time, and in each sample, one block by channel.
|data stream||ch 1||ch 2||ch 1||ch 2||ch 1||ch 2||...|
|Sample 1||Sample 2||Sample 3||...|
An audio filter module is constituted of a constructor, a destructor, and a p_filter->pf_do_work function. The constructor is passed a p_filter structure, and it returns 0 if it is able to do the whole transformation between p_filter->input and p_filter->output. If you can do only part of the transformation, say you can't do it (if the aout core doesn't find a fitting filter, it will split the transformation and ask you again).
Audio filters can be of three types :
- Converters : change i_format (for instance from float32 to s16).
- Resamplers : change i_rate (for instance from 48 kHz to 44.1 kHz).
- Channel mixers : change i_physical_channels/i_original_channels (for instance from 5.1 to stereo).
Audio filters can also combine any of these types. For instance you can have an audio filter which transforms A/52 5.1 to float32 stereo.
The constructor must also set p_filter->b_in_place. If it's 0, the aout core will allocate a new buffer for the output. If it's 1, when you write a byte in the output buffer, it destroys the same byte in the input buffer (they share the same memory area). Some filters can work in place because they just do a linear transformation (like float32->s16), but most filters will want b_in_place = 0. The filter can allocate private data in p_filter->p_sys. Do not forget to deallocate it in the destructor.
The p_filter->pf_do_work gets an input and an output buffer as arguments, and process them. At the end of the processing, do not forget to set p_out_buf->i_nb_samples and p_out_buf->i_nb_bytes, since they aren't inited by the aout core (their values can change between input and output and it's not quite predictible).