[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