Change the gmp download URL to https://gmplib.org/download
[vlc/gmpfix.git] / modules / arm_neon / simple_channel_mixer.c
blob8627415805726071359fcbbd0148f9ca034b9e30
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
5 * $Id$
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * David Geldreich <david.geldreich@free.fr>
9 * Sébastien Toque
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 /*****************************************************************************
27 * Preamble
28 *****************************************************************************/
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_aout.h>
36 #include <vlc_filter.h>
37 #include <vlc_block.h>
38 #include <vlc_cpu.h>
39 #include <assert.h>
41 /*****************************************************************************
42 * Module descriptor
43 *****************************************************************************/
44 static int OpenFilter( vlc_object_t * );
46 vlc_module_begin ()
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 )
52 vlc_module_end ()
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) \
57 { \
58 block_t *p_out; \
59 if (!FilterInit( p_filter, p_block, &p_out )) \
60 return NULL; \
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 ); \
66 return p_out; \
69 #define TRY_FILTER(in, out) \
70 if ( b_input_##in && b_output_##out ) \
71 { \
72 p_filter->pf_audio_filter = Filter_##in##to##out ; \
73 return VLC_SUCCESS; \
76 /*****************************************************************************
77 * Filter:
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 )
83 if( p_block )
84 block_Release( p_block );
85 return false;
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 );
93 if( !p_out )
95 msg_Warn( p_filter, "can't get output buffer" );
96 block_Release( p_block );
97 return false;
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;
109 *pp_out = p_out;
110 return true;
113 FILTER_WRAPPER(7,2)
114 FILTER_WRAPPER(5,2)
115 FILTER_WRAPPER(4,2)
116 FILTER_WRAPPER(3,2)
117 FILTER_WRAPPER(7,1)
118 FILTER_WRAPPER(5,1)
119 FILTER_WRAPPER(7,4)
120 FILTER_WRAPPER(5,4)
122 /*****************************************************************************
123 * OpenFilter:
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())
130 return VLC_EGENERIC;
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 )
142 return VLC_EGENERIC;
145 if( fmt_in.i_physical_channels == fmt_out.i_physical_channels &&
146 fmt_in.i_original_channels == fmt_out.i_original_channels )
148 return VLC_EGENERIC;
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 */
165 TRY_FILTER(7,2)
166 TRY_FILTER(5,2)
167 TRY_FILTER(4,2)
168 TRY_FILTER(3,2)
169 TRY_FILTER(7,1)
170 TRY_FILTER(5,1)
171 TRY_FILTER(7,4)
172 TRY_FILTER(5,4)
174 return VLC_EGENERIC;