1 /*****************************************************************************
2 * simple_channel_mixer.c : simple channel mixer plug-in using NEON assembly
3 *****************************************************************************
4 * Copyright (C) 2002, 2004, 2006-2009, 2012 VLC authors and VideoLAN
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * David Geldreich <david.geldreich@free.fr>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
36 #include <vlc_filter.h>
37 #include <vlc_block.h>
41 /*****************************************************************************
43 *****************************************************************************/
44 static int OpenFilter( vlc_object_t
* );
47 set_description( N_("Audio filter for simple channel mixing using NEON assembly") )
48 set_category( CAT_AUDIO
)
49 set_subcategory( SUBCAT_AUDIO_MISC
)
50 set_capability( "audio converter", 20 )
51 set_callbacks( OpenFilter
, NULL
)
54 #define FILTER_WRAPPER(in, out) \
55 void convert_##in##to##out##_neon_asm(float *dst, const float *src, int num, bool lfeChannel); \
56 static block_t *Filter_##in##to##out (filter_t *p_filter, block_t *p_block) \
59 if (!FilterInit( p_filter, p_block, &p_out )) \
61 const float *p_src = (const float *)p_block->p_buffer; \
62 float *p_dest = (float *)p_out->p_buffer; \
63 convert_##in##to##out##_neon_asm( p_dest, p_src, p_block->i_nb_samples, \
64 p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ); \
65 block_Release( p_block ); \
69 #define TRY_FILTER(in, out) \
70 if ( b_input_##in && b_output_##out ) \
72 p_filter->pf_audio_filter = Filter_##in##to##out ; \
76 /*****************************************************************************
78 *****************************************************************************/
79 static bool FilterInit( filter_t
*p_filter
, block_t
*p_block
, block_t
**pp_out
)
81 if( !p_block
|| !p_block
->i_nb_samples
)
84 block_Release( p_block
);
88 size_t i_out_size
= p_block
->i_nb_samples
*
89 p_filter
->fmt_out
.audio
.i_bitspersample
*
90 p_filter
->fmt_out
.audio
.i_channels
/ 8;
92 block_t
*p_out
= block_Alloc( i_out_size
);
95 msg_Warn( p_filter
, "can't get output buffer" );
96 block_Release( p_block
);
100 p_out
->i_nb_samples
= p_block
->i_nb_samples
;
101 p_out
->i_dts
= p_block
->i_dts
;
102 p_out
->i_pts
= p_block
->i_pts
;
103 p_out
->i_length
= p_block
->i_length
;
105 int i_input_nb
= aout_FormatNbChannels( &p_filter
->fmt_in
.audio
);
106 int i_output_nb
= aout_FormatNbChannels( &p_filter
->fmt_out
.audio
);
107 p_out
->i_buffer
= p_block
->i_buffer
* i_output_nb
/ i_input_nb
;
122 /*****************************************************************************
124 *****************************************************************************/
125 static int OpenFilter( vlc_object_t
*p_this
)
127 filter_t
*p_filter
= (filter_t
*)p_this
;
129 if (!vlc_CPU_ARM_NEON())
132 audio_format_t fmt_in
= p_filter
->fmt_in
.audio
;
133 audio_format_t fmt_out
= p_filter
->fmt_out
.audio
;
135 fmt_in
.i_format
= p_filter
->fmt_in
.i_codec
;
136 fmt_out
.i_format
= p_filter
->fmt_out
.i_codec
;
138 if( fmt_in
.i_format
!= VLC_CODEC_FL32
||
139 fmt_in
.i_format
!= fmt_out
.i_format
||
140 fmt_in
.i_rate
!= fmt_out
.i_rate
)
145 if( fmt_in
.i_physical_channels
== fmt_out
.i_physical_channels
&&
146 fmt_in
.i_original_channels
== fmt_out
.i_original_channels
)
151 const bool b_input_7
= (fmt_in
.i_physical_channels
& ~AOUT_CHAN_LFE
) == AOUT_CHANS_7_0
;
152 const bool b_input_5
= ( (fmt_in
.i_physical_channels
& AOUT_CHANS_5_0
) == AOUT_CHANS_5_0
||
153 (fmt_in
.i_physical_channels
& AOUT_CHANS_5_0_MIDDLE
) == AOUT_CHANS_5_0_MIDDLE
);
154 const bool b_input_4
= (fmt_in
.i_physical_channels
& ~AOUT_CHAN_LFE
) == AOUT_CHANS_4_CENTER_REAR
;
155 const bool b_input_3
= (fmt_in
.i_physical_channels
& ~AOUT_CHAN_LFE
) == AOUT_CHANS_3_0
;
157 const bool b_output_1
= fmt_out
.i_physical_channels
== AOUT_CHAN_CENTER
;
158 const bool b_output_2
= fmt_out
.i_physical_channels
== AOUT_CHANS_2_0
;
159 const bool b_output_4
= fmt_out
.i_physical_channels
== AOUT_CHANS_4_0
;
161 /* Only conversion to Mono, Stereo and 4.0 right now */
162 /* Only from 7/7.1/5/5.1/3/3.1/2.0
163 * XXX 5.X rear and middle are handled the same way */