[vlc-devel] [PATCH] Extend simple mixer to handle 16bit audio
Laurent Aimar
fenrir at elivagar.org
Sun Sep 25 13:01:02 CEST 2011
On Sun, Sep 25, 2011 at 12:29:46PM +0200, XilasZ wrote:
> Tested on Android which use 16bit audio only and the amem patch i sent last
> month with ac3 5.1 and wav 5.1 tracks.
>
> I'll work on a proper android aout soon, instead of using amem.
>
> +/*****************************************************************************************
> + * DoWork16: convert a buffer (same as above, but use 16bit short instead of 32 bit float)
> + *****************************************************************************************/
> +static void DoWork16( filter_t * p_filter,
> + aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
> +{
> + const unsigned i_input_physical = p_filter->fmt_in.audio.i_physical_channels;
> +
> + const bool b_input_7_0 = (i_input_physical & ~AOUT_CHAN_LFE) == AOUT_CHANS_7_0;
> + const bool b_input_5_0 = !b_input_7_0 &&
> + ( (i_input_physical & AOUT_CHANS_5_0) == AOUT_CHANS_5_0 ||
> + (i_input_physical & AOUT_CHANS_5_0_MIDDLE) == AOUT_CHANS_5_0_MIDDLE );
> + const bool b_input_4_center_rear = !b_input_7_0 && !b_input_5_0 &&
> + (i_input_physical & ~AOUT_CHAN_LFE) == AOUT_CHANS_4_CENTER_REAR;
> + const bool b_input_3_0 = !b_input_7_0 && !b_input_5_0 && !b_input_4_center_rear &&
> + (i_input_physical & ~AOUT_CHAN_LFE) == AOUT_CHANS_3_0;
> +
> + int i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
> + int i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
> + short *p_dest = (short *)p_out_buf->p_buffer;
> + const short *p_src = (const short *)p_in_buf->p_buffer;
Use int16_t instead of short.
> + int i;
> +
> + p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
> + p_out_buf->i_buffer = p_in_buf->i_buffer * i_output_nb / i_input_nb;
> +
> + if( p_filter->fmt_out.audio.i_physical_channels == AOUT_CHANS_2_0 )
> + {
> + if( b_input_7_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[6] + 0.5 * p_src[0] + p_src[2] / 4 + p_src[4] / 4;
> + p_dest++;
> + *p_dest = p_src[6] + 0.5 * p_src[1] + p_src[3] / 4 + p_src[5] / 4;
> + p_dest++;
> +
> + p_src += 7;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else if( b_input_5_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[4] + 0.5 * p_src[0] + 0.33 * p_src[2];
> + p_dest++;
> + *p_dest = p_src[4] + 0.5 * p_src[1] + 0.33 * p_src[3];
> + p_dest++;
> +
> + p_src += 5;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else if( b_input_3_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[2] + 0.5 * p_src[0];
> + p_dest++;
> + *p_dest = p_src[2] + 0.5 * p_src[1];
> + p_dest++;
> +
> + p_src += 3;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else if (b_input_4_center_rear)
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[2] + p_src[3] + 0.5 * p_src[0];
> + p_dest++;
> + *p_dest = p_src[2] + p_src[3] + 0.5 * p_src[1];
> + p_dest++;
> + p_src += 4;
> + }
> + }
> + else if( p_filter->fmt_out.audio.i_physical_channels == AOUT_CHAN_CENTER )
> + {
> + if( b_input_7_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[6] + p_src[0] / 4 + p_src[1] / 4 + p_src[2] / 8 + p_src[3] / 8 + p_src[4] / 8 + p_src[5] / 8;
> + p_dest++;
> +
> + p_src += 7;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else if( b_input_5_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[4] + p_src[0] / 4 + p_src[1] / 4 + p_src[2] / 6 + p_src[3] / 6;
> + p_dest++;
> +
> + p_src += 5;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else if( b_input_3_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[2] + p_src[0] / 4 + p_src[1] / 4;
> + p_dest++;
> +
> + p_src += 3;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[0] / 2 + p_src[1] / 2;
> + p_dest++;
> +
> + p_src += 2;
> + }
> + }
> + else
> + {
> + assert( p_filter->fmt_out.audio.i_physical_channels == AOUT_CHANS_4_0 );
> + assert( b_input_7_0 || b_input_5_0 );
> +
> + if( b_input_7_0 )
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[6] + 0.5 * p_src[0] + p_src[2] / 6;
> + p_dest++;
> + *p_dest = p_src[6] + 0.5 * p_src[1] + p_src[3] / 6;
> + p_dest++;
> + *p_dest = p_src[2] / 6 + p_src[4];
> + p_dest++;
> + *p_dest = p_src[3] / 6 + p_src[5];
> + p_dest++;
> +
> + p_src += 7;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + else
> + for( i = p_in_buf->i_nb_samples; i--; )
> + {
> + *p_dest = p_src[4] + 0.5 * p_src[0];
> + p_dest++;
> + *p_dest = p_src[4] + 0.5 * p_src[1];
> + p_dest++;
> + *p_dest = p_src[2];
> + p_dest++;
> + *p_dest = p_src[3];
> + p_dest++;
> +
> + p_src += 5;
> +
> + if( p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_LFE ) p_src++;
> + }
> + }
> +}
It's a full duplicate of the DoWork for float and can be avoiding by templating (move
the function to a .h, and include it twice with 2 sets of defines).
But the code is not acceptable IMHO:
- you don't handle overflow, and so you will have broken audio.
- you still use float, so no performance gain
--
fenrir
More information about the vlc-devel
mailing list