📄 mono.c
字号:
}/***************************************************************************** * OpenFilter *****************************************************************************/static int OpenFilter( vlc_object_t *p_this ){ filter_t * p_filter = (filter_t *)p_this; filter_sys_t *p_sys = NULL; if( aout_FormatNbChannels( &(p_filter->fmt_in.audio) ) == 1 ) { /*msg_Dbg( p_filter, "filter discarded (incompatible format)" );*/ return VLC_EGENERIC; } if( (p_filter->fmt_in.i_codec != AOUT_FMT_S16_NE) || (p_filter->fmt_out.i_codec != AOUT_FMT_S16_NE) ) { /*msg_Err( p_this, "filter discarded (invalid format)" );*/ return VLC_EGENERIC; } 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_format != AOUT_FMT_S16_NE) && (p_filter->fmt_out.audio.i_format != AOUT_FMT_S16_NE) && (p_filter->fmt_in.audio.i_bitspersample != p_filter->fmt_out.audio.i_bitspersample)) { /*msg_Err( p_this, "couldn't load mono filter" );*/ return VLC_EGENERIC; } /* Allocate the memory needed to store the module's structure */ p_sys = p_filter->p_sys = malloc( sizeof(filter_sys_t) ); if( p_sys == NULL ) return VLC_EGENERIC; var_Create( p_this, MONO_CFG "downmix", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); p_sys->b_downmix = var_GetBool( p_this, MONO_CFG "downmix" ); var_Create( p_this, MONO_CFG "channel", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); p_sys->i_channel_selected = (unsigned int) var_GetInteger( p_this, MONO_CFG "channel" ); if( p_sys->b_downmix ) { msg_Dbg( p_this, "using stereo to mono downmix" ); p_filter->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER; p_filter->fmt_out.audio.i_channels = 1; } else { msg_Dbg( p_this, "using pseudo mono" ); p_filter->fmt_out.audio.i_physical_channels = (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT); p_filter->fmt_out.audio.i_channels = 2; } p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate; p_filter->fmt_out.audio.i_format = p_filter->fmt_out.i_codec; p_sys->i_nb_channels = aout_FormatNbChannels( &(p_filter->fmt_in.audio) ); p_sys->i_bitspersample = p_filter->fmt_out.audio.i_bitspersample; p_sys->i_overflow_buffer_size = 0; p_sys->p_overflow_buffer = NULL; p_sys->i_nb_atomic_operations = 0; p_sys->p_atomic_operations = NULL; if( Init( VLC_OBJECT(p_filter), p_filter->p_sys, aout_FormatNbChannels( &p_filter->fmt_in.audio ), p_filter->fmt_in.audio.i_physical_channels, p_filter->fmt_in.audio.i_rate ) < 0 ) { var_Destroy( p_this, MONO_CFG "channel" ); var_Destroy( p_this, MONO_CFG "downmix" ); free( p_sys ); return VLC_EGENERIC; } p_filter->pf_audio_filter = Convert; msg_Dbg( p_this, "%4.4s->%4.4s, channels %d->%d, bits per sample: %i->%i", (char *)&p_filter->fmt_in.i_codec, (char *)&p_filter->fmt_out.i_codec, p_filter->fmt_in.audio.i_physical_channels, p_filter->fmt_out.audio.i_physical_channels, p_filter->fmt_in.audio.i_bitspersample, p_filter->fmt_out.audio.i_bitspersample ); return VLC_SUCCESS;}/***************************************************************************** * CloseFilter *****************************************************************************/static void CloseFilter( vlc_object_t *p_this){ filter_t *p_filter = (filter_t *) p_this; filter_sys_t *p_sys = p_filter->p_sys; var_Destroy( p_this, MONO_CFG "channel" ); var_Destroy( p_this, MONO_CFG "downmix" ); free( p_sys->p_atomic_operations ); free( p_sys->p_overflow_buffer ); free( p_sys );}/***************************************************************************** * Convert *****************************************************************************/static block_t *Convert( filter_t *p_filter, block_t *p_block ){ aout_filter_t aout_filter; aout_buffer_t in_buf, out_buf; block_t *p_out = NULL; unsigned int i_samples; int i_out_size; if( !p_block || !p_block->i_samples ) { if( p_block ) block_Release( p_block ); return NULL; } i_out_size = p_block->i_samples * p_filter->p_sys->i_bitspersample/8 * aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size ); if( !p_out ) { msg_Warn( p_filter, "can't get output buffer" ); block_Release( p_block ); return NULL; } p_out->i_samples = (p_block->i_samples / p_filter->p_sys->i_nb_channels) * aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); p_out->i_dts = p_block->i_dts; p_out->i_pts = p_block->i_pts; p_out->i_length = p_block->i_length; aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys; aout_filter.input = p_filter->fmt_in.audio; aout_filter.input.i_format = p_filter->fmt_in.i_codec; aout_filter.output = p_filter->fmt_out.audio; aout_filter.output.i_format = p_filter->fmt_out.i_codec; in_buf.p_buffer = p_block->p_buffer; in_buf.i_nb_bytes = p_block->i_buffer; in_buf.i_nb_samples = p_block->i_samples;#if 0 unsigned int i_in_size = in_buf.i_nb_samples * (p_filter->p_sys->i_bitspersample/8) * aout_FormatNbChannels( &(p_filter->fmt_in.audio) ); if( (in_buf.i_nb_bytes != i_in_size) && ((i_in_size % 32) != 0) ) /* is it word aligned?? */ { msg_Err( p_filter, "input buffer is not word aligned" ); /* Fix output buffer to be word aligned */ }#endif out_buf.p_buffer = p_out->p_buffer; out_buf.i_nb_bytes = p_out->i_buffer; out_buf.i_nb_samples = p_out->i_samples; memset( p_out->p_buffer, 0, i_out_size ); if( p_filter->p_sys->b_downmix ) { stereo2mono_downmix( &aout_filter, &in_buf, &out_buf ); i_samples = mono( &aout_filter, &out_buf, &in_buf ); } else { i_samples = stereo_to_mono( &aout_filter, &out_buf, &in_buf ); } p_out->i_buffer = out_buf.i_nb_bytes; p_out->i_samples = out_buf.i_nb_samples; block_Release( p_block ); return p_out;}/* stereo2mono_downmix - stereo channels into one mono channel. * Code taken from modules/audio_filter/channel_mixer/headphone.c * converted from float into int16_t based downmix * Written by Boris Dorès <babal@via.ecp.fr> */static void stereo2mono_downmix( aout_filter_t * p_filter, aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf ){ filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; int i_input_nb = aout_FormatNbChannels( &p_filter->input ); int i_output_nb = aout_FormatNbChannels( &p_filter->output ); int16_t * p_in = (int16_t*) p_in_buf->p_buffer; uint8_t * p_out; uint8_t * p_overflow; uint8_t * p_slide; size_t i_overflow_size; /* in bytes */ size_t i_out_size; /* in bytes */ unsigned int i, j; int i_source_channel_offset; int i_dest_channel_offset; unsigned int i_delay; double d_amplitude_factor; /* out buffer characterisitcs */ p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * i_output_nb / i_input_nb; p_out = p_out_buf->p_buffer; i_out_size = p_out_buf->i_nb_bytes; if( p_sys != NULL ) { /* Slide the overflow buffer */ p_overflow = p_sys->p_overflow_buffer; i_overflow_size = p_sys->i_overflow_buffer_size; if ( i_out_size > i_overflow_size ) memcpy( p_out, p_overflow, i_overflow_size ); else memcpy( p_out, p_overflow, i_out_size ); p_slide = p_sys->p_overflow_buffer; while( p_slide < p_overflow + i_overflow_size ) { if( p_slide + i_out_size < p_overflow + i_overflow_size ) { memset( p_slide, 0, i_out_size ); if( p_slide + 2 * i_out_size < p_overflow + i_overflow_size ) memcpy( p_slide, p_slide + i_out_size, i_out_size ); else memcpy( p_slide, p_slide + i_out_size, p_overflow + i_overflow_size - ( p_slide + i_out_size ) ); } else { memset( p_slide, 0, p_overflow + i_overflow_size - p_slide ); } p_slide += i_out_size; } /* apply the atomic operations */ for( i = 0; i < p_sys->i_nb_atomic_operations; i++ ) { /* shorter variable names */ i_source_channel_offset = p_sys->p_atomic_operations[i].i_source_channel_offset; i_dest_channel_offset = p_sys->p_atomic_operations[i].i_dest_channel_offset; i_delay = p_sys->p_atomic_operations[i].i_delay; d_amplitude_factor = p_sys->p_atomic_operations[i].d_amplitude_factor; if( p_out_buf->i_nb_samples > i_delay ) { /* current buffer coefficients */ for( j = 0; j < p_out_buf->i_nb_samples - i_delay; j++ ) { ((int16_t*)p_out)[ (i_delay+j)*i_output_nb + i_dest_channel_offset ] += p_in[ j * i_input_nb + i_source_channel_offset ] * d_amplitude_factor; } /* overflow buffer coefficients */ for( j = 0; j < i_delay; j++ ) { ((int16_t*)p_overflow)[ j*i_output_nb + i_dest_channel_offset ] += p_in[ (p_out_buf->i_nb_samples - i_delay + j) * i_input_nb + i_source_channel_offset ] * d_amplitude_factor; } } else { /* overflow buffer coefficients only */ for( j = 0; j < p_out_buf->i_nb_samples; j++ ) { ((int16_t*)p_overflow)[ (i_delay - p_out_buf->i_nb_samples + j) * i_output_nb + i_dest_channel_offset ] += p_in[ j * i_input_nb + i_source_channel_offset ] * d_amplitude_factor; } } } } else { memset( p_out, 0, i_out_size ); }}/* Simple stereo to mono mixing. */static unsigned int mono( aout_filter_t *p_filter, aout_buffer_t *p_output, aout_buffer_t *p_input ){ filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; int16_t *p_in, *p_out; unsigned int n = 0, r = 0; p_in = (int16_t *) p_input->p_buffer; p_out = (int16_t *) p_output->p_buffer; while( n < (p_input->i_nb_samples * p_sys->i_nb_channels) ) { p_out[r] = (p_in[n] + p_in[n+1]) >> 1; r++; n += 2; } return r;}/* Simple stereo to mono mixing. */static unsigned int stereo_to_mono( aout_filter_t *p_filter, aout_buffer_t *p_output, aout_buffer_t *p_input ){ filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; int16_t *p_in, *p_out; unsigned int n; p_in = (int16_t *) p_input->p_buffer; p_out = (int16_t *) p_output->p_buffer; for( n = 0; n < (p_input->i_nb_samples * p_sys->i_nb_channels); n++ ) { /* Fake real mono. */ if( p_sys->i_channel_selected == -1) { p_out[n] = p_out[n+1] = (p_in[n] + p_in[n+1]) >> 1; n++; } else if( (n % p_sys->i_nb_channels) == (unsigned int) p_sys->i_channel_selected ) { p_out[n] = p_out[n+1] = p_in[n]; } } return n;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -