Difference between revisions of "Hacker Guide/Audio Filters"

From VideoLAN Wiki
Jump to navigation Jump to search
m (rel2abs)
(C/e)
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
=Overview=
+
{{Back to|Hacker Guide}}
* [[{{#rel2abs:..}}|Back to Hacker Guide]]
 
  
=Writing an audio filter=
+
==Writing an audio filter==
  
==Module descriptor==
+
===Module descriptor===
 +
<syntaxhighlight lang="c">
 
  static int  Open    ( [vlc_object_t] *p_this );
 
  static int  Open    ( [vlc_object_t] *p_this );
 
  static void Close    ( [vlc_object_t] *p_this );
 
  static void Close    ( [vlc_object_t] *p_this );
Line 18: Line 18:
 
     set_callbacks( Open, Close )
 
     set_callbacks( Open, Close )
 
  vlc_module_end()
 
  vlc_module_end()
 +
</syntaxhighlight>
  
==I/O Buffers==
+
===I/O Buffers===
Data comes in and out the plugin in an [http://www.videolan.org/developers/vlc/doc/doxygen/html/structaout__buffer__t.html aout_buffer_t], one sample at a time, and in each sample, one block by channel.
+
Data comes in and out the plugin in an [https://www.videolan.org/developers/vlc/doc/doxygen/html/structaout__buffer__t.html aout_buffer_t], one sample at a time, and in each sample, one block by channel.
  
{|border="1" cellpadding="5" cellspacing="0" align="center"
+
{| class="wikitable center"
 
|-
 
|-
|data stream
+
! scope="col" | data stream
 
| ch 1
 
| ch 1
 
| ch 2
 
| ch 2
Line 31: Line 32:
 
| ch 1
 
| ch 1
 
| ch 2
 
| ch 2
| ...
+
| &hellip;
 
|-
 
|-
|
+
! scope="col" | samples
 
| colspan="2" | Sample 1
 
| colspan="2" | Sample 1
 
| colspan="2" | Sample 2
 
| colspan="2" | Sample 2
 
| colspan="2" | Sample 3
 
| colspan="2" | Sample 3
| ...
+
| &hellip;
 
|}
 
|}
  
  
  
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).
+
An audio filter module is constituted of a constructor, a destructor, and a <code>p_filter->pf_do_work</code> function. The constructor is passed a p_filter structure, and it returns 0 if it is able to do the whole transformation between <code>p_filter->input</code> and <code>p_filter->output</code>. 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).
  
==Note==
+
===Note===
  
 
Audio filters can be of three types :
 
Audio filters can be of three types :
  
*Converters : change i_format (for instance from float32 to s16).
+
* Converters : change <code>i_format</code> (for instance from float32 to s16).
*Resamplers : change i_rate (for instance from 48 kHz to 44.1 kHz).
+
* Resamplers : change <code>i_rate</code> (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).  
+
* Channel mixers : change <code>i_physical_channels</code>/<code>i_original_channels</code> (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.
+
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 constructor must also set <code>p_filter->b_in_place</code>. If it's <code>0</code>, the aout core will allocate a new buffer for the output. If it's <code>1</code>, 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 <code>float32->s16</code>), but most filters will want <code>b_in_place = 0</code>. The filter can allocate private data in <code>p_filter->p_sys</code>. 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).
+
The <code>p_filter->pf_do_work</code> gets an input and an output buffer as arguments, and process them. At the end of the processing, do not forget to set <code>p_out_buf->i_nb_samples</code> and <code>p_out_buf->i_nb_bytes</code>, since they aren't inited by the aout core (their values can change between input and output and it's not quite predictable).
  
  
=Writing an audio mixer=
+
==Writing an audio mixer==
  
Writing an audio mixer is very similar to writing an audio filter. The only difference is that you have to deal with the input buffers yourself, and request for new buffers when you need to. Between two calls to pf_do_work, the position in the buffer is remembered in p_input->p_first_byte_to_mix (it isn't always the start of the buffer, since input and output buffers can be of different length). It is your job to set this pointer at the end of pf_do_work.
+
Writing an audio mixer is very similar to writing an audio filter. The only difference is that you have to deal with the input buffers yourself, and request for new buffers when you need to. Between two calls to <code>pf_do_work</code>, the position in the buffer is remembered in <code>p_input->p_first_byte_to_mix</code> (it isn't always the start of the buffer, since input and output buffers can be of different length). It is your job to set this pointer at the end of <code>pf_do_work</code>.
  
 
For more details, please have a look at the float32 mixer. It's much more understandable than lines of documentation.
 
For more details, please have a look at the float32 mixer. It's much more understandable than lines of documentation.
  
{{Hacker_Guide}}
+
{{Hacker Guide}}

Latest revision as of 09:13, 17 April 2019

← Back to Hacker Guide

Writing an audio filter

Module descriptor

 static int  Open     ( [vlc_object_t] *p_this );
 static void Close    ( [vlc_object_t] *p_this );
 static block_t *DoWork (filter_t *filter, block_t *block)

 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()

I/O Buffers

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
samples 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).

Note

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 predictable).


Writing an audio mixer

Writing an audio mixer is very similar to writing an audio filter. The only difference is that you have to deal with the input buffers yourself, and request for new buffers when you need to. Between two calls to pf_do_work, the position in the buffer is remembered in p_input->p_first_byte_to_mix (it isn't always the start of the buffer, since input and output buffers can be of different length). It is your job to set this pointer at the end of pf_do_work.

For more details, please have a look at the float32 mixer. It's much more understandable than lines of documentation.

This page is part of official VLC media player Documentation (User GuideStreaming HowToHacker GuideModules)
Please read the Documentation Editing Guidelines before you edit the documentation
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.