1 /*****************************************************************************
2 * trivial.c : trivial channel mixer plug-in (drops unwanted channels)
3 *****************************************************************************
4 * Copyright (C) 2002, 2006, 2014 VLC authors and VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
36 #include <vlc_filter.h>
38 static int Create( vlc_object_t * );
41 set_description( N_("Audio filter for trivial channel mixing") )
42 set_capability( "audio converter", 1 )
43 set_category( CAT_AUDIO )
44 set_subcategory( SUBCAT_AUDIO_MISC )
45 set_callbacks( Create, NULL )
51 static block_t *Upmix( filter_t *p_filter, block_t *p_in_buf )
53 unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
54 unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
56 assert( i_input_nb < i_output_nb );
58 block_t *p_out_buf = block_Alloc(
59 p_in_buf->i_buffer * i_output_nb / i_input_nb );
60 if( unlikely(p_out_buf == NULL) )
62 block_Release( p_in_buf );
66 p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
67 p_out_buf->i_dts = p_in_buf->i_dts;
68 p_out_buf->i_pts = p_in_buf->i_pts;
69 p_out_buf->i_length = p_in_buf->i_length;
71 float *p_dest = (float *)p_out_buf->p_buffer;
72 const float *p_src = (float *)p_in_buf->p_buffer;
74 for( size_t i = 0; i < p_in_buf->i_nb_samples; i++ )
76 for( unsigned j = 0; j < i_output_nb; j++ )
77 p_dest[j] = p_src[j % i_input_nb];
80 p_dest += i_output_nb;
83 block_Release( p_in_buf );
88 * Trivially downmixes (i.e. drop extra channels)
90 static block_t *Downmix( filter_t *p_filter, block_t *p_buf )
92 unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
93 unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
95 assert( i_input_nb >= i_output_nb );
97 float *p_dest = (float *)p_buf->p_buffer;
98 const float *p_src = p_dest;
100 for( size_t i = 0; i < p_buf->i_nb_samples; i++ )
102 for( unsigned j = 0; j < i_output_nb; j++ )
103 p_dest[j] = p_src[j];
106 p_dest += i_output_nb;
112 static block_t *CopyLeft( filter_t *p_filter, block_t *p_buf )
114 float *p = (float *)p_buf->p_buffer;
116 for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
125 static block_t *CopyRight( filter_t *p_filter, block_t *p_buf )
127 float *p = (float *)p_buf->p_buffer;
129 for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
138 static block_t *ExtractLeft( filter_t *p_filter, block_t *p_buf )
140 float *p_dest = (float *)p_buf->p_buffer;
141 const float *p_src = p_dest;
143 for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
145 *(p_dest++) = *p_src;
152 static block_t *ExtractRight( filter_t *p_filter, block_t *p_buf )
154 float *p_dest = (float *)p_buf->p_buffer;
155 const float *p_src = p_dest;
157 for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
160 *(p_dest++) = *(p_src++);
166 static block_t *ReverseStereo( filter_t *p_filter, block_t *p_buf )
168 float *p = (float *)p_buf->p_buffer;
170 /* Reverse-stereo mode */
171 for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
183 * Probes the trivial channel mixer
185 static int Create( vlc_object_t *p_this )
187 filter_t *p_filter = (filter_t *)p_this;
188 const audio_format_t *infmt = &p_filter->fmt_in.audio;
189 const audio_format_t *outfmt = &p_filter->fmt_out.audio;
191 if( infmt->i_format != outfmt->i_format
192 || infmt->i_rate != outfmt->i_rate
193 || infmt->i_format != VLC_CODEC_FL32 )
195 if( infmt->i_physical_channels == outfmt->i_physical_channels
196 && infmt->i_original_channels == outfmt->i_original_channels )
199 if( outfmt->i_physical_channels == AOUT_CHANS_STEREO )
201 bool swap = (outfmt->i_original_channels & AOUT_CHAN_REVERSESTEREO)
202 != (infmt->i_original_channels & AOUT_CHAN_REVERSESTEREO);
204 if( (outfmt->i_original_channels & AOUT_CHAN_PHYSMASK)
207 p_filter->pf_audio_filter = swap ? CopyRight : CopyLeft;
211 if( (outfmt->i_original_channels & AOUT_CHAN_PHYSMASK)
214 p_filter->pf_audio_filter = swap ? CopyLeft : CopyRight;
220 p_filter->pf_audio_filter = ReverseStereo;
225 if ( aout_FormatNbChannels( outfmt ) == 1 )
227 bool mono = !!(infmt->i_original_channels & AOUT_CHAN_DUALMONO);
229 if( mono && (infmt->i_original_channels & AOUT_CHAN_LEFT) )
231 p_filter->pf_audio_filter = ExtractLeft;
235 if( mono && (infmt->i_original_channels & AOUT_CHAN_RIGHT) )
237 p_filter->pf_audio_filter = ExtractRight;
242 if( aout_FormatNbChannels( outfmt ) > aout_FormatNbChannels( infmt ) )
243 p_filter->pf_audio_filter = Upmix;
245 p_filter->pf_audio_filter = Downmix;