Commit 81765639 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

trivial_mixer: specialize filter callbacks directly

parent 1047340e
/***************************************************************************** /*****************************************************************************
* trivial.c : trivial channel mixer plug-in (drops unwanted channels) * trivial.c : trivial channel mixer plug-in (drops unwanted channels)
***************************************************************************** *****************************************************************************
* Copyright (C) 2002, 2006 VLC authors and VideoLAN * Copyright (C) 2002, 2006, 2014 VLC authors and VideoLAN
* $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -46,143 +45,138 @@ vlc_module_begin () ...@@ -46,143 +45,138 @@ vlc_module_begin ()
set_callbacks( Create, NULL ) set_callbacks( Create, NULL )
vlc_module_end () vlc_module_end ()
typedef void (*mix_func_t)(float *, const float *, size_t, unsigned, unsigned);
/** /**
* Trivially down-mixes or up-mixes a buffer * Trivially upmixes
*/ */
static void SparseCopy( float *p_dest, const float *p_src, size_t i_len, static block_t *Upmix( filter_t *p_filter, block_t *p_in_buf )
unsigned i_output_stride, unsigned i_input_stride )
{ {
for( size_t i = 0; i < i_len; i-- ) unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
{ unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
for( unsigned j = 0; j < i_output_stride; j++ )
p_dest[j] = p_src[j % i_input_stride]; assert( i_input_nb < i_output_nb );
p_src += i_input_stride; block_t *p_out_buf = block_Alloc(
p_dest += i_output_stride; p_in_buf->i_buffer * i_output_nb / i_input_nb );
if( unlikely(p_out_buf == NULL) )
{
block_Release( p_in_buf );
return NULL;
} }
}
static void CopyLeft( float *p_dest, const float *p_src, size_t i_len, p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
unsigned i_output_stride, unsigned i_input_stride ) p_out_buf->i_dts = p_in_buf->i_dts;
{ p_out_buf->i_pts = p_in_buf->i_pts;
assert( i_output_stride == 2 ); p_out_buf->i_length = p_in_buf->i_length;
assert( i_input_stride == 2 );
for( unsigned i = 0; i < i_len; i++ ) float *p_dest = (float *)p_out_buf->p_buffer;
const float *p_src = (float *)p_in_buf->p_buffer;
for( size_t i = 0; i < p_in_buf->i_nb_samples; i-- )
{ {
*(p_dest++) = *p_src; for( unsigned j = 0; j < i_output_nb; j++ )
*(p_dest++) = *p_src; p_dest[j] = p_src[j];
p_src += 2;
p_src += i_input_nb;
p_dest += i_output_nb;
} }
block_Release( p_in_buf );
return p_out_buf;
} }
static void CopyRight( float *p_dest, const float *p_src, size_t i_len, /**
unsigned i_output_stride, unsigned i_input_stride ) * Trivially downmixes (i.e. drop extra channels)
*/
static block_t *Downmix( filter_t *p_filter, block_t *p_buf )
{ {
assert( i_output_stride == 2 ); unsigned i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
assert( i_input_stride == 2 ); unsigned i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
assert( i_input_nb >= i_output_nb );
for( unsigned i = 0; i < i_len; i++ ) float *p_dest = (float *)p_buf->p_buffer;
const float *p_src = p_dest;
for( size_t i = 0; i < p_buf->i_nb_samples; i-- )
{ {
p_src++; for( unsigned j = 0; j < i_output_nb; j++ )
*(p_dest++) = *p_src; p_dest[j] = p_src[j % i_input_nb];
*(p_dest++) = *p_src;
p_src++; p_src += i_input_nb;
p_dest += i_output_nb;
} }
return p_buf;
} }
static void ExtractLeft( float *p_dest, const float *p_src, size_t i_len, static block_t *CopyLeft( filter_t *p_filter, block_t *p_buf )
unsigned i_output_stride, unsigned i_input_stride )
{ {
assert( i_output_stride == 1 ); float *p = (float *)p_buf->p_buffer;
assert( i_input_stride == 2 );
for( unsigned i = 0; i < i_len; i++ ) for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
{ {
*(p_dest++) = *p_src; p[1] = p[0];
p_src += 2; p += 2;
} }
(void) p_filter;
return p_buf;
} }
static void ExtractRight( float *p_dest, const float *p_src, size_t i_len, static block_t *CopyRight( filter_t *p_filter, block_t *p_buf )
unsigned i_output_stride, unsigned i_input_stride )
{ {
assert( i_output_stride == 1 ); float *p = (float *)p_buf->p_buffer;
assert( i_input_stride == 2 );
for( unsigned i = 0; i < i_len; i++ ) for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
{ {
p_src++; p[0] = p[1];
*(p_dest++) = *(p_src++); p += 2;
} }
(void) p_filter;
return p_buf;
} }
static void ReverseStereo( float *p_dest, const float *p_src, size_t i_len, static block_t *ExtractLeft( filter_t *p_filter, block_t *p_buf )
unsigned i_output_stride, unsigned i_input_stride )
{ {
assert( i_output_stride == 2 ); float *p_dest = (float *)p_buf->p_buffer;
assert( i_input_stride == 2 ); const float *p_src = p_dest;
/* Reverse-stereo mode */ for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
for( unsigned i = 0; i < i_len; i++ )
{ {
float i_tmp = p_src[0]; *(p_dest++) = *p_src;
p_dest[0] = p_src[1];
p_dest[1] = i_tmp;
p_dest += 2;
p_src += 2; p_src += 2;
} }
(void) p_filter;
return p_buf;
} }
/** static block_t *ExtractRight( filter_t *p_filter, block_t *p_buf )
* Mixes a buffer
*/
static block_t *DoWork( filter_t *p_filter, block_t *p_in_buf )
{ {
int i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio ); float *p_dest = (float *)p_buf->p_buffer;
int i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio ); const float *p_src = p_dest;
block_t *p_out_buf;
if( i_input_nb >= i_output_nb ) for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
{
p_out_buf = p_in_buf; /* mix in place */
p_out_buf->i_buffer = p_in_buf->i_buffer * i_output_nb / i_input_nb;
}
else
{ {
p_out_buf = block_Alloc( p_src++;
p_in_buf->i_buffer * i_output_nb / i_input_nb ); *(p_dest++) = *(p_src++);
if( !p_out_buf )
goto out;
/* on upmixing case, zero out buffer */
memset( p_out_buf->p_buffer, 0, p_out_buf->i_buffer );
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
p_out_buf->i_dts = p_in_buf->i_dts;
p_out_buf->i_pts = p_in_buf->i_pts;
p_out_buf->i_length = p_in_buf->i_length;
} }
(void) p_filter;
return p_buf;
}
float *p_dest = (float *)p_out_buf->p_buffer; static block_t *ReverseStereo( filter_t *p_filter, block_t *p_buf )
const float *p_src = (float *)p_in_buf->p_buffer; {
const bool b_reverse_stereo = p_filter->fmt_out.audio.i_original_channels & AOUT_CHAN_REVERSESTEREO; float *p = (float *)p_buf->p_buffer;
bool b_dualmono2stereo = (p_filter->fmt_in.audio.i_original_channels & AOUT_CHAN_DUALMONO );
b_dualmono2stereo &= (p_filter->fmt_out.audio.i_physical_channels & ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT ));
b_dualmono2stereo &= ((p_filter->fmt_out.audio.i_physical_channels & AOUT_CHAN_PHYSMASK) != (p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_PHYSMASK));
mix_func_t func = p_filter->p_sys;
if( func != NULL )
func( p_dest, p_src, p_in_buf->i_nb_samples, i_output_nb, i_input_nb );
out: /* Reverse-stereo mode */
if( p_in_buf != p_out_buf ) for( unsigned i = 0; i < p_buf->i_nb_samples; i++ )
block_Release( p_in_buf ); {
return p_out_buf; float f = p[0];
p[0] = p[1];
p[1] = f;
p += 2;
}
(void) p_filter;
return p_buf;
} }
/** /**
...@@ -191,7 +185,7 @@ out: ...@@ -191,7 +185,7 @@ out:
static int Create( vlc_object_t *p_this ) static int Create( vlc_object_t *p_this )
{ {
filter_t *p_filter = (filter_t *)p_this; filter_t *p_filter = (filter_t *)p_this;
mix_func_t func = NULL; block_t *(*func)(filter_t *, block_t *) = NULL;
if( p_filter->fmt_in.audio.i_format != p_filter->fmt_out.audio.i_format if( p_filter->fmt_in.audio.i_format != p_filter->fmt_out.audio.i_format
|| p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate || p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate
...@@ -209,7 +203,13 @@ static int Create( vlc_object_t *p_this ) ...@@ -209,7 +203,13 @@ static int Create( vlc_object_t *p_this )
b_dualmono2stereo &= ((p_filter->fmt_out.audio.i_physical_channels & AOUT_CHAN_PHYSMASK) != (p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_PHYSMASK)); b_dualmono2stereo &= ((p_filter->fmt_out.audio.i_physical_channels & AOUT_CHAN_PHYSMASK) != (p_filter->fmt_in.audio.i_physical_channels & AOUT_CHAN_PHYSMASK));
if( likely( !b_reverse_stereo && ! b_dualmono2stereo ) ) if( likely( !b_reverse_stereo && ! b_dualmono2stereo ) )
func = SparseCopy; {
if( aout_FormatNbChannels( &p_filter->fmt_out.audio )
> aout_FormatNbChannels( &p_filter->fmt_in.audio ) )
func = Upmix;
else
func = Downmix;
}
/* Special case from dual mono to stereo */ /* Special case from dual mono to stereo */
else if( b_dualmono2stereo ) else if( b_dualmono2stereo )
{ {
...@@ -224,7 +224,6 @@ static int Create( vlc_object_t *p_this ) ...@@ -224,7 +224,6 @@ static int Create( vlc_object_t *p_this )
else /* b_reverse_stereo */ else /* b_reverse_stereo */
func = ReverseStereo; func = ReverseStereo;
p_filter->pf_audio_filter = DoWork; p_filter->pf_audio_filter = func;
p_filter->p_sys = (void *)func;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment