Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

float32.c

00001 /*****************************************************************************
00002  * float32.c : precise float32 audio mixer implementation
00003  *****************************************************************************
00004  * Copyright (C) 2002 the VideoLAN team
00005  * $Id: float32.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Christophe Massiot <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  * 
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <stdlib.h>                                      /* malloc(), free() */
00028 #include <string.h>
00029 
00030 #include <vlc/vlc.h>
00031 #include "audio_output.h"
00032 #include "aout_internal.h"
00033 
00034 /*****************************************************************************
00035  * Local prototypes
00036  *****************************************************************************/
00037 static int  Create    ( vlc_object_t * );
00038 
00039 static void DoWork    ( aout_instance_t *, aout_buffer_t * );
00040 
00041 /*****************************************************************************
00042  * Module descriptor
00043  *****************************************************************************/
00044 vlc_module_begin();
00045     set_category( CAT_AUDIO );
00046     set_subcategory( SUBCAT_AUDIO_MISC );
00047     set_description( _("Float32 audio mixer") );
00048     set_capability( "audio mixer", 10 );
00049     set_callbacks( Create, NULL );
00050 vlc_module_end();
00051 
00052 /*****************************************************************************
00053  * Create: allocate mixer
00054  *****************************************************************************/
00055 static int Create( vlc_object_t *p_this )
00056 {
00057     aout_instance_t * p_aout = (aout_instance_t *)p_this;
00058 
00059     if ( p_aout->mixer.mixer.i_format != VLC_FOURCC('f','l','3','2') )
00060     {
00061         return -1;
00062     }
00063 
00064     if ( p_aout->i_nb_inputs == 1 && p_aout->mixer.f_multiplier == 1.0 )
00065     {
00066         /* Tell the trivial mixer to go for it. */
00067         return -1;
00068     }
00069 
00070     p_aout->mixer.pf_do_work = DoWork;
00071 
00072     return 0;
00073 }
00074 
00075 /*****************************************************************************
00076  * ScaleWords: prepare input words for averaging
00077  *****************************************************************************/
00078 static void ScaleWords( float * p_out, const float * p_in, size_t i_nb_words,
00079                         int i_nb_inputs, float f_multiplier )
00080 {
00081     int i;
00082     f_multiplier /= i_nb_inputs;
00083 
00084     for ( i = i_nb_words; i--; )
00085     {
00086         *p_out++ = *p_in++ * f_multiplier;
00087     }
00088 }
00089 
00090 /*****************************************************************************
00091  * MeanWords: average input words
00092  *****************************************************************************/
00093 static void MeanWords( float * p_out, const float * p_in, size_t i_nb_words,
00094                        int i_nb_inputs, float f_multiplier )
00095 {
00096     int i;
00097     f_multiplier /= i_nb_inputs;
00098 
00099     for ( i = i_nb_words; i--; )
00100     {
00101         *p_out++ += *p_in++ * f_multiplier;
00102     }
00103 }
00104 
00105 /*****************************************************************************
00106  * DoWork: mix a new output buffer
00107  *****************************************************************************
00108  * Terminology : in this function a word designates a single float32, eg.
00109  * a stereo sample is consituted of two words.
00110  *****************************************************************************/
00111 static void DoWork( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
00112 {
00113     int i_nb_inputs = p_aout->i_nb_inputs;
00114     float f_multiplier = p_aout->mixer.f_multiplier;
00115     int i_input;
00116     int i_nb_channels = aout_FormatNbChannels( &p_aout->mixer.mixer );
00117 
00118     for ( i_input = 0; i_input < i_nb_inputs; i_input++ )
00119     {
00120         int i_nb_words = p_buffer->i_nb_samples * i_nb_channels;
00121         aout_input_t * p_input = p_aout->pp_inputs[i_input];
00122         float * p_out = (float *)p_buffer->p_buffer;
00123         float * p_in = (float *)p_input->p_first_byte_to_mix;
00124 
00125         if ( p_input->b_error ) continue;
00126 
00127         for ( ; ; )
00128         {
00129             ptrdiff_t i_available_words = (
00130                  (float *)p_input->fifo.p_first->p_buffer - p_in)
00131                                    + p_input->fifo.p_first->i_nb_samples
00132                                    * i_nb_channels;
00133 
00134             if ( i_available_words < i_nb_words )
00135             {
00136                 aout_buffer_t * p_old_buffer;
00137 
00138                 if ( i_available_words > 0 )
00139                 {
00140                     if ( !i_input )
00141                     {
00142                         ScaleWords( p_out, p_in, i_available_words,
00143                                     i_nb_inputs, f_multiplier );
00144                     }
00145                     else
00146                     {
00147                         MeanWords( p_out, p_in, i_available_words,
00148                                    i_nb_inputs, f_multiplier );
00149                     }
00150                 }
00151 
00152                 i_nb_words -= i_available_words;
00153                 p_out += i_available_words;
00154 
00155                 /* Next buffer */
00156                 p_old_buffer = aout_FifoPop( p_aout, &p_input->fifo );
00157                 aout_BufferFree( p_old_buffer );
00158                 if ( p_input->fifo.p_first == NULL )
00159                 {
00160                     msg_Err( p_aout, "internal amix error" );
00161                     return;
00162                 }
00163                 p_in = (float *)p_input->fifo.p_first->p_buffer;
00164             }
00165             else
00166             {
00167                 if ( i_nb_words > 0 )
00168                 {
00169                     if ( !i_input )
00170                     {
00171                         ScaleWords( p_out, p_in, i_nb_words, i_nb_inputs,
00172                                     f_multiplier );
00173                     }
00174                     else
00175                     {
00176                         MeanWords( p_out, p_in, i_nb_words, i_nb_inputs,
00177                                    f_multiplier );
00178                     }
00179                 }
00180                 p_input->p_first_byte_to_mix = (void *)(p_in
00181                                             + i_nb_words);
00182                 break;
00183             }
00184         }
00185     }
00186 }
00187 

Generated on Tue Dec 20 10:14:27 2005 for vlc-0.8.4a by  doxygen 1.4.2