add_integer: remove callback parameter
[vlc/asuraparaju-public.git] / modules / audio_filter / channel_mixer / mono.c
blob5db5bdcace1a90a52f9904d58b237c71ab37f559
1 /*****************************************************************************
2 * mono.c : stereo2mono downmixsimple channel mixer plug-in
3 *****************************************************************************
4 * Copyright (C) 2006 M2X
5 * $Id$
7 * Authors: Jean-Paul Saman <jpsaman at m2x dot nl>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <math.h> /* sqrt */
32 #include <stdint.h> /* int16_t .. */
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
38 #include <vlc_common.h>
39 #include <vlc_plugin.h>
40 #include <vlc_block.h>
41 #include <vlc_filter.h>
42 #include <vlc_aout.h>
44 /*****************************************************************************
45 * Local prototypes
46 *****************************************************************************/
47 static int OpenFilter ( vlc_object_t * );
48 static void CloseFilter ( vlc_object_t * );
50 static block_t *Convert( filter_t *p_filter, block_t *p_block );
52 static unsigned int stereo_to_mono( aout_filter_t *, aout_buffer_t *,
53 aout_buffer_t * );
54 static unsigned int mono( aout_filter_t *, aout_buffer_t *, aout_buffer_t * );
55 static void stereo2mono_downmix( aout_filter_t *, aout_buffer_t *,
56 aout_buffer_t * );
58 /*****************************************************************************
59 * Local structures
60 *****************************************************************************/
61 struct atomic_operation_t
63 int i_source_channel_offset;
64 int i_dest_channel_offset;
65 unsigned int i_delay;/* in sample unit */
66 double d_amplitude_factor;
69 struct filter_sys_t
71 bool b_downmix;
73 unsigned int i_nb_channels; /* number of int16_t per sample */
74 int i_channel_selected;
75 int i_bitspersample;
77 size_t i_overflow_buffer_size;/* in bytes */
78 uint8_t * p_overflow_buffer;
79 unsigned int i_nb_atomic_operations;
80 struct atomic_operation_t * p_atomic_operations;
83 #define MONO_DOWNMIX_TEXT N_("Use downmix algorithm")
84 #define MONO_DOWNMIX_LONGTEXT N_("This option selects a stereo to mono " \
85 "downmix algorithm that is used in the headphone channel mixer. It " \
86 "gives the effect of standing in a room full of speakers." )
88 #define MONO_CHANNEL_TEXT N_("Select channel to keep")
89 #define MONO_CHANNEL_LONGTEXT N_("This option silences all other channels " \
90 "except the selected channel. Choose one from (0=left, 1=right, " \
91 "2=rear left, 3=rear right, 4=center, 5=left front)")
93 static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5 };
94 static const char *const ppsz_pos_descriptions[] =
95 { N_("Left"), N_("Right"), N_("Left rear"), N_("Right rear"), N_("Center"),
96 N_("Left front") };
98 /* our internal channel order (WG-4 order) */
99 static const uint32_t pi_channels_out[] =
100 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
101 AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
103 #define MONO_CFG "sout-mono-"
104 /*****************************************************************************
105 * Module descriptor
106 *****************************************************************************/
107 vlc_module_begin ()
108 set_description( N_("Audio filter for stereo to mono conversion") )
109 set_capability( "audio filter", 2 )
110 set_category( CAT_AUDIO )
111 set_subcategory( SUBCAT_AUDIO_AFILTER )
112 set_callbacks( OpenFilter, CloseFilter )
113 set_shortname( "Mono" )
115 add_bool( MONO_CFG "downmix", true, NULL, MONO_DOWNMIX_TEXT,
116 MONO_DOWNMIX_LONGTEXT, false )
117 add_integer( MONO_CFG "channel", -1, MONO_CHANNEL_TEXT,
118 MONO_CHANNEL_LONGTEXT, false )
119 change_integer_list( pi_pos_values, ppsz_pos_descriptions )
121 vlc_module_end ()
123 /* Init() and ComputeChannelOperations() -
124 * Code taken from modules/audio_filter/channel_mixer/headphone.c
125 * converted from float into int16_t based downmix
126 * Written by Boris Dorès <babal@via.ecp.fr>
129 /*****************************************************************************
130 * Init: initialize internal data structures
131 * and computes the needed atomic operations
132 *****************************************************************************/
133 /* x and z represent the coordinates of the virtual speaker
134 * relatively to the center of the listener's head, measured in meters :
136 * left right
139 *a head
143 * rear left rear right
145 * x-axis
146 * */
147 static void ComputeChannelOperations( struct filter_sys_t * p_data,
148 unsigned int i_rate, unsigned int i_next_atomic_operation,
149 int i_source_channel_offset, double d_x, double d_z,
150 double d_compensation_length, double d_channel_amplitude_factor )
152 double d_c = 340; /*sound celerity (unit: m/s)*/
153 double d_compensation_delay = (d_compensation_length-0.1) / d_c * i_rate;
155 /* Left ear */
156 p_data->p_atomic_operations[i_next_atomic_operation]
157 .i_source_channel_offset = i_source_channel_offset;
158 p_data->p_atomic_operations[i_next_atomic_operation]
159 .i_dest_channel_offset = 0;/* left */
160 p_data->p_atomic_operations[i_next_atomic_operation]
161 .i_delay = (int)( sqrt( (-0.1-d_x)*(-0.1-d_x) + (0-d_z)*(0-d_z) )
162 / d_c * i_rate - d_compensation_delay );
163 if( d_x < 0 )
165 p_data->p_atomic_operations[i_next_atomic_operation]
166 .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
168 else if( d_x > 0 )
170 p_data->p_atomic_operations[i_next_atomic_operation]
171 .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
173 else
175 p_data->p_atomic_operations[i_next_atomic_operation]
176 .d_amplitude_factor = d_channel_amplitude_factor / 2;
179 /* Right ear */
180 p_data->p_atomic_operations[i_next_atomic_operation + 1]
181 .i_source_channel_offset = i_source_channel_offset;
182 p_data->p_atomic_operations[i_next_atomic_operation + 1]
183 .i_dest_channel_offset = 1;/* right */
184 p_data->p_atomic_operations[i_next_atomic_operation + 1]
185 .i_delay = (int)( sqrt( (0.1-d_x)*(0.1-d_x) + (0-d_z)*(0-d_z) )
186 / d_c * i_rate - d_compensation_delay );
187 if( d_x < 0 )
189 p_data->p_atomic_operations[i_next_atomic_operation + 1]
190 .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
192 else if( d_x > 0 )
194 p_data->p_atomic_operations[i_next_atomic_operation + 1]
195 .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
197 else
199 p_data->p_atomic_operations[i_next_atomic_operation + 1]
200 .d_amplitude_factor = d_channel_amplitude_factor / 2;
204 static int Init( vlc_object_t *p_this, struct filter_sys_t * p_data,
205 unsigned int i_nb_channels, uint32_t i_physical_channels,
206 unsigned int i_rate )
208 double d_x = var_InheritInteger( p_this, "headphone-dim" );
209 double d_z = d_x;
210 double d_z_rear = -d_x/3;
211 double d_min = 0;
212 unsigned int i_next_atomic_operation;
213 int i_source_channel_offset;
214 unsigned int i;
216 if( var_InheritBool( p_this, "headphone-compensate" ) )
218 /* minimal distance to any speaker */
219 if( i_physical_channels & AOUT_CHAN_REARCENTER )
221 d_min = d_z_rear;
223 else
225 d_min = d_z;
229 /* Number of elementary operations */
230 p_data->i_nb_atomic_operations = i_nb_channels * 2;
231 if( i_physical_channels & AOUT_CHAN_CENTER )
233 p_data->i_nb_atomic_operations += 2;
235 p_data->p_atomic_operations = malloc( sizeof(struct atomic_operation_t)
236 * p_data->i_nb_atomic_operations );
237 if( p_data->p_atomic_operations == NULL )
238 return -1;
240 /* For each virtual speaker, computes elementary wave propagation time
241 * to each ear */
242 i_next_atomic_operation = 0;
243 i_source_channel_offset = 0;
244 if( i_physical_channels & AOUT_CHAN_LEFT )
246 ComputeChannelOperations( p_data , i_rate
247 , i_next_atomic_operation , i_source_channel_offset
248 , -d_x , d_z , d_min , 2.0 / i_nb_channels );
249 i_next_atomic_operation += 2;
250 i_source_channel_offset++;
252 if( i_physical_channels & AOUT_CHAN_RIGHT )
254 ComputeChannelOperations( p_data , i_rate
255 , i_next_atomic_operation , i_source_channel_offset
256 , d_x , d_z , d_min , 2.0 / i_nb_channels );
257 i_next_atomic_operation += 2;
258 i_source_channel_offset++;
260 if( i_physical_channels & AOUT_CHAN_MIDDLELEFT )
262 ComputeChannelOperations( p_data , i_rate
263 , i_next_atomic_operation , i_source_channel_offset
264 , -d_x , 0 , d_min , 1.5 / i_nb_channels );
265 i_next_atomic_operation += 2;
266 i_source_channel_offset++;
268 if( i_physical_channels & AOUT_CHAN_MIDDLERIGHT )
270 ComputeChannelOperations( p_data , i_rate
271 , i_next_atomic_operation , i_source_channel_offset
272 , d_x , 0 , d_min , 1.5 / i_nb_channels );
273 i_next_atomic_operation += 2;
274 i_source_channel_offset++;
276 if( i_physical_channels & AOUT_CHAN_REARLEFT )
278 ComputeChannelOperations( p_data , i_rate
279 , i_next_atomic_operation , i_source_channel_offset
280 , -d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
281 i_next_atomic_operation += 2;
282 i_source_channel_offset++;
284 if( i_physical_channels & AOUT_CHAN_REARRIGHT )
286 ComputeChannelOperations( p_data , i_rate
287 , i_next_atomic_operation , i_source_channel_offset
288 , d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
289 i_next_atomic_operation += 2;
290 i_source_channel_offset++;
292 if( i_physical_channels & AOUT_CHAN_REARCENTER )
294 ComputeChannelOperations( p_data , i_rate
295 , i_next_atomic_operation , i_source_channel_offset
296 , 0 , -d_z , d_min , 1.5 / i_nb_channels );
297 i_next_atomic_operation += 2;
298 i_source_channel_offset++;
300 if( i_physical_channels & AOUT_CHAN_CENTER )
302 /* having two center channels increases the spatialization effect */
303 ComputeChannelOperations( p_data , i_rate
304 , i_next_atomic_operation , i_source_channel_offset
305 , d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
306 i_next_atomic_operation += 2;
307 ComputeChannelOperations( p_data , i_rate
308 , i_next_atomic_operation , i_source_channel_offset
309 , -d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
310 i_next_atomic_operation += 2;
311 i_source_channel_offset++;
313 if( i_physical_channels & AOUT_CHAN_LFE )
315 ComputeChannelOperations( p_data , i_rate
316 , i_next_atomic_operation , i_source_channel_offset
317 , 0 , d_z_rear , d_min , 5.0 / i_nb_channels );
318 i_next_atomic_operation += 2;
319 i_source_channel_offset++;
322 /* Initialize the overflow buffer
323 * we need it because the process induce a delay in the samples */
324 p_data->i_overflow_buffer_size = 0;
325 for( i = 0 ; i < p_data->i_nb_atomic_operations ; i++ )
327 if( p_data->i_overflow_buffer_size
328 < p_data->p_atomic_operations[i].i_delay * 2 * sizeof (int16_t) )
330 p_data->i_overflow_buffer_size
331 = p_data->p_atomic_operations[i].i_delay * 2 * sizeof (int16_t);
334 p_data->p_overflow_buffer = malloc( p_data->i_overflow_buffer_size );
335 if( p_data->p_overflow_buffer == NULL )
337 free( p_data->p_atomic_operations );
338 return -1;
340 memset( p_data->p_overflow_buffer, 0, p_data->i_overflow_buffer_size );
342 /* end */
343 return 0;
346 /*****************************************************************************
347 * OpenFilter
348 *****************************************************************************/
349 static int OpenFilter( vlc_object_t *p_this )
351 filter_t * p_filter = (filter_t *)p_this;
352 filter_sys_t *p_sys = NULL;
354 if( aout_FormatNbChannels( &(p_filter->fmt_in.audio) ) == 1 )
356 /*msg_Dbg( p_filter, "filter discarded (incompatible format)" );*/
357 return VLC_EGENERIC;
360 if( (p_filter->fmt_in.i_codec != VLC_CODEC_S16N) ||
361 (p_filter->fmt_out.i_codec != VLC_CODEC_S16N) )
363 /*msg_Err( p_this, "filter discarded (invalid format)" );*/
364 return VLC_EGENERIC;
367 if( (p_filter->fmt_in.audio.i_format != p_filter->fmt_out.audio.i_format) &&
368 (p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate) &&
369 (p_filter->fmt_in.audio.i_format != VLC_CODEC_S16N) &&
370 (p_filter->fmt_out.audio.i_format != VLC_CODEC_S16N) &&
371 (p_filter->fmt_in.audio.i_bitspersample !=
372 p_filter->fmt_out.audio.i_bitspersample))
374 /*msg_Err( p_this, "couldn't load mono filter" );*/
375 return VLC_EGENERIC;
378 /* Allocate the memory needed to store the module's structure */
379 p_sys = p_filter->p_sys = malloc( sizeof(filter_sys_t) );
380 if( p_sys == NULL )
381 return VLC_EGENERIC;
383 p_sys->b_downmix = var_CreateGetBool( p_this, MONO_CFG "downmix" );
384 p_sys->i_channel_selected =
385 (unsigned int) var_CreateGetInteger( p_this, MONO_CFG "channel" );
387 if( p_sys->b_downmix )
389 msg_Dbg( p_this, "using stereo to mono downmix" );
390 p_filter->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER;
391 p_filter->fmt_out.audio.i_channels = 1;
393 else
395 msg_Dbg( p_this, "using pseudo mono" );
396 p_filter->fmt_out.audio.i_physical_channels =
397 (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT);
398 p_filter->fmt_out.audio.i_channels = 2;
401 p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate;
402 p_filter->fmt_out.audio.i_format = p_filter->fmt_out.i_codec;
404 p_sys->i_nb_channels = aout_FormatNbChannels( &(p_filter->fmt_in.audio) );
405 p_sys->i_bitspersample = p_filter->fmt_out.audio.i_bitspersample;
407 p_sys->i_overflow_buffer_size = 0;
408 p_sys->p_overflow_buffer = NULL;
409 p_sys->i_nb_atomic_operations = 0;
410 p_sys->p_atomic_operations = NULL;
412 if( Init( VLC_OBJECT(p_filter), p_filter->p_sys,
413 aout_FormatNbChannels( &p_filter->fmt_in.audio ),
414 p_filter->fmt_in.audio.i_physical_channels,
415 p_filter->fmt_in.audio.i_rate ) < 0 )
417 var_Destroy( p_this, MONO_CFG "channel" );
418 var_Destroy( p_this, MONO_CFG "downmix" );
419 free( p_sys );
420 return VLC_EGENERIC;
423 p_filter->pf_audio_filter = Convert;
425 msg_Dbg( p_this, "%4.4s->%4.4s, channels %d->%d, bits per sample: %i->%i",
426 (char *)&p_filter->fmt_in.i_codec,
427 (char *)&p_filter->fmt_out.i_codec,
428 p_filter->fmt_in.audio.i_physical_channels,
429 p_filter->fmt_out.audio.i_physical_channels,
430 p_filter->fmt_in.audio.i_bitspersample,
431 p_filter->fmt_out.audio.i_bitspersample );
433 return VLC_SUCCESS;
436 /*****************************************************************************
437 * CloseFilter
438 *****************************************************************************/
439 static void CloseFilter( vlc_object_t *p_this)
441 filter_t *p_filter = (filter_t *) p_this;
442 filter_sys_t *p_sys = p_filter->p_sys;
444 var_Destroy( p_this, MONO_CFG "channel" );
445 var_Destroy( p_this, MONO_CFG "downmix" );
446 free( p_sys->p_atomic_operations );
447 free( p_sys->p_overflow_buffer );
448 free( p_sys );
451 /*****************************************************************************
452 * Convert
453 *****************************************************************************/
454 static block_t *Convert( filter_t *p_filter, block_t *p_block )
456 aout_filter_t aout_filter;
457 aout_buffer_t in_buf, out_buf;
458 block_t *p_out = NULL;
459 unsigned int i_samples;
460 int i_out_size;
462 if( !p_block || !p_block->i_nb_samples )
464 if( p_block )
465 block_Release( p_block );
466 return NULL;
469 i_out_size = p_block->i_nb_samples * p_filter->p_sys->i_bitspersample/8 *
470 aout_FormatNbChannels( &(p_filter->fmt_out.audio) );
472 p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size );
473 if( !p_out )
475 msg_Warn( p_filter, "can't get output buffer" );
476 block_Release( p_block );
477 return NULL;
479 p_out->i_nb_samples =
480 (p_block->i_nb_samples / p_filter->p_sys->i_nb_channels) *
481 aout_FormatNbChannels( &(p_filter->fmt_out.audio) );
482 p_out->i_dts = p_block->i_dts;
483 p_out->i_pts = p_block->i_pts;
484 p_out->i_length = p_block->i_length;
486 aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys;
487 aout_filter.fmt_in.audio = p_filter->fmt_in.audio;
488 aout_filter.fmt_in.audio.i_format = p_filter->fmt_in.i_codec;
489 aout_filter.fmt_out.audio = p_filter->fmt_out.audio;
490 aout_filter.fmt_out.audio.i_format = p_filter->fmt_out.i_codec;
492 in_buf.p_buffer = p_block->p_buffer;
493 in_buf.i_buffer = p_block->i_buffer;
494 in_buf.i_nb_samples = p_block->i_nb_samples;
496 #if 0
497 unsigned int i_in_size = in_buf.i_nb_samples * (p_filter->p_sys->i_bitspersample/8) *
498 aout_FormatNbChannels( &(p_filter->fmt_in.audio) );
499 if( (in_buf.i_buffer != i_in_size) && ((i_in_size % 32) != 0) ) /* is it word aligned?? */
501 msg_Err( p_filter, "input buffer is not word aligned" );
502 /* Fix output buffer to be word aligned */
504 #endif
506 out_buf.p_buffer = p_out->p_buffer;
507 out_buf.i_buffer = p_out->i_buffer;
508 out_buf.i_nb_samples = p_out->i_nb_samples;
510 memset( p_out->p_buffer, 0, i_out_size );
511 if( p_filter->p_sys->b_downmix )
513 stereo2mono_downmix( &aout_filter, &in_buf, &out_buf );
514 i_samples = mono( &aout_filter, &out_buf, &in_buf );
516 else
518 i_samples = stereo_to_mono( &aout_filter, &out_buf, &in_buf );
521 p_out->i_buffer = out_buf.i_buffer;
522 p_out->i_nb_samples = out_buf.i_nb_samples;
524 block_Release( p_block );
525 return p_out;
528 /* stereo2mono_downmix - stereo channels into one mono channel.
529 * Code taken from modules/audio_filter/channel_mixer/headphone.c
530 * converted from float into int16_t based downmix
531 * Written by Boris Dorès <babal@via.ecp.fr>
533 static void stereo2mono_downmix( aout_filter_t * p_filter,
534 aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
536 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
538 int i_input_nb = aout_FormatNbChannels( &p_filter->fmt_in.audio );
539 int i_output_nb = aout_FormatNbChannels( &p_filter->fmt_out.audio );
541 int16_t * p_in = (int16_t*) p_in_buf->p_buffer;
542 uint8_t * p_out;
543 uint8_t * p_overflow;
544 uint8_t * p_slide;
546 size_t i_overflow_size; /* in bytes */
547 size_t i_out_size; /* in bytes */
549 unsigned int i, j;
551 int i_source_channel_offset;
552 int i_dest_channel_offset;
553 unsigned int i_delay;
554 double d_amplitude_factor;
556 /* out buffer characterisitcs */
557 p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
558 p_out_buf->i_buffer = p_in_buf->i_buffer * i_output_nb / i_input_nb;
559 p_out = p_out_buf->p_buffer;
560 i_out_size = p_out_buf->i_buffer;
562 /* Slide the overflow buffer */
563 p_overflow = p_sys->p_overflow_buffer;
564 i_overflow_size = p_sys->i_overflow_buffer_size;
566 if ( i_out_size > i_overflow_size )
567 memcpy( p_out, p_overflow, i_overflow_size );
568 else
569 memcpy( p_out, p_overflow, i_out_size );
571 p_slide = p_sys->p_overflow_buffer;
572 while( p_slide < p_overflow + i_overflow_size )
574 if( p_slide + i_out_size < p_overflow + i_overflow_size )
576 memset( p_slide, 0, i_out_size );
577 if( p_slide + 2 * i_out_size < p_overflow + i_overflow_size )
578 memcpy( p_slide, p_slide + i_out_size, i_out_size );
579 else
580 memcpy( p_slide, p_slide + i_out_size,
581 p_overflow + i_overflow_size - ( p_slide + i_out_size ) );
583 else
585 memset( p_slide, 0, p_overflow + i_overflow_size - p_slide );
587 p_slide += i_out_size;
590 /* apply the atomic operations */
591 for( i = 0; i < p_sys->i_nb_atomic_operations; i++ )
593 /* shorter variable names */
594 i_source_channel_offset
595 = p_sys->p_atomic_operations[i].i_source_channel_offset;
596 i_dest_channel_offset
597 = p_sys->p_atomic_operations[i].i_dest_channel_offset;
598 i_delay = p_sys->p_atomic_operations[i].i_delay;
599 d_amplitude_factor
600 = p_sys->p_atomic_operations[i].d_amplitude_factor;
602 if( p_out_buf->i_nb_samples > i_delay )
604 /* current buffer coefficients */
605 for( j = 0; j < p_out_buf->i_nb_samples - i_delay; j++ )
607 ((int16_t*)p_out)[ (i_delay+j)*i_output_nb + i_dest_channel_offset ]
608 += p_in[ j * i_input_nb + i_source_channel_offset ]
609 * d_amplitude_factor;
612 /* overflow buffer coefficients */
613 for( j = 0; j < i_delay; j++ )
615 ((int16_t*)p_overflow)[ j*i_output_nb + i_dest_channel_offset ]
616 += p_in[ (p_out_buf->i_nb_samples - i_delay + j)
617 * i_input_nb + i_source_channel_offset ]
618 * d_amplitude_factor;
621 else
623 /* overflow buffer coefficients only */
624 for( j = 0; j < p_out_buf->i_nb_samples; j++ )
626 ((int16_t*)p_overflow)[ (i_delay - p_out_buf->i_nb_samples + j)
627 * i_output_nb + i_dest_channel_offset ]
628 += p_in[ j * i_input_nb + i_source_channel_offset ]
629 * d_amplitude_factor;
635 /* Simple stereo to mono mixing. */
636 static unsigned int mono( aout_filter_t *p_filter,
637 aout_buffer_t *p_output, aout_buffer_t *p_input )
639 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
640 int16_t *p_in, *p_out;
641 unsigned int n = 0, r = 0;
643 p_in = (int16_t *) p_input->p_buffer;
644 p_out = (int16_t *) p_output->p_buffer;
646 while( n < (p_input->i_nb_samples * p_sys->i_nb_channels) )
648 p_out[r] = (p_in[n] + p_in[n+1]) >> 1;
649 r++;
650 n += 2;
652 return r;
655 /* Simple stereo to mono mixing. */
656 static unsigned int stereo_to_mono( aout_filter_t *p_filter,
657 aout_buffer_t *p_output, aout_buffer_t *p_input )
659 filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
660 int16_t *p_in, *p_out;
661 unsigned int n;
663 p_in = (int16_t *) p_input->p_buffer;
664 p_out = (int16_t *) p_output->p_buffer;
666 for( n = 0; n < (p_input->i_nb_samples * p_sys->i_nb_channels); n++ )
668 /* Fake real mono. */
669 if( p_sys->i_channel_selected == -1)
671 p_out[n] = p_out[n+1] = (p_in[n] + p_in[n+1]) >> 1;
672 n++;
674 else if( (n % p_sys->i_nb_channels) == (unsigned int) p_sys->i_channel_selected )
676 p_out[n] = p_out[n+1] = p_in[n];
679 return n;