mono.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:25k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mono.c : stereo2mono downmixsimple channel mixer plug-in
  3.  *****************************************************************************
  4.  * Copyright (C) 2006 M2X
  5.  * $Id: 131a118c35061fa3066bdf41b7e981d9c8af019c $
  6.  *
  7.  * Authors: Jean-Paul Saman <jpsaman at m2x dot nl>
  8.  *
  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.
  13.  *
  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.
  18.  *
  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.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <math.h>                                        /* sqrt */
  30. #include <stdint.h>                                         /* int16_t .. */
  31. #ifdef HAVE_UNISTD_H
  32. #   include <unistd.h>
  33. #endif
  34. #include <vlc_common.h>
  35. #include <vlc_plugin.h>
  36. #include <vlc_es.h>
  37. #include <vlc_block.h>
  38. #include <vlc_filter.h>
  39. #include <vlc_aout.h>
  40. /*****************************************************************************
  41.  * Local prototypes
  42.  *****************************************************************************/
  43. static int  OpenFilter    ( vlc_object_t * );
  44. static void CloseFilter   ( vlc_object_t * );
  45. static block_t *Convert( filter_t *p_filter, block_t *p_block );
  46. static unsigned int stereo_to_mono( aout_filter_t *, aout_buffer_t *,
  47.                                     aout_buffer_t * );
  48. static unsigned int mono( aout_filter_t *, aout_buffer_t *, aout_buffer_t * );
  49. static void stereo2mono_downmix( aout_filter_t *, aout_buffer_t *,
  50.                                  aout_buffer_t * );
  51. /*****************************************************************************
  52.  * Local structures
  53.  *****************************************************************************/
  54. struct atomic_operation_t
  55. {
  56.     int i_source_channel_offset;
  57.     int i_dest_channel_offset;
  58.     unsigned int i_delay;/* in sample unit */
  59.     double d_amplitude_factor;
  60. };
  61. struct filter_sys_t
  62. {
  63.     bool b_downmix;
  64.     unsigned int i_nb_channels; /* number of int16_t per sample */
  65.     int i_channel_selected;
  66.     int i_bitspersample;
  67.     size_t i_overflow_buffer_size;/* in bytes */
  68.     uint8_t * p_overflow_buffer;
  69.     unsigned int i_nb_atomic_operations;
  70.     struct atomic_operation_t * p_atomic_operations;
  71. };
  72. #define MONO_DOWNMIX_TEXT N_("Use downmix algorithm")
  73. #define MONO_DOWNMIX_LONGTEXT N_("This option selects a stereo to mono " 
  74.     "downmix algorithm that is used in the headphone channel mixer. It " 
  75.     "gives the effect of standing in a room full of speakers." )
  76. #define MONO_CHANNEL_TEXT N_("Select channel to keep")
  77. #define MONO_CHANNEL_LONGTEXT N_("This option silences all other channels " 
  78.     "except the selected channel. Choose one from (0=left, 1=right, " 
  79.     "2=rear left, 3=rear right, 4=center, 5=left front)")
  80. static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5 };
  81. static const char *const ppsz_pos_descriptions[] =
  82. { N_("Left"), N_("Right"), N_("Left rear"), N_("Right rear"), N_("Center"),
  83.   N_("Left front") };
  84. /* our internal channel order (WG-4 order) */
  85. static const uint32_t pi_channels_out[] =
  86. { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
  87.   AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
  88. #define MONO_CFG "sout-mono-"
  89. /*****************************************************************************
  90.  * Module descriptor
  91.  *****************************************************************************/
  92. vlc_module_begin ()
  93.     set_description( N_("Audio filter for stereo to mono conversion") )
  94.     set_capability( "audio filter2", 2 )
  95.     set_category( CAT_AUDIO )
  96.     set_subcategory( SUBCAT_AUDIO_AFILTER )
  97.     set_callbacks( OpenFilter, CloseFilter )
  98.     set_shortname( "Mono" )
  99.     add_bool( MONO_CFG "downmix", true, NULL, MONO_DOWNMIX_TEXT,
  100.               MONO_DOWNMIX_LONGTEXT, false )
  101.     add_integer( MONO_CFG "channel", -1, NULL, MONO_CHANNEL_TEXT,
  102.         MONO_CHANNEL_LONGTEXT, false )
  103.         change_integer_list( pi_pos_values, ppsz_pos_descriptions, NULL )
  104. vlc_module_end ()
  105. /* Init() and ComputeChannelOperations() -
  106.  * Code taken from modules/audio_filter/channel_mixer/headphone.c
  107.  * converted from float into int16_t based downmix
  108.  * Written by Boris Dorès <babal@via.ecp.fr>
  109.  */
  110. /*****************************************************************************
  111.  * Init: initialize internal data structures
  112.  * and computes the needed atomic operations
  113.  *****************************************************************************/
  114. /* x and z represent the coordinates of the virtual speaker
  115.  *  relatively to the center of the listener's head, measured in meters :
  116.  *
  117.  *  left              right
  118.  *Z
  119.  *-
  120.  *a          head
  121.  *x
  122.  *i
  123.  *s
  124.  *  rear left    rear right
  125.  *
  126.  *          x-axis
  127.  *  */
  128. static void ComputeChannelOperations( struct filter_sys_t * p_data,
  129.         unsigned int i_rate, unsigned int i_next_atomic_operation,
  130.         int i_source_channel_offset, double d_x, double d_z,
  131.         double d_compensation_length, double d_channel_amplitude_factor )
  132. {
  133.     double d_c = 340; /*sound celerity (unit: m/s)*/
  134.     double d_compensation_delay = (d_compensation_length-0.1) / d_c * i_rate;
  135.     /* Left ear */
  136.     p_data->p_atomic_operations[i_next_atomic_operation]
  137.         .i_source_channel_offset = i_source_channel_offset;
  138.     p_data->p_atomic_operations[i_next_atomic_operation]
  139.         .i_dest_channel_offset = 0;/* left */
  140.     p_data->p_atomic_operations[i_next_atomic_operation]
  141.         .i_delay = (int)( sqrt( (-0.1-d_x)*(-0.1-d_x) + (0-d_z)*(0-d_z) )
  142.                           / d_c * i_rate - d_compensation_delay );
  143.     if( d_x < 0 )
  144.     {
  145.         p_data->p_atomic_operations[i_next_atomic_operation]
  146.             .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
  147.     }
  148.     else if( d_x > 0 )
  149.     {
  150.         p_data->p_atomic_operations[i_next_atomic_operation]
  151.             .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
  152.     }
  153.     else
  154.     {
  155.         p_data->p_atomic_operations[i_next_atomic_operation]
  156.             .d_amplitude_factor = d_channel_amplitude_factor / 2;
  157.     }
  158.     /* Right ear */
  159.     p_data->p_atomic_operations[i_next_atomic_operation + 1]
  160.         .i_source_channel_offset = i_source_channel_offset;
  161.     p_data->p_atomic_operations[i_next_atomic_operation + 1]
  162.         .i_dest_channel_offset = 1;/* right */
  163.     p_data->p_atomic_operations[i_next_atomic_operation + 1]
  164.         .i_delay = (int)( sqrt( (0.1-d_x)*(0.1-d_x) + (0-d_z)*(0-d_z) )
  165.                           / d_c * i_rate - d_compensation_delay );
  166.     if( d_x < 0 )
  167.     {
  168.         p_data->p_atomic_operations[i_next_atomic_operation + 1]
  169.             .d_amplitude_factor = d_channel_amplitude_factor * 0.9 / 2;
  170.     }
  171.     else if( d_x > 0 )
  172.     {
  173.         p_data->p_atomic_operations[i_next_atomic_operation + 1]
  174.             .d_amplitude_factor = d_channel_amplitude_factor * 1.1 / 2;
  175.     }
  176.     else
  177.     {
  178.         p_data->p_atomic_operations[i_next_atomic_operation + 1]
  179.             .d_amplitude_factor = d_channel_amplitude_factor / 2;
  180.     }
  181. }
  182. static int Init( vlc_object_t *p_this, struct filter_sys_t * p_data,
  183.                  unsigned int i_nb_channels, uint32_t i_physical_channels,
  184.                  unsigned int i_rate )
  185. {
  186.     double d_x = config_GetInt( p_this, "headphone-dim" );
  187.     double d_z = d_x;
  188.     double d_z_rear = -d_x/3;
  189.     double d_min = 0;
  190.     unsigned int i_next_atomic_operation;
  191.     int i_source_channel_offset;
  192.     unsigned int i;
  193.     if( config_GetInt( p_this, "headphone-compensate" ) )
  194.     {
  195.         /* minimal distance to any speaker */
  196.         if( i_physical_channels & AOUT_CHAN_REARCENTER )
  197.         {
  198.             d_min = d_z_rear;
  199.         }
  200.         else
  201.         {
  202.             d_min = d_z;
  203.         }
  204.     }
  205.     /* Number of elementary operations */
  206.     p_data->i_nb_atomic_operations = i_nb_channels * 2;
  207.     if( i_physical_channels & AOUT_CHAN_CENTER )
  208.     {
  209.         p_data->i_nb_atomic_operations += 2;
  210.     }
  211.     p_data->p_atomic_operations = malloc( sizeof(struct atomic_operation_t)
  212.             * p_data->i_nb_atomic_operations );
  213.     if( p_data->p_atomic_operations == NULL )
  214.         return -1;
  215.     /* For each virtual speaker, computes elementary wave propagation time
  216.      * to each ear */
  217.     i_next_atomic_operation = 0;
  218.     i_source_channel_offset = 0;
  219.     if( i_physical_channels & AOUT_CHAN_LEFT )
  220.     {
  221.         ComputeChannelOperations( p_data , i_rate
  222.                 , i_next_atomic_operation , i_source_channel_offset
  223.                 , -d_x , d_z , d_min , 2.0 / i_nb_channels );
  224.         i_next_atomic_operation += 2;
  225.         i_source_channel_offset++;
  226.     }
  227.     if( i_physical_channels & AOUT_CHAN_RIGHT )
  228.     {
  229.         ComputeChannelOperations( p_data , i_rate
  230.                 , i_next_atomic_operation , i_source_channel_offset
  231.                 , d_x , d_z , d_min , 2.0 / i_nb_channels );
  232.         i_next_atomic_operation += 2;
  233.         i_source_channel_offset++;
  234.     }
  235.     if( i_physical_channels & AOUT_CHAN_MIDDLELEFT )
  236.     {
  237.         ComputeChannelOperations( p_data , i_rate
  238.                 , i_next_atomic_operation , i_source_channel_offset
  239.                 , -d_x , 0 , d_min , 1.5 / i_nb_channels );
  240.         i_next_atomic_operation += 2;
  241.         i_source_channel_offset++;
  242.     }
  243.     if( i_physical_channels & AOUT_CHAN_MIDDLERIGHT )
  244.     {
  245.         ComputeChannelOperations( p_data , i_rate
  246.                 , i_next_atomic_operation , i_source_channel_offset
  247.                 , d_x , 0 , d_min , 1.5 / i_nb_channels );
  248.         i_next_atomic_operation += 2;
  249.         i_source_channel_offset++;
  250.     }
  251.     if( i_physical_channels & AOUT_CHAN_REARLEFT )
  252.     {
  253.         ComputeChannelOperations( p_data , i_rate
  254.                 , i_next_atomic_operation , i_source_channel_offset
  255.                 , -d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
  256.         i_next_atomic_operation += 2;
  257.         i_source_channel_offset++;
  258.     }
  259.     if( i_physical_channels & AOUT_CHAN_REARRIGHT )
  260.     {
  261.         ComputeChannelOperations( p_data , i_rate
  262.                 , i_next_atomic_operation , i_source_channel_offset
  263.                 , d_x , d_z_rear , d_min , 1.5 / i_nb_channels );
  264.         i_next_atomic_operation += 2;
  265.         i_source_channel_offset++;
  266.     }
  267.     if( i_physical_channels & AOUT_CHAN_REARCENTER )
  268.     {
  269.         ComputeChannelOperations( p_data , i_rate
  270.                 , i_next_atomic_operation , i_source_channel_offset
  271.                 , 0 , -d_z , d_min , 1.5 / i_nb_channels );
  272.         i_next_atomic_operation += 2;
  273.         i_source_channel_offset++;
  274.     }
  275.     if( i_physical_channels & AOUT_CHAN_CENTER )
  276.     {
  277.         /* having two center channels increases the spatialization effect */
  278.         ComputeChannelOperations( p_data , i_rate
  279.                 , i_next_atomic_operation , i_source_channel_offset
  280.                 , d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
  281.         i_next_atomic_operation += 2;
  282.         ComputeChannelOperations( p_data , i_rate
  283.                 , i_next_atomic_operation , i_source_channel_offset
  284.                 , -d_x / 5.0 , d_z , d_min , 0.75 / i_nb_channels );
  285.         i_next_atomic_operation += 2;
  286.         i_source_channel_offset++;
  287.     }
  288.     if( i_physical_channels & AOUT_CHAN_LFE )
  289.     {
  290.         ComputeChannelOperations( p_data , i_rate
  291.                 , i_next_atomic_operation , i_source_channel_offset
  292.                 , 0 , d_z_rear , d_min , 5.0 / i_nb_channels );
  293.         i_next_atomic_operation += 2;
  294.         i_source_channel_offset++;
  295.     }
  296.     /* Initialize the overflow buffer
  297.      * we need it because the process induce a delay in the samples */
  298.     p_data->i_overflow_buffer_size = 0;
  299.     for( i = 0 ; i < p_data->i_nb_atomic_operations ; i++ )
  300.     {
  301.         if( p_data->i_overflow_buffer_size
  302.                 < p_data->p_atomic_operations[i].i_delay * 2 * sizeof (int16_t) )
  303.         {
  304.             p_data->i_overflow_buffer_size
  305.                 = p_data->p_atomic_operations[i].i_delay * 2 * sizeof (int16_t);
  306.         }
  307.     }
  308.     p_data->p_overflow_buffer = malloc( p_data->i_overflow_buffer_size );
  309.     if( p_data->p_overflow_buffer == NULL )
  310.     {
  311.         free( p_data->p_atomic_operations );
  312.         return -1;
  313.     }
  314.     memset( p_data->p_overflow_buffer, 0, p_data->i_overflow_buffer_size );
  315.     /* end */
  316.     return 0;
  317. }
  318. /*****************************************************************************
  319.  * OpenFilter
  320.  *****************************************************************************/
  321. static int OpenFilter( vlc_object_t *p_this )
  322. {
  323.     filter_t * p_filter = (filter_t *)p_this;
  324.     filter_sys_t *p_sys = NULL;
  325.     if( aout_FormatNbChannels( &(p_filter->fmt_in.audio) ) == 1 )
  326.     {
  327.         /*msg_Dbg( p_filter, "filter discarded (incompatible format)" );*/
  328.         return VLC_EGENERIC;
  329.     }
  330.     if( (p_filter->fmt_in.i_codec != AOUT_FMT_S16_NE) ||
  331.         (p_filter->fmt_out.i_codec != AOUT_FMT_S16_NE) )
  332.     {
  333.         /*msg_Err( p_this, "filter discarded (invalid format)" );*/
  334.         return VLC_EGENERIC;
  335.     }
  336.     if( (p_filter->fmt_in.audio.i_format != p_filter->fmt_out.audio.i_format) &&
  337.         (p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate) &&
  338.         (p_filter->fmt_in.audio.i_format != AOUT_FMT_S16_NE) &&
  339.         (p_filter->fmt_out.audio.i_format != AOUT_FMT_S16_NE) &&
  340.         (p_filter->fmt_in.audio.i_bitspersample !=
  341.                                     p_filter->fmt_out.audio.i_bitspersample))
  342.     {
  343.         /*msg_Err( p_this, "couldn't load mono filter" );*/
  344.         return VLC_EGENERIC;
  345.     }
  346.     /* Allocate the memory needed to store the module's structure */
  347.     p_sys = p_filter->p_sys = malloc( sizeof(filter_sys_t) );
  348.     if( p_sys == NULL )
  349.         return VLC_EGENERIC;
  350.     var_Create( p_this, MONO_CFG "downmix",
  351.                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
  352.     p_sys->b_downmix = var_GetBool( p_this, MONO_CFG "downmix" );
  353.     var_Create( p_this, MONO_CFG "channel",
  354.                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  355.     p_sys->i_channel_selected =
  356.             (unsigned int) var_GetInteger( p_this, MONO_CFG "channel" );
  357.     if( p_sys->b_downmix )
  358.     {
  359.         msg_Dbg( p_this, "using stereo to mono downmix" );
  360.         p_filter->fmt_out.audio.i_physical_channels = AOUT_CHAN_CENTER;
  361.         p_filter->fmt_out.audio.i_channels = 1;
  362.     }
  363.     else
  364.     {
  365.         msg_Dbg( p_this, "using pseudo mono" );
  366.         p_filter->fmt_out.audio.i_physical_channels =
  367.                             (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT);
  368.         p_filter->fmt_out.audio.i_channels = 2;
  369.     }
  370.     p_filter->fmt_out.audio.i_rate = p_filter->fmt_in.audio.i_rate;
  371.     p_filter->fmt_out.audio.i_format = p_filter->fmt_out.i_codec;
  372.     p_sys->i_nb_channels = aout_FormatNbChannels( &(p_filter->fmt_in.audio) );
  373.     p_sys->i_bitspersample = p_filter->fmt_out.audio.i_bitspersample;
  374.     p_sys->i_overflow_buffer_size = 0;
  375.     p_sys->p_overflow_buffer = NULL;
  376.     p_sys->i_nb_atomic_operations = 0;
  377.     p_sys->p_atomic_operations = NULL;
  378.     if( Init( VLC_OBJECT(p_filter), p_filter->p_sys,
  379.               aout_FormatNbChannels( &p_filter->fmt_in.audio ),
  380.               p_filter->fmt_in.audio.i_physical_channels,
  381.               p_filter->fmt_in.audio.i_rate ) < 0 )
  382.     {
  383.         var_Destroy( p_this, MONO_CFG "channel" );
  384.         var_Destroy( p_this, MONO_CFG "downmix" );
  385.         free( p_sys );
  386.         return VLC_EGENERIC;
  387.     }
  388.     p_filter->pf_audio_filter = Convert;
  389.     msg_Dbg( p_this, "%4.4s->%4.4s, channels %d->%d, bits per sample: %i->%i",
  390.              (char *)&p_filter->fmt_in.i_codec,
  391.              (char *)&p_filter->fmt_out.i_codec,
  392.              p_filter->fmt_in.audio.i_physical_channels,
  393.              p_filter->fmt_out.audio.i_physical_channels,
  394.              p_filter->fmt_in.audio.i_bitspersample,
  395.              p_filter->fmt_out.audio.i_bitspersample );
  396.     return VLC_SUCCESS;
  397. }
  398. /*****************************************************************************
  399.  * CloseFilter
  400.  *****************************************************************************/
  401. static void CloseFilter( vlc_object_t *p_this)
  402. {
  403.     filter_t *p_filter = (filter_t *) p_this;
  404.     filter_sys_t *p_sys = p_filter->p_sys;
  405.     var_Destroy( p_this, MONO_CFG "channel" );
  406.     var_Destroy( p_this, MONO_CFG "downmix" );
  407.     free( p_sys->p_atomic_operations );
  408.     free( p_sys->p_overflow_buffer );
  409.     free( p_sys );
  410. }
  411. /*****************************************************************************
  412.  * Convert
  413.  *****************************************************************************/
  414. static block_t *Convert( filter_t *p_filter, block_t *p_block )
  415. {
  416.     aout_filter_t aout_filter;
  417.     aout_buffer_t in_buf, out_buf;
  418.     block_t *p_out = NULL;
  419.     unsigned int i_samples;
  420.     int i_out_size;
  421.     if( !p_block || !p_block->i_samples )
  422.     {
  423.         if( p_block )
  424.             block_Release( p_block );
  425.         return NULL;
  426.     }
  427.     i_out_size = p_block->i_samples * p_filter->p_sys->i_bitspersample/8 *
  428.                  aout_FormatNbChannels( &(p_filter->fmt_out.audio) );
  429.     p_out = p_filter->pf_audio_buffer_new( p_filter, i_out_size );
  430.     if( !p_out )
  431.     {
  432.         msg_Warn( p_filter, "can't get output buffer" );
  433.         block_Release( p_block );
  434.         return NULL;
  435.     }
  436.     p_out->i_samples = (p_block->i_samples / p_filter->p_sys->i_nb_channels) *
  437.                        aout_FormatNbChannels( &(p_filter->fmt_out.audio) );
  438.     p_out->i_dts = p_block->i_dts;
  439.     p_out->i_pts = p_block->i_pts;
  440.     p_out->i_length = p_block->i_length;
  441.     aout_filter.p_sys = (struct aout_filter_sys_t *)p_filter->p_sys;
  442.     aout_filter.input = p_filter->fmt_in.audio;
  443.     aout_filter.input.i_format = p_filter->fmt_in.i_codec;
  444.     aout_filter.output = p_filter->fmt_out.audio;
  445.     aout_filter.output.i_format = p_filter->fmt_out.i_codec;
  446.     in_buf.p_buffer = p_block->p_buffer;
  447.     in_buf.i_nb_bytes = p_block->i_buffer;
  448.     in_buf.i_nb_samples = p_block->i_samples;
  449. #if 0
  450.     unsigned int i_in_size = in_buf.i_nb_samples  * (p_filter->p_sys->i_bitspersample/8) *
  451.                              aout_FormatNbChannels( &(p_filter->fmt_in.audio) );
  452.     if( (in_buf.i_nb_bytes != i_in_size) && ((i_in_size % 32) != 0) ) /* is it word aligned?? */
  453.     {
  454.         msg_Err( p_filter, "input buffer is not word aligned" );
  455.         /* Fix output buffer to be word aligned */
  456.     }
  457. #endif
  458.     out_buf.p_buffer = p_out->p_buffer;
  459.     out_buf.i_nb_bytes = p_out->i_buffer;
  460.     out_buf.i_nb_samples = p_out->i_samples;
  461.     memset( p_out->p_buffer, 0, i_out_size );
  462.     if( p_filter->p_sys->b_downmix )
  463.     {
  464.         stereo2mono_downmix( &aout_filter, &in_buf, &out_buf );
  465.         i_samples = mono( &aout_filter, &out_buf, &in_buf );
  466.     }
  467.     else
  468.     {
  469.         i_samples = stereo_to_mono( &aout_filter, &out_buf, &in_buf );
  470.     }
  471.     p_out->i_buffer = out_buf.i_nb_bytes;
  472.     p_out->i_samples = out_buf.i_nb_samples;
  473.     block_Release( p_block );
  474.     return p_out;
  475. }
  476. /* stereo2mono_downmix - stereo channels into one mono channel.
  477.  * Code taken from modules/audio_filter/channel_mixer/headphone.c
  478.  * converted from float into int16_t based downmix
  479.  * Written by Boris Dorès <babal@via.ecp.fr>
  480.  */
  481. static void stereo2mono_downmix( aout_filter_t * p_filter,
  482.                             aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
  483. {
  484.     filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
  485.     int i_input_nb = aout_FormatNbChannels( &p_filter->input );
  486.     int i_output_nb = aout_FormatNbChannels( &p_filter->output );
  487.     int16_t * p_in = (int16_t*) p_in_buf->p_buffer;
  488.     uint8_t * p_out;
  489.     uint8_t * p_overflow;
  490.     uint8_t * p_slide;
  491.     size_t i_overflow_size;     /* in bytes */
  492.     size_t i_out_size;          /* in bytes */
  493.     unsigned int i, j;
  494.     int i_source_channel_offset;
  495.     int i_dest_channel_offset;
  496.     unsigned int i_delay;
  497.     double d_amplitude_factor;
  498.     /* out buffer characterisitcs */
  499.     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
  500.     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * i_output_nb / i_input_nb;
  501.     p_out = p_out_buf->p_buffer;
  502.     i_out_size = p_out_buf->i_nb_bytes;
  503.     if( p_sys != NULL )
  504.     {
  505.         /* Slide the overflow buffer */
  506.         p_overflow = p_sys->p_overflow_buffer;
  507.         i_overflow_size = p_sys->i_overflow_buffer_size;
  508.         if ( i_out_size > i_overflow_size )
  509.             memcpy( p_out, p_overflow, i_overflow_size );
  510.         else
  511.             memcpy( p_out, p_overflow, i_out_size );
  512.         p_slide = p_sys->p_overflow_buffer;
  513.         while( p_slide < p_overflow + i_overflow_size )
  514.         {
  515.             if( p_slide + i_out_size < p_overflow + i_overflow_size )
  516.             {
  517.                 memset( p_slide, 0, i_out_size );
  518.                 if( p_slide + 2 * i_out_size < p_overflow + i_overflow_size )
  519.                     memcpy( p_slide, p_slide + i_out_size, i_out_size );
  520.                 else
  521.                     memcpy( p_slide, p_slide + i_out_size,
  522.                             p_overflow + i_overflow_size - ( p_slide + i_out_size ) );
  523.             }
  524.             else
  525.             {
  526.                 memset( p_slide, 0, p_overflow + i_overflow_size - p_slide );
  527.             }
  528.             p_slide += i_out_size;
  529.         }
  530.         /* apply the atomic operations */
  531.         for( i = 0; i < p_sys->i_nb_atomic_operations; i++ )
  532.         {
  533.             /* shorter variable names */
  534.             i_source_channel_offset
  535.                 = p_sys->p_atomic_operations[i].i_source_channel_offset;
  536.             i_dest_channel_offset
  537.                 = p_sys->p_atomic_operations[i].i_dest_channel_offset;
  538.             i_delay = p_sys->p_atomic_operations[i].i_delay;
  539.             d_amplitude_factor
  540.                 = p_sys->p_atomic_operations[i].d_amplitude_factor;
  541.             if( p_out_buf->i_nb_samples > i_delay )
  542.             {
  543.                 /* current buffer coefficients */
  544.                 for( j = 0; j < p_out_buf->i_nb_samples - i_delay; j++ )
  545.                 {
  546.                     ((int16_t*)p_out)[ (i_delay+j)*i_output_nb + i_dest_channel_offset ]
  547.                         += p_in[ j * i_input_nb + i_source_channel_offset ]
  548.                            * d_amplitude_factor;
  549.                 }
  550.                 /* overflow buffer coefficients */
  551.                 for( j = 0; j < i_delay; j++ )
  552.                 {
  553.                     ((int16_t*)p_overflow)[ j*i_output_nb + i_dest_channel_offset ]
  554.                         += p_in[ (p_out_buf->i_nb_samples - i_delay + j)
  555.                            * i_input_nb + i_source_channel_offset ]
  556.                            * d_amplitude_factor;
  557.                 }
  558.             }
  559.             else
  560.             {
  561.                 /* overflow buffer coefficients only */
  562.                 for( j = 0; j < p_out_buf->i_nb_samples; j++ )
  563.                 {
  564.                     ((int16_t*)p_overflow)[ (i_delay - p_out_buf->i_nb_samples + j)
  565.                         * i_output_nb + i_dest_channel_offset ]
  566.                         += p_in[ j * i_input_nb + i_source_channel_offset ]
  567.                            * d_amplitude_factor;
  568.                 }
  569.             }
  570.         }
  571.     }
  572.     else
  573.     {
  574.         memset( p_out, 0, i_out_size );
  575.     }
  576. }
  577. /* Simple stereo to mono mixing. */
  578. static unsigned int mono( aout_filter_t *p_filter,
  579.                           aout_buffer_t *p_output, aout_buffer_t *p_input )
  580. {
  581.     filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
  582.     int16_t *p_in, *p_out;
  583.     unsigned int n = 0, r = 0;
  584.     p_in = (int16_t *) p_input->p_buffer;
  585.     p_out = (int16_t *) p_output->p_buffer;
  586.     while( n < (p_input->i_nb_samples * p_sys->i_nb_channels) )
  587.     {
  588.         p_out[r] = (p_in[n] + p_in[n+1]) >> 1;
  589.         r++;
  590.         n += 2;
  591.     }
  592.     return r;
  593. }
  594. /* Simple stereo to mono mixing. */
  595. static unsigned int stereo_to_mono( aout_filter_t *p_filter,
  596.                                     aout_buffer_t *p_output, aout_buffer_t *p_input )
  597. {
  598.     filter_sys_t *p_sys = (filter_sys_t *)p_filter->p_sys;
  599.     int16_t *p_in, *p_out;
  600.     unsigned int n;
  601.     p_in = (int16_t *) p_input->p_buffer;
  602.     p_out = (int16_t *) p_output->p_buffer;
  603.     for( n = 0; n < (p_input->i_nb_samples * p_sys->i_nb_channels); n++ )
  604.     {
  605.         /* Fake real mono. */
  606.         if( p_sys->i_channel_selected == -1)
  607.         {
  608.             p_out[n] = p_out[n+1] = (p_in[n] + p_in[n+1]) >> 1;
  609.             n++;
  610.         }
  611.         else if( (n % p_sys->i_nb_channels) == (unsigned int) p_sys->i_channel_selected )
  612.         {
  613.             p_out[n] = p_out[n+1] = p_in[n];
  614.         }
  615.     }
  616.     return n;
  617. }