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

dolby.c

00001 /*****************************************************************************
00002  * dolby.c : simple decoder for dolby surround encoded streams
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  * $Id: headphone.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Boris Dorès <[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 static void Destroy   ( vlc_object_t * );
00039 
00040 static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
00041                         aout_buffer_t * );
00042 
00043 /*****************************************************************************
00044  * Module descriptor
00045  *****************************************************************************/
00046 vlc_module_begin();
00047     set_description( N_("Simple decoder for dolby surround encoded streams") );
00048     set_shortname( _("Dolby surround decoder") );
00049     set_category( CAT_INPUT );
00050     set_subcategory( SUBCAT_INPUT_ACODEC );
00051     set_capability( "audio filter", 5 );
00052     set_callbacks( Create, Destroy );
00053 vlc_module_end();
00054 
00055 /*****************************************************************************
00056  * Internal data structures
00057  *****************************************************************************/
00058 struct aout_filter_sys_t
00059 {
00060     int i_left;
00061     int i_center;
00062     int i_right;
00063     int i_rear_left;
00064     int i_rear_center;
00065     int i_rear_right;
00066 };
00067 
00068 /* our internal channel order (WG-4 order) */
00069 static const uint32_t pi_channels[] =
00070 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
00071   AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER,
00072   AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
00073 
00074 /*****************************************************************************
00075  * Create: allocate headphone downmixer
00076  *****************************************************************************/
00077 static int Create( vlc_object_t *p_this )
00078 {
00079     int i = 0;
00080     int i_offset = 0;
00081     aout_filter_t * p_filter = (aout_filter_t *)p_this;
00082 
00083     /* Validate audio filter format */
00084     if ( p_filter->input.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
00085        || ! ( p_filter->input.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
00086        || aout_FormatNbChannels( &p_filter->output ) <= 2
00087        || ( p_filter->input.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO )
00088           != ( p_filter->output.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO ) )
00089     {
00090         return VLC_EGENERIC;
00091     }
00092 
00093     if ( p_filter->input.i_rate != p_filter->output.i_rate )
00094     {
00095         return VLC_EGENERIC;
00096     }
00097 
00098     if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
00099           || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
00100     {
00101         return VLC_EGENERIC;
00102     }
00103 
00104     /* Allocate the memory needed to store the module's structure */
00105     p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
00106     if ( p_filter->p_sys == NULL )
00107     {
00108         msg_Err( p_filter, "Out of memory" );
00109         return VLC_EGENERIC;
00110     }
00111     p_filter->p_sys->i_left = -1;
00112     p_filter->p_sys->i_center = -1;
00113     p_filter->p_sys->i_right = -1;
00114     p_filter->p_sys->i_rear_left = -1;
00115     p_filter->p_sys->i_rear_center = -1;
00116     p_filter->p_sys->i_rear_right = -1;
00117 
00118     while ( pi_channels[i] )
00119     {
00120         if ( p_filter->output.i_physical_channels & pi_channels[i] )
00121         {
00122             switch ( pi_channels[i] )
00123             {
00124                 case AOUT_CHAN_LEFT:
00125                     p_filter->p_sys->i_left = i_offset;
00126                     break;
00127                 case AOUT_CHAN_CENTER:
00128                     p_filter->p_sys->i_center = i_offset;
00129                     break;
00130                 case AOUT_CHAN_RIGHT:
00131                     p_filter->p_sys->i_right = i_offset;
00132                     break;
00133                 case AOUT_CHAN_REARLEFT:
00134                     p_filter->p_sys->i_rear_left = i_offset;
00135                     break;
00136                 case AOUT_CHAN_REARCENTER:
00137                     p_filter->p_sys->i_rear_center = i_offset;
00138                     break;
00139                 case AOUT_CHAN_REARRIGHT:
00140                     p_filter->p_sys->i_rear_right = i_offset;
00141                     break;
00142             }
00143             ++i_offset;
00144         }
00145         ++i;
00146     }
00147 
00148     p_filter->pf_do_work = DoWork;
00149     p_filter->b_in_place = 0;
00150 
00151     return VLC_SUCCESS;
00152 }
00153 
00154 /*****************************************************************************
00155  * Destroy: deallocate resources associated with headphone downmixer
00156  *****************************************************************************/
00157 static void Destroy( vlc_object_t *p_this )
00158 {
00159     aout_filter_t * p_filter = (aout_filter_t *)p_this;
00160 
00161     if ( p_filter->p_sys != NULL )
00162     {
00163         free ( p_filter->p_sys );
00164         p_filter->p_sys = NULL;
00165     }
00166 }
00167 
00168 /*****************************************************************************
00169  * DoWork: convert a buffer
00170  *****************************************************************************/
00171 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
00172                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
00173 {
00174     float * p_in = (float*) p_in_buf->p_buffer;
00175     float * p_out = (float*) p_out_buf->p_buffer;
00176     size_t i_nb_samples = p_in_buf->i_nb_samples;
00177     size_t i_nb_channels = aout_FormatNbChannels( &p_filter->output );
00178 
00179     p_out_buf->i_nb_samples = i_nb_samples;
00180     p_out_buf->i_nb_bytes = sizeof(float) * i_nb_samples
00181                             * aout_FormatNbChannels( &p_filter->output );
00182     memset ( p_out , 0 , p_out_buf->i_nb_bytes );
00183 
00184     if ( p_filter->p_sys != NULL )
00185     {
00186         struct aout_filter_sys_t * p_sys = p_filter->p_sys;
00187         size_t i_nb_rear = 0;
00188         size_t i;
00189 
00190         if ( p_sys->i_rear_left >= 0 )
00191         {
00192             ++i_nb_rear;
00193         }
00194         if ( p_sys->i_rear_center >= 0 )
00195         {
00196             ++i_nb_rear;
00197         }
00198         if ( p_sys->i_rear_right >= 0 )
00199         {
00200             ++i_nb_rear;
00201         }
00202 
00203         for ( i = 0; i < i_nb_samples; ++i )
00204         {
00205             float f_left = p_in[ i * 2 ];
00206             float f_right = p_in[ i * 2 + 1 ];
00207             float f_rear = ( f_left - f_right ) / i_nb_rear;
00208 
00209             if ( p_sys->i_center >= 0 )
00210             {
00211                 float f_center = f_left + f_right;
00212                 f_left -= f_center / 2;
00213                 f_right -= f_center / 2;
00214 
00215                 p_out[ i * i_nb_channels + p_sys->i_center ] = f_center;
00216             }
00217 
00218             if ( p_sys->i_left >= 0 )
00219             {
00220                 p_out[ i * i_nb_channels + p_sys->i_left ] = f_left;
00221             }
00222             if ( p_sys->i_right >= 0 )
00223             {
00224                 p_out[ i * i_nb_channels + p_sys->i_right ] = f_right;
00225             }
00226             if ( p_sys->i_rear_left >= 0 )
00227             {
00228                 p_out[ i * i_nb_channels + p_sys->i_rear_left ] = f_rear;
00229             }
00230             if ( p_sys->i_rear_center >= 0 )
00231             {
00232                 p_out[ i * i_nb_channels + p_sys->i_rear_center ] = f_rear;
00233             }
00234             if ( p_sys->i_rear_right >= 0 )
00235             {
00236                 p_out[ i * i_nb_channels + p_sys->i_rear_right ] = f_rear;
00237             }
00238         }
00239     }
00240 }

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