1 /*****************************************************************************
2 * dolby.c : simple decoder for dolby surround encoded streams
3 *****************************************************************************
4 * Copyright (C) 2005-2009 the VideoLAN team
7 * Authors: Boris Dorès <babal@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along with
20 * this program; if not, write to the Free Software Foundation, Inc., 51
21 * Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int Create ( vlc_object_t * );
41 static void Destroy ( vlc_object_t * );
43 static block_t *DoWork( filter_t *, block_t * );
45 /*****************************************************************************
47 *****************************************************************************/
49 set_description( N_("Simple decoder for Dolby Surround encoded streams") )
50 set_shortname( N_("Dolby Surround decoder") )
51 set_category( CAT_INPUT )
52 set_subcategory( SUBCAT_INPUT_ACODEC )
53 set_capability( "audio converter", 5 )
54 set_callbacks( Create, Destroy )
57 /*****************************************************************************
58 * Internal data structures
59 *****************************************************************************/
70 /*****************************************************************************
71 * Create: allocate headphone downmixer
72 *****************************************************************************/
73 static int Create( vlc_object_t *p_this )
77 filter_t * p_filter = (filter_t *)p_this;
80 /* Validate audio filter format */
81 if ( p_filter->fmt_in.audio.i_physical_channels != (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT)
82 || ! ( p_filter->fmt_in.audio.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
83 || aout_FormatNbChannels( &p_filter->fmt_out.audio ) <= 2
84 || ( p_filter->fmt_in.audio.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO )
85 != ( p_filter->fmt_out.audio.i_original_channels & ~AOUT_CHAN_DOLBYSTEREO ) )
90 if ( p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate )
95 if ( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32
96 || p_filter->fmt_out.audio.i_format != VLC_CODEC_FL32 )
101 /* Allocate the memory needed to store the module's structure */
102 p_sys = p_filter->p_sys = malloc( sizeof(*p_sys) );
106 p_sys->i_center = -1;
108 p_sys->i_rear_left = -1;
109 p_sys->i_rear_center = -1;
110 p_sys->i_rear_right = -1;
112 while ( pi_vlc_chan_order_wg4[i] )
114 if ( p_filter->fmt_out.audio.i_physical_channels & pi_vlc_chan_order_wg4[i] )
116 switch ( pi_vlc_chan_order_wg4[i] )
119 p_sys->i_left = i_offset;
121 case AOUT_CHAN_CENTER:
122 p_sys->i_center = i_offset;
124 case AOUT_CHAN_RIGHT:
125 p_sys->i_right = i_offset;
127 case AOUT_CHAN_REARLEFT:
128 p_sys->i_rear_left = i_offset;
130 case AOUT_CHAN_REARCENTER:
131 p_sys->i_rear_center = i_offset;
133 case AOUT_CHAN_REARRIGHT:
134 p_sys->i_rear_right = i_offset;
142 p_filter->pf_audio_filter = DoWork;
147 /*****************************************************************************
148 * Destroy: deallocate resources associated with headphone downmixer
149 *****************************************************************************/
150 static void Destroy( vlc_object_t *p_this )
152 filter_t * p_filter = (filter_t *)p_this;
153 free( p_filter->p_sys );
156 /*****************************************************************************
157 * DoWork: convert a buffer
158 *****************************************************************************/
159 static block_t *DoWork( filter_t * p_filter, block_t * p_in_buf )
161 filter_sys_t * p_sys = p_filter->p_sys;
162 float * p_in = (float*) p_in_buf->p_buffer;
163 size_t i_nb_samples = p_in_buf->i_nb_samples;
164 size_t i_nb_channels = aout_FormatNbChannels( &p_filter->fmt_out.audio );
165 size_t i_nb_rear = 0;
167 block_t *p_out_buf = block_Alloc(
168 sizeof(float) * i_nb_samples * i_nb_channels );
172 float * p_out = (float*) p_out_buf->p_buffer;
173 p_out_buf->i_nb_samples = i_nb_samples;
174 p_out_buf->i_dts = p_in_buf->i_dts;
175 p_out_buf->i_pts = p_in_buf->i_pts;
176 p_out_buf->i_length = p_in_buf->i_length;
178 memset( p_out, 0, p_out_buf->i_buffer );
180 if( p_sys->i_rear_left >= 0 )
184 if( p_sys->i_rear_center >= 0 )
188 if( p_sys->i_rear_right >= 0 )
193 for( i = 0; i < i_nb_samples; ++i )
195 float f_left = p_in[ i * 2 ];
196 float f_right = p_in[ i * 2 + 1 ];
197 float f_rear = ( f_left - f_right ) / i_nb_rear;
199 if( p_sys->i_center >= 0 )
201 float f_center = f_left + f_right;
202 f_left -= f_center / 2;
203 f_right -= f_center / 2;
205 p_out[ i * i_nb_channels + p_sys->i_center ] = f_center;
208 if( p_sys->i_left >= 0 )
210 p_out[ i * i_nb_channels + p_sys->i_left ] = f_left;
212 if( p_sys->i_right >= 0 )
214 p_out[ i * i_nb_channels + p_sys->i_right ] = f_right;
216 if( p_sys->i_rear_left >= 0 )
218 p_out[ i * i_nb_channels + p_sys->i_rear_left ] = f_rear;
220 if( p_sys->i_rear_center >= 0 )
222 p_out[ i * i_nb_channels + p_sys->i_rear_center ] = f_rear;
224 if( p_sys->i_rear_right >= 0 )
226 p_out[ i * i_nb_channels + p_sys->i_rear_right ] = f_rear;
230 block_Release( p_in_buf );