1 /*****************************************************************************
2 * dolby.c : simple decoder for dolby surround encoded streams
3 *****************************************************************************
4 * Copyright (C) 2005-2009 the VideoLAN team
6 * Authors: Boris Dorès <babal@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
34 #include <vlc_filter.h>
36 /*****************************************************************************
38 *****************************************************************************/
39 static int Create ( vlc_object_t
* );
41 static block_t
*DoWork( filter_t
*, block_t
* );
43 /*****************************************************************************
45 *****************************************************************************/
47 set_description( N_("Simple decoder for Dolby Surround encoded streams") )
48 set_shortname( N_("Dolby Surround decoder") )
49 set_category( CAT_INPUT
)
50 set_subcategory( SUBCAT_INPUT_ACODEC
)
51 set_capability( "audio converter", 5 )
52 set_callback( Create
)
55 /*****************************************************************************
56 * Internal data structures
57 *****************************************************************************/
68 /*****************************************************************************
69 * Create: allocate headphone downmixer
70 *****************************************************************************/
71 static int Create( vlc_object_t
*p_this
)
75 filter_t
* p_filter
= (filter_t
*)p_this
;
78 /* Validate audio filter format */
79 if ( p_filter
->fmt_in
.audio
.i_physical_channels
!= (AOUT_CHAN_LEFT
|AOUT_CHAN_RIGHT
)
80 || ! ( p_filter
->fmt_in
.audio
.i_chan_mode
& AOUT_CHANMODE_DOLBYSTEREO
)
81 || p_filter
->fmt_out
.audio
.i_channels
<= 2
82 || ( p_filter
->fmt_in
.audio
.i_chan_mode
& ~AOUT_CHANMODE_DOLBYSTEREO
)
83 != ( p_filter
->fmt_out
.audio
.i_chan_mode
& ~AOUT_CHANMODE_DOLBYSTEREO
) )
88 if ( p_filter
->fmt_in
.audio
.i_rate
!= p_filter
->fmt_out
.audio
.i_rate
)
93 if ( p_filter
->fmt_in
.audio
.i_format
!= VLC_CODEC_FL32
94 || p_filter
->fmt_out
.audio
.i_format
!= VLC_CODEC_FL32
)
99 /* Allocate the memory needed to store the module's structure */
100 p_sys
= p_filter
->p_sys
= vlc_obj_malloc( VLC_OBJECT(p_filter
), sizeof(*p_sys
) );
101 if( unlikely(p_sys
== NULL
) )
104 p_sys
->i_center
= -1;
106 p_sys
->i_rear_left
= -1;
107 p_sys
->i_rear_center
= -1;
108 p_sys
->i_rear_right
= -1;
110 while ( pi_vlc_chan_order_wg4
[i
] )
112 if ( p_filter
->fmt_out
.audio
.i_physical_channels
& pi_vlc_chan_order_wg4
[i
] )
114 switch ( pi_vlc_chan_order_wg4
[i
] )
117 p_sys
->i_left
= i_offset
;
119 case AOUT_CHAN_CENTER
:
120 p_sys
->i_center
= i_offset
;
122 case AOUT_CHAN_RIGHT
:
123 p_sys
->i_right
= i_offset
;
125 case AOUT_CHAN_REARLEFT
:
126 p_sys
->i_rear_left
= i_offset
;
128 case AOUT_CHAN_REARCENTER
:
129 p_sys
->i_rear_center
= i_offset
;
131 case AOUT_CHAN_REARRIGHT
:
132 p_sys
->i_rear_right
= i_offset
;
140 static const struct vlc_filter_operations filter_ops
=
142 .filter_audio
= DoWork
,
144 p_filter
->ops
= &filter_ops
;
149 /*****************************************************************************
150 * DoWork: convert a buffer
151 *****************************************************************************/
152 static block_t
*DoWork( filter_t
* p_filter
, block_t
* p_in_buf
)
154 filter_sys_t
* p_sys
= p_filter
->p_sys
;
155 float * p_in
= (float*) p_in_buf
->p_buffer
;
156 size_t i_nb_samples
= p_in_buf
->i_nb_samples
;
157 size_t i_nb_channels
= aout_FormatNbChannels( &p_filter
->fmt_out
.audio
);
158 size_t i_nb_rear
= 0;
160 block_t
*p_out_buf
= block_Alloc(
161 sizeof(float) * i_nb_samples
* i_nb_channels
);
165 float * p_out
= (float*) p_out_buf
->p_buffer
;
166 p_out_buf
->i_nb_samples
= i_nb_samples
;
167 p_out_buf
->i_dts
= p_in_buf
->i_dts
;
168 p_out_buf
->i_pts
= p_in_buf
->i_pts
;
169 p_out_buf
->i_length
= p_in_buf
->i_length
;
171 memset( p_out
, 0, p_out_buf
->i_buffer
);
173 if( p_sys
->i_rear_left
>= 0 )
177 if( p_sys
->i_rear_center
>= 0 )
181 if( p_sys
->i_rear_right
>= 0 )
186 for( i
= 0; i
< i_nb_samples
; ++i
)
188 float f_left
= p_in
[ i
* 2 ];
189 float f_right
= p_in
[ i
* 2 + 1 ];
190 float f_rear
= ( f_left
- f_right
) / i_nb_rear
;
192 if( p_sys
->i_center
>= 0 )
194 float f_center
= f_left
+ f_right
;
195 f_left
-= f_center
/ 2;
196 f_right
-= f_center
/ 2;
198 p_out
[ i
* i_nb_channels
+ p_sys
->i_center
] = f_center
;
201 if( p_sys
->i_left
>= 0 )
203 p_out
[ i
* i_nb_channels
+ p_sys
->i_left
] = f_left
;
205 if( p_sys
->i_right
>= 0 )
207 p_out
[ i
* i_nb_channels
+ p_sys
->i_right
] = f_right
;
209 if( p_sys
->i_rear_left
>= 0 )
211 p_out
[ i
* i_nb_channels
+ p_sys
->i_rear_left
] = f_rear
;
213 if( p_sys
->i_rear_center
>= 0 )
215 p_out
[ i
* i_nb_channels
+ p_sys
->i_rear_center
] = f_rear
;
217 if( p_sys
->i_rear_right
>= 0 )
219 p_out
[ i
* i_nb_channels
+ p_sys
->i_rear_right
] = f_rear
;
223 block_Release( p_in_buf
);