1 /*****************************************************************************
2 * filters.c : audio output filters management
3 *****************************************************************************
4 * Copyright (C) 2002-2007 VLC authors and VideoLAN
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_dialog.h>
35 #include <vlc_modules.h>
38 #include <vlc_filter.h>
40 #include "aout_internal.h"
43 /*****************************************************************************
44 * FindFilter: find an audio filter for a specific transformation
45 *****************************************************************************/
46 static filter_t
* FindFilter( vlc_object_t
*obj
,
47 const audio_sample_format_t
* p_input_format
,
48 const audio_sample_format_t
* p_output_format
)
50 static const char typename
[] = "audio filter";
53 p_filter
= vlc_custom_create( obj
, sizeof(*p_filter
), typename
);
55 if ( p_filter
== NULL
) return NULL
;
57 memcpy( &p_filter
->fmt_in
.audio
, p_input_format
,
58 sizeof(audio_sample_format_t
) );
59 p_filter
->fmt_in
.i_codec
= p_input_format
->i_format
;
60 memcpy( &p_filter
->fmt_out
.audio
, p_output_format
,
61 sizeof(audio_sample_format_t
) );
62 p_filter
->fmt_out
.i_codec
= p_output_format
->i_format
;
63 p_filter
->p_owner
= NULL
;
65 p_filter
->p_module
= module_need( p_filter
, "audio filter", NULL
, false );
66 if ( p_filter
->p_module
== NULL
)
68 vlc_object_release( p_filter
);
72 assert( p_filter
->pf_audio_filter
);
77 * Splits audio format conversion in two simpler conversions
78 * @return 0 on successful split, -1 if the input and output formats are too
79 * similar to split the conversion.
81 static int SplitConversion( const audio_sample_format_t
*restrict infmt
,
82 const audio_sample_format_t
*restrict outfmt
,
83 audio_sample_format_t
*midfmt
)
87 if( infmt
->i_rate
!= outfmt
->i_rate
)
88 midfmt
->i_rate
= infmt
->i_rate
;
90 if( infmt
->i_physical_channels
!= outfmt
->i_physical_channels
91 || infmt
->i_original_channels
!= outfmt
->i_original_channels
)
93 midfmt
->i_physical_channels
= infmt
->i_physical_channels
;
94 midfmt
->i_original_channels
= infmt
->i_original_channels
;
98 assert( infmt
->i_format
!= outfmt
->i_format
);
99 if( AOUT_FMT_LINEAR( infmt
) )
100 /* NOTE: Use S16N as intermediate. We have all conversions to S16N,
101 * and all useful conversions from S16N. TODO: FL32 if HAVE_FPU. */
102 midfmt
->i_format
= VLC_CODEC_S16N
;
104 if( AOUT_FMT_LINEAR( outfmt
) )
105 /* NOTE: our non-linear -> linear filters always output 32-bits */
106 midfmt
->i_format
= HAVE_FPU
? VLC_CODEC_FL32
: VLC_CODEC_FI32
;
108 return -1; /* no indirect non-linear -> non-linear */
111 aout_FormatPrepare( midfmt
);
112 return AOUT_FMTS_IDENTICAL( infmt
, midfmt
) ? -1 : 0;
115 #undef aout_FiltersCreatePipeline
117 * Allocates audio format conversion filters
118 * @param obj parent VLC object for new filters
119 * @param filters table of filters [IN/OUT]
120 * @param nb_filters pointer to the number of filters in the table [IN/OUT]
121 * @param infmt input audio format
122 * @param outfmt output audio format
123 * @return 0 on success, -1 on failure
125 int aout_FiltersCreatePipeline( vlc_object_t
*obj
,
128 const audio_sample_format_t
*restrict infmt
,
129 const audio_sample_format_t
*restrict outfmt
)
131 audio_sample_format_t curfmt
= *outfmt
;
132 unsigned i
= 0, max
= *nb_filters
- AOUT_MAX_FILTERS
;
134 filters
+= *nb_filters
;
135 aout_FormatsPrint( obj
, "filter(s)", infmt
, outfmt
);
137 while( !AOUT_FMTS_IDENTICAL( infmt
, &curfmt
) )
141 msg_Err( obj
, "max (%u) filters reached", AOUT_MAX_FILTERS
);
142 dialog_Fatal( obj
, _("Audio filtering failed"),
143 _("The maximum number of filters (%u) was reached."),
148 /* Make room and prepend a filter */
149 memmove( filters
+ 1, filters
, i
* sizeof( *filters
) );
151 *filters
= FindFilter( obj
, infmt
, &curfmt
);
152 if( *filters
!= NULL
)
158 audio_sample_format_t midfmt
;
159 /* Split the conversion */
160 if( SplitConversion( infmt
, &curfmt
, &midfmt
) )
162 msg_Err( obj
, "conversion pipeline failed: %4.4s -> %4.4s",
163 (const char *)&infmt
->i_format
,
164 (const char *)&outfmt
->i_format
);
168 *filters
= FindFilter( obj
, &midfmt
, &curfmt
);
169 if( *filters
== NULL
)
171 msg_Err( obj
, "cannot find filter for simple conversion" );
178 msg_Dbg( obj
, "conversion pipeline completed" );
183 aout_FiltersDestroyPipeline( filters
, i
);
188 * Destroys a chain of audio filters.
190 void aout_FiltersDestroyPipeline( filter_t
*const *filters
, unsigned n
)
192 for( unsigned i
= 0; i
< n
; i
++ )
194 filter_t
*p_filter
= filters
[i
];
196 module_unneed( p_filter
, p_filter
->p_module
);
197 free( p_filter
->p_owner
);
198 vlc_object_release( p_filter
);
203 * Filters an audio buffer through a chain of filters.
205 void aout_FiltersPlay( filter_t
*const *pp_filters
,
206 unsigned i_nb_filters
, block_t
** pp_block
)
208 block_t
*p_block
= *pp_block
;
210 /* TODO: use filter chain */
211 for( unsigned i
= 0; (i
< i_nb_filters
) && (p_block
!= NULL
); i
++ )
213 filter_t
* p_filter
= pp_filters
[i
];
215 /* Please note that p_block->i_nb_samples & i_buffer
216 * shall be set by the filter plug-in. */
217 p_block
= p_filter
->pf_audio_filter( p_filter
, p_block
);