]> git.sesse.net Git - vlc/blob - src/audio_output/aout_s16.c
* Split audio output into several separate files to make it easier
[vlc] / src / audio_output / aout_s16.c
1 /*****************************************************************************
2  * aout_s16.c: 16 bit signed audio output functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  *
6  * Authors: Michel Kaempf <maxx@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
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 General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include "defs.h"
27
28 #include <stdio.h>                                           /* "intf_msg.h" */
29 #include <stdlib.h>                            /* calloc(), malloc(), free() */
30
31 #include "config.h"
32 #include "common.h"
33 #include "threads.h"
34 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
35
36 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
37
38 #include "audio_output.h"
39 #include "aout_common.h"
40
41 /*****************************************************************************
42  * Local prototypes
43  *****************************************************************************/
44 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
45
46 /*****************************************************************************
47  * Functions
48  *****************************************************************************/
49 void aout_S16MonoThread( aout_thread_t * p_aout )
50 {
51     intf_ErrMsg( "aout error: 16 bit signed mono thread unsupported" );
52 }
53
54 void aout_S16StereoThread( aout_thread_t * p_aout )
55 {
56     int  i_fifo;
57     long l_buffer, l_buffer_limit, l_bytes;
58
59     /* As the s32_buffer was created with calloc(), we don't have to set this
60      * memory to zero and we can immediately jump into the thread's loop */
61     while ( ! p_aout->b_die )
62     {
63         vlc_mutex_lock( &p_aout->fifos_lock );
64
65         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
66         {
67             if( p_aout->fifo[i_fifo].b_die )
68             {
69                 aout_FreeFifo( &p_aout->fifo[i_fifo] );
70             }
71             else
72             {
73                 S16StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
74             }
75         }
76
77         vlc_mutex_unlock( &p_aout->fifos_lock );
78
79         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
80
81         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
82         {
83             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
84             p_aout->s32_buffer[l_buffer] = 0;
85         }
86
87         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
88         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
89         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
90         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
91         {
92             msleep( p_aout->l_msleep );
93         }
94     }
95
96     vlc_mutex_lock( &p_aout->fifos_lock );
97
98     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
99     {
100         aout_FreeFifo( &p_aout->fifo[i_fifo] );
101     }
102
103     vlc_mutex_unlock( &p_aout->fifos_lock );
104 }
105
106 /* Following functions are local */
107
108 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
109 {
110     long l_buffer = 0;
111     long l_buffer_limit, l_units;
112
113     switch ( p_fifo->i_type )
114     {
115     case AOUT_EMPTY_FIFO:
116
117         break;
118
119     case AOUT_INTF_MONO_FIFO:
120
121         if ( p_fifo->l_units > p_aout->l_units )
122         {
123             /* p_aout->b_stereo == 1 */
124             while ( l_buffer < (p_aout->l_units << 1) )
125             {
126                 p_aout->s32_buffer[l_buffer++] +=
127                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
128                 p_aout->s32_buffer[l_buffer++] +=
129                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
130                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
131             }
132             p_fifo->l_units -= p_aout->l_units;
133         }
134         else
135         {
136             /* p_aout->b_stereo == 1 */
137             while ( l_buffer < (p_fifo->l_units << 1) )
138             {
139                 p_aout->s32_buffer[l_buffer++] +=
140                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
141                 p_aout->s32_buffer[l_buffer++] +=
142                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
143                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
144             }
145             free( p_fifo->buffer ); /* !! */
146             p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
147         }
148         break;
149
150     case AOUT_INTF_STEREO_FIFO:
151
152         if ( p_fifo->l_units > p_aout->l_units )
153         {
154             /* p_aout->b_stereo == 1 */
155             while ( l_buffer < (p_aout->l_units << 1) )
156             {
157                 p_aout->s32_buffer[l_buffer++] +=
158                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
159                 p_aout->s32_buffer[l_buffer++] +=
160                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
161                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
162             }
163             p_fifo->l_units -= p_aout->l_units;
164         }
165         else
166         {
167             /* p_aout->b_stereo == 1 */
168             while ( l_buffer < (p_fifo->l_units << 1) )
169             {
170                 p_aout->s32_buffer[l_buffer++] +=
171                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
172                 p_aout->s32_buffer[l_buffer++] +=
173                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
174                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
175             }
176             free( p_fifo->buffer );
177             p_fifo->i_type = AOUT_EMPTY_FIFO;
178         }
179         break;
180
181     case AOUT_ADEC_MONO_FIFO:
182
183         l_units = p_aout->l_units;
184         while ( l_units > 0 )
185         {
186             if ( !p_fifo->b_next_frame )
187             {
188                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
189                 {
190                     break;
191                 }
192             }
193
194             if ( p_fifo->l_units > l_units )
195             {
196                 /* p_aout->b_stereo == 1 */
197                 l_buffer_limit = p_aout->l_units << 1;
198
199                 while ( l_buffer < l_buffer_limit )
200                 {
201                     p_aout->s32_buffer[l_buffer++] +=
202                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
203                     p_aout->s32_buffer[l_buffer++] +=
204                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
205
206                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
207                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
208                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
209                     {
210                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
211                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
212                     }
213                 }
214                 p_fifo->l_units -= l_units;
215                 break;
216             }
217             else
218             {
219                 /* p_aout->b_stereo == 1 */
220                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
221
222                 while ( l_buffer < l_buffer_limit )
223                 {
224                     p_aout->s32_buffer[l_buffer++] +=
225                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
226                     p_aout->s32_buffer[l_buffer++] +=
227                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
228
229                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
230                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
231                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
232                     {
233                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
234                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
235                     }
236                 }
237                 l_units -= p_fifo->l_units;
238
239                 vlc_mutex_lock( &p_fifo->data_lock );
240                 p_fifo->l_start_frame = p_fifo->l_next_frame;
241                 vlc_cond_signal( &p_fifo->data_wait );
242                 vlc_mutex_unlock( &p_fifo->data_lock );
243
244                 /* p_fifo->b_start_frame = 1; */
245                 p_fifo->l_next_frame += 1;
246                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
247                 p_fifo->b_next_frame = 0;
248             }
249         }
250         break;
251
252     case AOUT_ADEC_STEREO_FIFO:
253
254         l_units = p_aout->l_units;
255         while ( l_units > 0 )
256         {
257             if ( !p_fifo->b_next_frame )
258             {
259                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
260                 {
261                     break;
262                 }
263             }
264
265             if ( p_fifo->l_units > l_units )
266             {
267                 /* p_aout->b_stereo == 1 */
268                 l_buffer_limit = p_aout->l_units << 1;
269
270                 while ( l_buffer < l_buffer_limit )
271                 {
272                     p_aout->s32_buffer[l_buffer++] +=
273                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
274                     p_aout->s32_buffer[l_buffer++] +=
275                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
276
277                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
278                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
279                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
280                     {
281                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
282                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
283                     }
284                 }
285                 p_fifo->l_units -= l_units;
286                 break;
287             }
288             else
289             {
290                 /* p_aout->b_stereo == 1 */
291                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
292
293                 while ( l_buffer < l_buffer_limit )
294                 {
295                     p_aout->s32_buffer[l_buffer++] +=
296                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
297                     p_aout->s32_buffer[l_buffer++] +=
298                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
299
300                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
301                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
302                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
303                     {
304                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
305                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
306                     }
307                 }
308                 l_units -= p_fifo->l_units;
309
310                 vlc_mutex_lock( &p_fifo->data_lock );
311                 p_fifo->l_start_frame = p_fifo->l_next_frame;
312                 vlc_cond_signal( &p_fifo->data_wait );
313                 vlc_mutex_unlock( &p_fifo->data_lock );
314
315                 /* p_fifo->b_start_frame = 1; */
316                 p_fifo->l_next_frame += 1;
317                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
318                 p_fifo->b_next_frame = 0;
319             }
320         }
321         break;
322
323     default:
324
325         intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
326         break;
327     }
328 }
329