Changeset 10e3212ea54875dd09bc3ac36bd31b7f795a1cb8
- Timestamp:
- 22/08/06 16:31:40
(2 years ago)
- Author:
- Jean-Paul Saman <jpsaman@videolan.org>
- git-committer:
- Jean-Paul Saman <jpsaman@videolan.org> 1156257100 +0000
- git-parent:
[63fa138598d47f1e75e7065a03952e00be6d4780]
- git-author:
- Jean-Paul Saman <jpsaman@videolan.org> 1156257100 +0000
- Message:
Downmix stereo to mono channel and choose with --sout-mono-channel <n> the destination channel.
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| r5f1df8a |
r10e3212 |
|
| 52 | 52 | |
|---|
| 53 | 53 | static block_t *Convert( filter_t *p_filter, block_t *p_block ); |
|---|
| 54 | | static void stereo_mono_downmix( aout_instance_t *, aout_filter_t *, |
|---|
| 55 | | aout_buffer_t *, aout_buffer_t * ); |
|---|
| 56 | | static unsigned int stereo_to_mono( int16_t *, int16_t *, unsigned int ); |
|---|
| 57 | | |
|---|
| 58 | | static void silence_channel( aout_instance_t *, aout_filter_t *, |
|---|
| 59 | | aout_buffer_t *, aout_buffer_t * ); |
|---|
| | 54 | |
|---|
| | 55 | static unsigned int stereo_to_mono( aout_instance_t *, aout_filter_t *, |
|---|
| | 56 | aout_buffer_t *, aout_buffer_t * ); |
|---|
| 60 | 57 | |
|---|
| 61 | 58 | /***************************************************************************** |
|---|
| … | … | |
| 64 | 61 | struct filter_sys_t |
|---|
| 65 | 62 | { |
|---|
| 66 | | vlc_bool_t b_block_channel; |
|---|
| 67 | 63 | int i_nb_channels; /* number of float32 per sample */ |
|---|
| 68 | 64 | unsigned int i_channel_selected; |
|---|
| … | … | |
| 119 | 115 | (p_filter->fmt_out.i_codec != AOUT_FMT_S16_NE) ) |
|---|
| 120 | 116 | { |
|---|
| 121 | | msg_Err( p_this, "invalid format" ); |
|---|
| | 117 | msg_Err( p_this, "filter discarded (invalid format)" ); |
|---|
| 122 | 118 | return -1; |
|---|
| 123 | 119 | } |
|---|
| … | … | |
| 145 | 141 | (unsigned int) var_GetInteger( p_this, MONO_CFG "mono-channel" ); |
|---|
| 146 | 142 | |
|---|
| 147 | | /* temporarily force channel silence */ |
|---|
| 148 | | p_sys->b_block_channel = VLC_TRUE; |
|---|
| 149 | | if( p_sys->b_block_channel ) |
|---|
| 150 | | { |
|---|
| 151 | | p_filter->fmt_out.audio.i_physical_channels = |
|---|
| | 143 | #if 0 |
|---|
| | 144 | p_filter->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER; |
|---|
| | 145 | #endif |
|---|
| | 146 | p_filter->fmt_out.audio.i_physical_channels = |
|---|
| 152 | 147 | (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT); |
|---|
| 153 | | } |
|---|
| 154 | | else |
|---|
| 155 | | p_filter->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER; |
|---|
| 156 | | |
|---|
| 157 | | p_filter->pf_audio_filter = Convert; |
|---|
| | 148 | |
|---|
| 158 | 149 | p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate; |
|---|
| 159 | 150 | p_filter->fmt_out.audio.i_format = p_filter->fmt_out.i_codec; |
|---|
| 160 | 151 | |
|---|
| 161 | | p_sys->i_nb_channels = aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); |
|---|
| | 152 | p_sys->i_nb_channels = aout_FormatNbChannels( &(p_filter->fmt_in.audio) ); |
|---|
| 162 | 153 | p_sys->i_bitspersample = p_filter->fmt_out.audio.i_bitspersample; |
|---|
| | 154 | |
|---|
| | 155 | p_filter->pf_audio_filter = Convert; |
|---|
| 163 | 156 | |
|---|
| 164 | 157 | msg_Dbg( p_this, "%4.4s->%4.4s, channels %d->%d, bits per sample: %i->%i", |
|---|
| … | … | |
| 194 | 187 | block_t *p_out = NULL; |
|---|
| 195 | 188 | int i_out_size; |
|---|
| | 189 | unsigned int i_samples; |
|---|
| 196 | 190 | |
|---|
| 197 | 191 | if( !p_block || !p_block->i_samples ) |
|---|
| … | … | |
| 203 | 197 | |
|---|
| 204 | 198 | i_out_size = p_block->i_samples * p_filter->p_sys->i_bitspersample/8 * |
|---|
| 205 | | p_filter->p_sys->i_nb_channels; |
|---|
| | 199 | aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); |
|---|
| 206 | 200 | |
|---|
| 207 | 201 | p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size ); |
|---|
| … | … | |
| 213 | 207 | } |
|---|
| 214 | 208 | |
|---|
| 215 | | p_out->i_samples = p_block->i_samples; |
|---|
| | 209 | p_out->i_samples = (p_block->i_samples / p_filter->p_sys->i_nb_channels) * |
|---|
| | 210 | aout_FormatNbChannels( &(p_filter->fmt_out.audio) ); |
|---|
| 216 | 211 | p_out->i_dts = p_block->i_dts; |
|---|
| 217 | 212 | p_out->i_pts = p_block->i_pts; |
|---|
| … | … | |
| 229 | 224 | |
|---|
| 230 | 225 | #if 0 |
|---|
| 231 | | if( in_buf.i_nb_bytes != (p_filter->p_sys->i_bitspersample/8) * in_buf.i_nb_samples ) |
|---|
| 232 | | { |
|---|
| 233 | | msg_Err( p_filter, "input buffer is not alligned" ); |
|---|
| 234 | | /* if( in_buf.i_nb_bytes > (p_filter->p_sys->i_bitspersample/8) * in_buf.i_nb_samples) |
|---|
| 235 | | in_buf.i_nb_bytes = (p_filter->p_sys->i_bitspersample/8) * in_buf.i_nb_samples; |
|---|
| 236 | | else |
|---|
| 237 | | //in_buf*/ |
|---|
| | 226 | unsigned int i_in_size = in_buf.i_nb_samples * (p_filter->p_sys->i_bitspersample/8) * |
|---|
| | 227 | aout_FormatNbChannels( &(p_filter->fmt_in.audio) ); |
|---|
| | 228 | if( (in_buf.i_nb_bytes != i_in_size) && ((i_in_size % 32) != 0) ) /* is it word aligned?? */ |
|---|
| | 229 | { |
|---|
| | 230 | msg_Err( p_filter, "input buffer is not word aligned" ); |
|---|
| | 231 | /* Fix output buffer to be word aligned */ |
|---|
| 238 | 232 | } |
|---|
| 239 | 233 | #endif |
|---|
| … | … | |
| 243 | 237 | out_buf.i_nb_samples = p_out->i_samples; |
|---|
| 244 | 238 | |
|---|
| 245 | | stereo_mono_downmix( (aout_instance_t *)p_filter, &aout_filter, &in_buf, &out_buf ); |
|---|
| | 239 | i_samples = stereo_to_mono( (aout_instance_t *)p_filter, &aout_filter, |
|---|
| | 240 | &out_buf, &in_buf ); |
|---|
| 246 | 241 | |
|---|
| 247 | 242 | p_out->i_buffer = out_buf.i_nb_bytes; |
|---|
| … | … | |
| 252 | 247 | } |
|---|
| 253 | 248 | |
|---|
| 254 | | static void stereo_mono_downmix( aout_instance_t * p_aout, aout_filter_t * p_filter, |
|---|
| 255 | | aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf ) |
|---|
| | 249 | /* stereo_to_mono - mix 2 channels (left,right) into one and play silence on |
|---|
| | 250 | * all other channels. |
|---|
| | 251 | */ |
|---|
| | 252 | static unsigned int stereo_to_mono( aout_instance_t * p_aout, aout_filter_t *p_filter, |
|---|
| | 253 | aout_buffer_t *p_output, aout_buffer_t *p_input ) |
|---|
| 256 | 254 | { |
|---|
| 257 | 255 | filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; |
|---|
| 258 | | |
|---|
| 259 | | if( p_sys->b_block_channel ) |
|---|
| 260 | | { |
|---|
| 261 | | silence_channel( p_aout, p_filter, p_out_buf, p_in_buf ); |
|---|
| 262 | | } |
|---|
| 263 | | else |
|---|
| 264 | | { |
|---|
| 265 | | unsigned int i_samples; |
|---|
| 266 | | |
|---|
| 267 | | i_samples = stereo_to_mono( (int16_t *)p_out_buf->p_buffer, (int16_t *)p_in_buf->p_buffer, |
|---|
| 268 | | p_out_buf->i_nb_samples ); |
|---|
| 269 | | } |
|---|
| 270 | | |
|---|
| 271 | | p_out_buf->i_nb_samples = p_in_buf->i_nb_samples; |
|---|
| 272 | | } |
|---|
| 273 | | |
|---|
| 274 | | /* silence_channel - play silence on all channels except the selected one. |
|---|
| 275 | | */ |
|---|
| 276 | | static void silence_channel( aout_instance_t * p_aout, aout_filter_t * p_filter, |
|---|
| 277 | | aout_buffer_t *p_out_buf, aout_buffer_t *p_in_buf ) |
|---|
| 278 | | { |
|---|
| 279 | | filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys; |
|---|
| 280 | | unsigned int n = 0; |
|---|
| 281 | 256 | int16_t *p_in, *p_out; |
|---|
| 282 | | |
|---|
| 283 | | p_in = (int16_t *)p_in_buf->p_buffer; |
|---|
| 284 | | p_out = (int16_t *)p_out_buf->p_buffer; |
|---|
| 285 | | |
|---|
| 286 | | for( n = 0; n < p_in_buf->i_nb_samples * p_sys->i_nb_channels; n++ ) |
|---|
| | 257 | unsigned int n; |
|---|
| | 258 | |
|---|
| | 259 | p_in = (int16_t *) p_input->p_buffer; |
|---|
| | 260 | p_out = (int16_t *) p_output->p_buffer; |
|---|
| | 261 | |
|---|
| | 262 | for( n = 0; n < (p_input->i_nb_samples * p_sys->i_nb_channels); n++ ) |
|---|
| 287 | 263 | { |
|---|
| 288 | 264 | if( (n%p_sys->i_nb_channels) == p_sys->i_channel_selected ) |
|---|
| 289 | 265 | { |
|---|
| 290 | | p_out[n] = p_in[n]; |
|---|
| | 266 | p_out[n] = (p_in[n] + p_in[n+1]) >> 1; |
|---|
| 291 | 267 | } |
|---|
| 292 | 268 | else |
|---|
| … | … | |
| 295 | 271 | } |
|---|
| 296 | 272 | } |
|---|
| 297 | | } |
|---|
| 298 | | |
|---|
| 299 | | /* stereo_to_mono() function is from ffmpeg file libavcodec/resample.c |
|---|
| 300 | | * Copyright (c) 2000 Fabrice Bellard. |
|---|
| 301 | | */ |
|---|
| 302 | | static unsigned int stereo_to_mono( int16_t *p_output, int16_t *p_input, |
|---|
| 303 | | unsigned int i_samples ) |
|---|
| 304 | | { |
|---|
| 305 | | int16_t *p, *q; |
|---|
| 306 | | unsigned int n = i_samples; |
|---|
| 307 | | |
|---|
| 308 | | p = p_input; |
|---|
| 309 | | q = p_output; |
|---|
| 310 | | |
|---|
| 311 | | while (n >= 4) { |
|---|
| 312 | | q[0] = (p[0] + p[1]) >> 1; |
|---|
| 313 | | q[1] = (p[2] + p[3]) >> 1; |
|---|
| 314 | | q[2] = (p[4] + p[5]) >> 1; |
|---|
| 315 | | q[3] = (p[6] + p[7]) >> 1; |
|---|
| 316 | | q += 4; |
|---|
| 317 | | p += 8; |
|---|
| 318 | | n -= 4; |
|---|
| 319 | | } |
|---|
| 320 | | while (n > 0) { |
|---|
| 321 | | q[0] = (p[0] + p[1]) >> 1; |
|---|
| 322 | | q++; |
|---|
| 323 | | p += 2; |
|---|
| 324 | | n--; |
|---|
| 325 | | } |
|---|
| 326 | 273 | return n; |
|---|
| 327 | 274 | } |
|---|