qt: playlist: use item title if available
[vlc.git] / modules / audio_filter / channel_mixer / dolby.c
blob4810eec6c2f7626fffae92b09413d6e0b1efde2f
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 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_aout.h>
34 #include <vlc_filter.h>
36 /*****************************************************************************
37 * Local prototypes
38 *****************************************************************************/
39 static int Create ( vlc_object_t * );
41 static block_t *DoWork( filter_t *, block_t * );
43 /*****************************************************************************
44 * Module descriptor
45 *****************************************************************************/
46 vlc_module_begin ()
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 )
53 vlc_module_end ()
55 /*****************************************************************************
56 * Internal data structures
57 *****************************************************************************/
58 typedef struct
60 int i_left;
61 int i_center;
62 int i_right;
63 int i_rear_left;
64 int i_rear_center;
65 int i_rear_right;
66 } filter_sys_t;
68 /*****************************************************************************
69 * Create: allocate headphone downmixer
70 *****************************************************************************/
71 static int Create( vlc_object_t *p_this )
73 int i = 0;
74 int i_offset = 0;
75 filter_t * p_filter = (filter_t *)p_this;
76 filter_sys_t *p_sys;
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 ) )
85 return VLC_EGENERIC;
88 if ( p_filter->fmt_in.audio.i_rate != p_filter->fmt_out.audio.i_rate )
90 return VLC_EGENERIC;
93 if ( p_filter->fmt_in.audio.i_format != VLC_CODEC_FL32
94 || p_filter->fmt_out.audio.i_format != VLC_CODEC_FL32 )
96 return VLC_EGENERIC;
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) )
102 return VLC_ENOMEM;
103 p_sys->i_left = -1;
104 p_sys->i_center = -1;
105 p_sys->i_right = -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] )
116 case AOUT_CHAN_LEFT:
117 p_sys->i_left = i_offset;
118 break;
119 case AOUT_CHAN_CENTER:
120 p_sys->i_center = i_offset;
121 break;
122 case AOUT_CHAN_RIGHT:
123 p_sys->i_right = i_offset;
124 break;
125 case AOUT_CHAN_REARLEFT:
126 p_sys->i_rear_left = i_offset;
127 break;
128 case AOUT_CHAN_REARCENTER:
129 p_sys->i_rear_center = i_offset;
130 break;
131 case AOUT_CHAN_REARRIGHT:
132 p_sys->i_rear_right = i_offset;
133 break;
135 ++i_offset;
137 ++i;
140 static const struct vlc_filter_operations filter_ops =
142 .filter_audio = DoWork,
144 p_filter->ops = &filter_ops;
146 return VLC_SUCCESS;
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;
159 size_t i;
160 block_t *p_out_buf = block_Alloc(
161 sizeof(float) * i_nb_samples * i_nb_channels );
162 if( !p_out_buf )
163 goto out;
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 )
175 ++i_nb_rear;
177 if( p_sys->i_rear_center >= 0 )
179 ++i_nb_rear;
181 if( p_sys->i_rear_right >= 0 )
183 ++i_nb_rear;
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;
222 out:
223 block_Release( p_in_buf );
224 return p_out_buf;