+#include <libvlc.h>
+
+block_t *aout_FilterBufferNew( filter_t *p_filter, int size )
+{
+ (void) p_filter;
+ return block_Alloc( size );
+}
+
+/*****************************************************************************
+ * FindFilter: find an audio filter for a specific transformation
+ *****************************************************************************/
+static filter_t * FindFilter( aout_instance_t * p_aout,
+ const audio_sample_format_t * p_input_format,
+ const audio_sample_format_t * p_output_format )
+{
+ static const char typename[] = "audio filter";
+ filter_t * p_filter;
+
+ p_filter = vlc_custom_create( p_aout, sizeof(*p_filter),
+ VLC_OBJECT_GENERIC, typename );
+
+ if ( p_filter == NULL ) return NULL;
+ vlc_object_attach( p_filter, p_aout );
+
+ memcpy( &p_filter->fmt_in.audio, p_input_format,
+ sizeof(audio_sample_format_t) );
+ p_filter->fmt_in.i_codec = p_input_format->i_format;
+ memcpy( &p_filter->fmt_out.audio, p_output_format,
+ sizeof(audio_sample_format_t) );
+ p_filter->fmt_out.i_codec = p_output_format->i_format;
+ p_filter->pf_audio_buffer_new = aout_FilterBufferNew;
+
+ p_filter->p_module = module_need( p_filter, "audio filter", NULL, false );
+ if ( p_filter->p_module == NULL )
+ {
+ vlc_object_detach( p_filter );
+ vlc_object_release( p_filter );
+ return NULL;
+ }
+
+ assert( p_filter->pf_audio_filter );
+ return p_filter;
+}
+
+/*****************************************************************************
+ * SplitConversion: split a conversion in two parts
+ *****************************************************************************
+ * Returns the number of conversions required by the first part - 0 if only
+ * one conversion was asked.
+ * Beware : p_output_format can be modified during this function if the
+ * developer passed SplitConversion( toto, titi, titi, ... ). That is legal.
+ * SplitConversion( toto, titi, toto, ... ) isn't.
+ *****************************************************************************/
+static int SplitConversion( const audio_sample_format_t * p_input_format,
+ const audio_sample_format_t * p_output_format,
+ audio_sample_format_t * p_middle_format )
+{
+ bool b_format =
+ (p_input_format->i_format != p_output_format->i_format);
+ bool b_rate = (p_input_format->i_rate != p_output_format->i_rate);
+ bool b_channels =
+ (p_input_format->i_physical_channels
+ != p_output_format->i_physical_channels)
+ || (p_input_format->i_original_channels
+ != p_output_format->i_original_channels);
+ int i_nb_conversions = b_format + b_rate + b_channels;
+
+ if ( i_nb_conversions <= 1 ) return 0;
+
+ memcpy( p_middle_format, p_output_format, sizeof(audio_sample_format_t) );
+
+ if ( i_nb_conversions == 2 )
+ {
+ if ( !b_format || !b_channels )
+ {
+ p_middle_format->i_rate = p_input_format->i_rate;
+ aout_FormatPrepare( p_middle_format );
+ return 1;
+ }
+
+ /* !b_rate */
+ p_middle_format->i_physical_channels
+ = p_input_format->i_physical_channels;
+ p_middle_format->i_original_channels
+ = p_input_format->i_original_channels;
+ aout_FormatPrepare( p_middle_format );
+ return 1;
+ }
+
+ /* i_nb_conversion == 3 */
+ p_middle_format->i_rate = p_input_format->i_rate;
+ aout_FormatPrepare( p_middle_format );
+ return 2;
+}
+
+static void ReleaseFilter( filter_t * p_filter )
+{
+ module_unneed( p_filter, p_filter->p_module );
+ vlc_object_detach( p_filter );
+ vlc_object_release( p_filter );
+}