Moves volume icon update in the timer
[vlc.git] / modules / audio_filter / channel_mixer / trivial.c
1 /*****************************************************************************
2  * trivial.c : trivial channel mixer plug-in (drops unwanted channels)
3  *****************************************************************************
4  * Copyright (C) 2002, 2006 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #include <vlc/vlc.h>
29 #include <vlc_aout.h>
30
31 /*****************************************************************************
32  * Local prototypes
33  *****************************************************************************/
34 static int  Create    ( vlc_object_t * );
35
36 static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
37                         aout_buffer_t * );
38
39 /*****************************************************************************
40  * Module descriptor
41  *****************************************************************************/
42 vlc_module_begin();
43     set_description( _("Audio filter for trivial channel mixing") );
44     set_capability( "audio filter", 1 );
45     set_category( CAT_AUDIO );
46     set_subcategory( SUBCAT_AUDIO_MISC );
47     set_callbacks( Create, NULL );
48 vlc_module_end();
49
50 /*****************************************************************************
51  * Create: allocate trivial channel mixer
52  *****************************************************************************/
53 static int Create( vlc_object_t *p_this )
54 {
55     aout_filter_t * p_filter = (aout_filter_t *)p_this;
56
57     if ( (p_filter->input.i_physical_channels
58            == p_filter->output.i_physical_channels
59            && p_filter->input.i_original_channels
60                == p_filter->output.i_original_channels)
61           || p_filter->input.i_format != p_filter->output.i_format
62           || p_filter->input.i_rate != p_filter->output.i_rate
63           || (p_filter->input.i_format != VLC_FOURCC('f','l','3','2')
64                && p_filter->input.i_format != VLC_FOURCC('f','i','3','2')) )
65     {
66         return -1;
67     }
68
69     p_filter->pf_do_work = DoWork;
70     if ( aout_FormatNbChannels( &p_filter->input )
71            > aout_FormatNbChannels( &p_filter->output ) )
72     {
73         /* Downmixing */
74         p_filter->b_in_place = 1;
75     }
76     else
77     {
78         /* Upmixing */
79         p_filter->b_in_place = 0;
80     }
81
82     return 0;
83 }
84
85 /*****************************************************************************
86  * SparseCopy: trivially downmix or upmix a buffer
87  *****************************************************************************/
88 static void SparseCopy( int32_t * p_dest, const int32_t * p_src, size_t i_len,
89                         int i_output_stride, int i_input_stride )
90 {
91     int i;
92     for ( i = i_len; i--; )
93     {
94         int j;
95         for ( j = 0; j < i_output_stride; j++ )
96         {
97             p_dest[j] = p_src[j % i_input_stride];
98         }
99         p_src += i_input_stride;
100         p_dest += i_output_stride;
101     }
102 }
103
104 /*****************************************************************************
105  * DoWork: convert a buffer
106  *****************************************************************************/
107 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
108                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
109 {
110     int i_input_nb = aout_FormatNbChannels( &p_filter->input );
111     int i_output_nb = aout_FormatNbChannels( &p_filter->output );
112     int32_t * p_dest = (int32_t *)p_out_buf->p_buffer;
113     int32_t * p_src = (int32_t *)p_in_buf->p_buffer;
114
115     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
116     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * i_output_nb / i_input_nb;
117
118     if ( (p_filter->output.i_original_channels & AOUT_CHAN_PHYSMASK)
119                 != (p_filter->input.i_original_channels & AOUT_CHAN_PHYSMASK)
120            && (p_filter->input.i_original_channels & AOUT_CHAN_PHYSMASK)
121                 == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) )
122     {
123         int i;
124         /* This is a bit special. */
125         if ( !(p_filter->output.i_original_channels & AOUT_CHAN_LEFT) )
126         {
127             p_src++;
128         }
129         if ( p_filter->output.i_physical_channels == AOUT_CHAN_CENTER )
130         {
131             /* Mono mode */
132             for ( i = p_in_buf->i_nb_samples; i--; )
133             {
134                 *p_dest = *p_src;
135                 p_dest++;
136                 p_src += 2;
137             }
138         }
139         else
140         {
141             /* Fake-stereo mode */
142             for ( i = p_in_buf->i_nb_samples; i--; )
143             {
144                 *p_dest = *p_src;
145                 p_dest++;
146                 *p_dest = *p_src;
147                 p_dest++;
148                 p_src += 2;
149             }
150         }
151     }
152     else if ( p_filter->output.i_original_channels
153                                     & AOUT_CHAN_REVERSESTEREO )
154     {
155         /* Reverse-stereo mode */
156         int i;
157         for ( i = p_in_buf->i_nb_samples; i--; )
158         {
159             *p_dest = p_src[1];
160             p_dest++;
161             *p_dest = p_src[0];
162             p_dest++;
163             p_src += 2;
164         }
165     }
166     else
167     {
168         SparseCopy( p_dest, p_src, p_in_buf->i_nb_samples, i_output_nb,
169                     i_input_nb );
170     }
171 }
172