]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
* audio_output/audio_output.c :
[vlc] / src / audio_output / audio_output.c
1 /******************************************************************************
2  * audio_output.c : audio output thread
3  * (c)1999 VideoLAN
4  ******************************************************************************/
5
6 /* TODO:
7  *
8  * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
9  *   inline
10  * - Faire les optimisations dans les fonctions threads :
11  *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
12  *     à chaque boucle
13  *   = Utiliser des tables pour les gros calculs
14  * - Faire une structure différente pour intf/adec fifo
15  *
16  */
17
18 /******************************************************************************
19  * Preamble
20  ******************************************************************************/
21 #include <unistd.h>
22
23 #include <sys/soundcard.h>
24 #include <stdio.h>                                            /* "intf_msg.h" */
25 #include <stdlib.h>                             /* calloc(), malloc(), free() */
26
27 #include "common.h"
28 #include "config.h"
29 #include "mtime.h"                              /* mtime_t, mdate(), msleep() */
30 #include "vlc_thread.h"
31
32 #include "intf_msg.h"                         /* intf_DbgMsg(), intf_ErrMsg() */
33
34 #include "audio_output.h"
35 #include "audio_dsp.h"
36 #include "main.h"
37
38 /******************************************************************************
39  * Local prototypes
40  ******************************************************************************/
41
42 static int aout_SpawnThread( aout_thread_t * p_aout );
43
44 /* Creating as much aout_Thread functions as configurations is one solution,
45  * examining the different cases in the Thread loop of an unique function is
46  * another. I chose the first solution. */
47 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
48 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
49 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
50 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
51 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
52 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
53 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
54 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
55
56 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
57 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
58
59 /******************************************************************************
60  * aout_CreateThread: initialize audio thread
61  ******************************************************************************/
62 aout_thread_t *aout_CreateThread( int *pi_status )
63 {
64     aout_thread_t * p_aout;                               /* thread descriptor */
65 //    int             i_status;                                 /* thread status */
66    
67     /* Allocate descriptor */
68     p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
69     if( p_aout == NULL )
70     {
71         return( NULL );
72     }
73
74     //???? kludge to initialize some audio parameters - place this section somewhere
75     //???? else
76     p_aout->dsp.i_format = AOUT_DEFAULT_FORMAT;
77     p_aout->dsp.psz_device = main_GetPszVariable( AOUT_DSP_VAR, AOUT_DSP_DEFAULT );
78     p_aout->dsp.b_stereo   = main_GetIntVariable( AOUT_STEREO_VAR, AOUT_STEREO_DEFAULT );
79     p_aout->dsp.l_rate     = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );    
80     // ???? end of kludge
81
82     /* 
83      * Initialize DSP 
84      */
85     if ( aout_dspOpen( &p_aout->dsp ) )
86     {
87         free( p_aout );
88         return( NULL );
89     }
90     if ( aout_dspReset( &p_aout->dsp ) )
91     {
92         aout_dspClose( &p_aout->dsp );
93         free( p_aout );
94         return( NULL );
95     }
96     if ( aout_dspSetFormat( &p_aout->dsp ) )
97     {
98         aout_dspClose( &p_aout->dsp );
99         free( p_aout );
100         return( NULL );
101     }
102     if ( aout_dspSetChannels( &p_aout->dsp ) )
103     {
104         aout_dspClose( &p_aout->dsp );
105         free( p_aout );
106         return( NULL );
107     }
108     if ( aout_dspSetRate( &p_aout->dsp ) )
109     {
110         aout_dspClose( &p_aout->dsp );
111         free( p_aout );
112         return( NULL );
113     }
114     intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, stereo=%i, rate=%li)\n",
115         p_aout->dsp.psz_device,
116         p_aout->dsp.i_format,
117         p_aout->dsp.b_stereo, p_aout->dsp.l_rate);
118
119     //?? maybe it would be cleaner to change SpawnThread prototype
120     //?? see vout to handle status correctly - however, it is not critical since
121     //?? this thread is only called in main is all calls are blocking
122     if( aout_SpawnThread( p_aout ) )
123     {
124         aout_dspClose( &p_aout->dsp );
125         free( p_aout );
126         return( NULL );
127     }
128
129     return( p_aout );
130 }
131
132 /******************************************************************************
133  * aout_SpawnThread
134  ******************************************************************************/
135 static int aout_SpawnThread( aout_thread_t * p_aout )
136 {
137     int             i_fifo;
138     long            l_bytes;
139     void *          aout_thread = NULL;
140
141     intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
142
143     /* We want the audio output thread to live */
144     p_aout->b_die = 0;
145
146     /* Initialize the fifos lock */
147     vlc_mutex_init( &p_aout->fifos_lock );
148     /* Initialize audio fifos : set all fifos as empty and initialize locks */
149     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
150     {
151         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
152         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
153         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
154     }
155
156     /* Compute the size (in audio units) of the audio output buffer. Although
157      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
158      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
159     p_aout->l_units = (long)( ((s64)p_aout->dsp.l_rate * AOUT_BUFFER_DURATION) / 1000000 );
160     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->dsp.l_rate );
161
162     /* Make aout_thread point to the right thread function, and compute the
163      * byte size of the audio output buffer */
164     switch ( p_aout->dsp.b_stereo )
165     {
166         /* Audio output is mono */
167         case 0:
168             switch ( p_aout->dsp.i_format )
169             {
170                 case AFMT_U8:
171                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
172                     aout_thread = (void *)aout_Thread_U8_Mono;
173                     break;
174
175                 case AFMT_S8:
176                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
177                     aout_thread = (void *)aout_Thread_S8_Mono;
178                     break;
179
180                 case AFMT_U16_LE:
181                 case AFMT_U16_BE:
182                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
183                     aout_thread = (void *)aout_Thread_U16_Mono;
184                     break;
185
186                 case AFMT_S16_LE:
187                 case AFMT_S16_BE:
188                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
189                     aout_thread = (void *)aout_Thread_S16_Mono;
190                     break;
191
192                 default:
193                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
194                         p_aout->dsp.i_format);
195                     return( -1 );
196             }
197             break;
198
199         /* Audio output is stereo */
200         case 1:
201             switch ( p_aout->dsp.i_format )
202             {
203                 case AFMT_U8:
204                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
205                     aout_thread = (void *)aout_Thread_U8_Stereo;
206                     break;
207
208                 case AFMT_S8:
209                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
210                     aout_thread = (void *)aout_Thread_S8_Stereo;
211                     break;
212
213                 case AFMT_U16_LE:
214                 case AFMT_U16_BE:
215                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
216                     aout_thread = (void *)aout_Thread_U16_Stereo;
217                     break;
218
219                 case AFMT_S16_LE:
220                 case AFMT_S16_BE:
221                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
222                     aout_thread = (void *)aout_Thread_S16_Stereo;
223                     break;
224
225                 default:
226                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
227                         p_aout->dsp.i_format);
228                     return( -1 );
229             }
230             break;
231
232         default:
233             intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
234                 p_aout->dsp.b_stereo + 1);
235             return( -1 );
236     }
237
238     /* Allocate the memory needed by the audio output buffers, and set to zero
239      * the s32 buffer's memory */
240     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
241     {
242         intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
243         return( -1 );
244     }
245     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << p_aout->dsp.b_stereo)) == NULL )
246     {
247         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
248         free( p_aout->buffer );
249         return( -1 );
250     }
251
252     /* Before launching the thread, we try to predict the date of the first
253      * audio unit in the first output buffer */
254     p_aout->date = mdate();
255
256     /* Launch the thread */
257     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
258     {
259         intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
260         free( p_aout->buffer );
261         free( p_aout->s32_buffer );
262         return( -1 );
263     }
264
265     intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
266     return( 0 );
267 }
268
269 /******************************************************************************
270  * aout_DestroyThread
271  ******************************************************************************/
272 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
273 {
274     //???? pi_status is not handled correctly: check vout how to do! 
275
276     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
277
278     /* Ask thread to kill itself and wait until it's done */
279     p_aout->b_die = 1;
280     vlc_thread_join( p_aout->thread_id ); // only if pi_status is NULL
281
282     /* Free the allocated memory */
283     free( p_aout->buffer );
284     free( p_aout->s32_buffer );
285
286     /* Free the structure */
287     aout_dspClose( &p_aout->dsp );
288     intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->dsp.psz_device);
289     free( p_aout );
290 }
291
292 /******************************************************************************
293  * aout_CreateFifo
294  ******************************************************************************/
295 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
296 {
297     int i_fifo;
298
299     /* Take the fifos lock */
300     vlc_mutex_lock( &p_aout->fifos_lock );
301
302     /* Looking for a free fifo structure */
303     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
304     {
305         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
306         {
307             break;
308         }
309     }
310     if ( i_fifo == AOUT_MAX_FIFOS )
311     {
312         intf_ErrMsg("aout error: no empty fifo available\n");
313         vlc_mutex_unlock( &p_aout->fifos_lock );
314         return( NULL );
315     }
316
317     /* Initialize the new fifo structure */
318     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
319     {
320         case AOUT_INTF_MONO_FIFO:
321         case AOUT_INTF_STEREO_FIFO:
322             p_aout->fifo[i_fifo].b_die = 0;
323
324             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
325             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
326
327             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
328
329             p_aout->fifo[i_fifo].l_unit = 0;
330             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->dsp.l_rate );
331             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
332             break;
333
334         case AOUT_ADEC_MONO_FIFO:
335         case AOUT_ADEC_STEREO_FIFO:
336             p_aout->fifo[i_fifo].b_die = 0;
337
338             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
339             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
340
341             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
342             /* Allocate the memory needed to store the audio frames. As the
343              * fifo is a rotative fifo, we must be able to find out whether the
344              * fifo is full or empty, that's why we must in fact allocate memory
345              * for (AOUT_FIFO_SIZE+1) audio frames. */
346             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
347             {
348                 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
349                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
350                 vlc_mutex_unlock( &p_aout->fifos_lock );
351                 return( NULL );
352             }
353
354             /* Allocate the memory needed to store the dates of the frames */
355             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
356             {
357                 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
358                 free( p_aout->fifo[i_fifo].buffer );
359                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
360                 vlc_mutex_unlock( &p_aout->fifos_lock );
361                 return( NULL );
362             }
363
364             /* Set the fifo's buffer as empty (the first frame that is to be
365              * played is also the first frame that is not to be played) */
366             p_aout->fifo[i_fifo].l_start_frame = 0;
367             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
368             p_aout->fifo[i_fifo].l_end_frame = 0;
369
370             /* Waiting for the audio decoder to compute enough frames to work
371              * out the fifo's current rate (as soon as the decoder has decoded
372              * enough frames, the members of the fifo structure that are not
373              * initialized now will be calculated) */
374             p_aout->fifo[i_fifo].b_start_frame = 0;
375             p_aout->fifo[i_fifo].b_next_frame = 0;
376             break;
377
378         default:
379             intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
380             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
381             vlc_mutex_unlock( &p_aout->fifos_lock );
382             return( NULL );
383     }
384
385     /* Release the fifos lock */
386     vlc_mutex_unlock( &p_aout->fifos_lock );
387
388     /* Return the pointer to the fifo structure */
389     intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
390     return( &p_aout->fifo[i_fifo] );
391 }
392
393 /******************************************************************************
394  * aout_DestroyFifo
395  ******************************************************************************/
396 void aout_DestroyFifo( aout_fifo_t * p_fifo )
397 {
398     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
399     p_fifo->b_die = 1;
400 }
401
402 /* Here are the local macros */
403
404 #define UPDATE_INCREMENT( increment, integer ) \
405     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 ) \
406     { \
407         (integer) += (increment).l_euclidean_integer + 1; \
408         (increment).l_remainder -= (increment).l_euclidean_denominator; \
409     } \
410     else \
411     { \
412         (integer) += (increment).l_euclidean_integer; \
413     }
414
415 /* Following functions are local */
416
417 /******************************************************************************
418  * InitializeIncrement
419  ******************************************************************************/
420 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
421 {
422     p_increment->l_remainder = -l_denominator;
423
424     p_increment->l_euclidean_integer = 0;
425     while ( l_numerator >= l_denominator )
426     {
427         p_increment->l_euclidean_integer++;
428         l_numerator -= l_denominator;
429     }
430
431     p_increment->l_euclidean_remainder = l_numerator;
432
433     p_increment->l_euclidean_denominator = l_denominator;
434 }
435
436 /******************************************************************************
437  * NextFrame
438  ******************************************************************************/
439 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
440 {
441     long l_units, l_rate;
442
443     /* We take the lock */
444     vlc_mutex_lock( &p_fifo->data_lock );
445
446     /* Are we looking for a dated start frame ? */
447     if ( !p_fifo->b_start_frame )
448     {
449         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
450         {
451             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
452             {
453                 p_fifo->b_start_frame = 1;
454                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
455                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo);
456                 break;
457             }
458             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
459         }
460
461         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
462         {
463             vlc_mutex_unlock( &p_fifo->data_lock );
464             return( -1 );
465         }
466     }
467
468     /* We are looking for the next dated frame */
469     /* FIXME : is the output fifo full ? */
470     while ( !p_fifo->b_next_frame )
471     {
472         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
473         {
474             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
475             {
476                 p_fifo->b_next_frame = 1;
477                 break;
478             }
479             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
480         }
481
482         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
483         {
484             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
485             if ( p_fifo->b_die )
486             {
487                 vlc_mutex_unlock( &p_fifo->data_lock );
488                 return( -1 );
489             }
490         }
491     }
492
493     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
494
495     l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
496 //    fprintf( stderr, "aout debug: %lli (%li);\n", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
497
498     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->dsp.l_rate );
499
500     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
501         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
502         * p_aout->dsp.l_rate) / l_rate) + 1;
503
504     /* We release the lock before leaving */
505     vlc_mutex_unlock( &p_fifo->data_lock );
506     return( 0 );
507 }
508
509 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
510 {
511 }
512
513 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
514 {
515 }
516
517 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
518 {
519 }
520
521 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
522 {
523 }
524
525 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
526 {
527 }
528
529 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
530 {
531     int i_fifo;
532     long l_buffer, l_buffer_limit;
533     long l_units, l_bytes;
534
535     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
536
537     /* As the s32_buffer was created with calloc(), we don't have to set this
538      * memory to zero and we can immediately jump into the thread's loop */
539     while ( !p_aout->b_die )
540     {
541         vlc_mutex_lock( &p_aout->fifos_lock );
542         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
543         {
544             switch ( p_aout->fifo[i_fifo].i_type )
545             {
546                 case AOUT_EMPTY_FIFO:
547                     break;
548
549                 case AOUT_INTF_MONO_FIFO:
550                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
551                     {
552                         l_buffer = 0;
553                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
554                         {
555                             p_aout->s32_buffer[l_buffer++] +=
556                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
557                             p_aout->s32_buffer[l_buffer++] +=
558                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
559                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
560                         }
561                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
562                     }
563                     else
564                     {
565                         l_buffer = 0;
566                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
567                         {
568                             p_aout->s32_buffer[l_buffer++] +=
569                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
570                             p_aout->s32_buffer[l_buffer++] +=
571                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
572                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
573                         }
574                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
575                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
576                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
577                     }
578                     break;
579
580                 case AOUT_INTF_STEREO_FIFO:
581                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
582                     {
583                         l_buffer = 0;
584                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
585                         {
586                             p_aout->s32_buffer[l_buffer++] +=
587                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
588                             p_aout->s32_buffer[l_buffer++] +=
589                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
590                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
591                         }
592                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
593                     }
594                     else
595                     {
596                         l_buffer = 0;
597                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo */
598                         {
599                             p_aout->s32_buffer[l_buffer++] +=
600                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
601                             p_aout->s32_buffer[l_buffer++] +=
602                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
603                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
604                         }
605                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
606                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
607                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
608                     }
609                     break;
610
611                 case AOUT_ADEC_MONO_FIFO:
612                     if ( p_aout->fifo[i_fifo].b_die )
613                     {
614                         free( p_aout->fifo[i_fifo].buffer );
615                         free( p_aout->fifo[i_fifo].date );
616                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
617                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
618                         continue;
619                     }
620
621                     l_units = p_aout->l_units;
622                     l_buffer = 0;
623                     while ( l_units > 0 )
624                     {
625                         if ( !p_aout->fifo[i_fifo].b_next_frame )
626                         {
627                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->dsp.l_rate))) )
628                             {
629                                 break;
630                             }
631                         }
632
633                         if ( p_aout->fifo[i_fifo].l_units > l_units )
634                         {
635                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
636                             while ( l_buffer < l_buffer_limit )
637                             {
638                                 p_aout->s32_buffer[l_buffer++] +=
639                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
640                                 p_aout->s32_buffer[l_buffer++] +=
641                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
642
643                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
644                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
645                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
646                                 {
647                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
648                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
649                                 }
650                             }
651                             p_aout->fifo[i_fifo].l_units -= l_units;
652                             break;
653                         }
654                         else
655                         {
656                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
657                             /* p_aout->dsp.b_stereo == 1 */
658                             while ( l_buffer < l_buffer_limit )
659                             {
660                                 p_aout->s32_buffer[l_buffer++] +=
661                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
662                                 p_aout->s32_buffer[l_buffer++] +=
663                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
664
665                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
666                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
667                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
668                                 {
669                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
670                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
671                                 }
672                             }
673                             l_units -= p_aout->fifo[i_fifo].l_units;
674
675                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
676                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
677                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
678                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
679
680                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
681                             p_aout->fifo[i_fifo].l_next_frame += 1;
682                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
683                             p_aout->fifo[i_fifo].b_next_frame = 0;
684                         }
685                     }
686                     break;
687
688                 case AOUT_ADEC_STEREO_FIFO:
689                     if ( p_aout->fifo[i_fifo].b_die )
690                     {
691                         free( p_aout->fifo[i_fifo].buffer );
692                         free( p_aout->fifo[i_fifo].date );
693                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
694                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
695                         continue;
696                     }
697
698                     l_units = p_aout->l_units;
699                     l_buffer = 0;
700                     while ( l_units > 0 )
701                     {
702                         if ( !p_aout->fifo[i_fifo].b_next_frame )
703                         {
704                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->dsp.l_rate))) )
705                             {
706                                 break;
707                             }
708                         }
709
710                         if ( p_aout->fifo[i_fifo].l_units > l_units )
711                         {
712                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
713                             while ( l_buffer < l_buffer_limit )
714                             {
715                                 p_aout->s32_buffer[l_buffer++] +=
716                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
717                                 p_aout->s32_buffer[l_buffer++] +=
718                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
719
720                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
721                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
722                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
723                                 {
724                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
725                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
726                                 }
727                             }
728                             p_aout->fifo[i_fifo].l_units -= l_units;
729                             break;
730                         }
731                         else
732                         {
733                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
734                             /* p_aout->dsp.b_stereo == 1 */
735                             while ( l_buffer < l_buffer_limit )
736                             {
737                                 p_aout->s32_buffer[l_buffer++] +=
738                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
739                                 p_aout->s32_buffer[l_buffer++] +=
740                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
741
742                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
743                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
744                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
745                                 {
746                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
747                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
748                                 }
749                             }
750                             l_units -= p_aout->fifo[i_fifo].l_units;
751
752                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
753                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
754                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
755                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
756
757                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
758                             p_aout->fifo[i_fifo].l_next_frame += 1;
759                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
760                             p_aout->fifo[i_fifo].b_next_frame = 0;
761                         }
762                     }
763                     break;
764
765                 default:
766                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
767                     break;
768             }
769         }
770         vlc_mutex_unlock( &p_aout->fifos_lock );
771
772         l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
773
774         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
775         {
776             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
777             p_aout->s32_buffer[l_buffer] = 0;
778         }
779
780         aout_dspGetBufInfo( &p_aout->dsp );
781         l_bytes = (p_aout->dsp.buf_info.fragstotal * p_aout->dsp.buf_info.fragsize) - p_aout->dsp.buf_info.bytes;
782         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->dsp.l_rate)); /* sizeof(s16) << p_aout->dsp.b_stereo == 4 */
783         aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
784         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
785         {
786             msleep( p_aout->l_msleep );
787         }
788     }
789
790     vlc_mutex_lock( &p_aout->fifos_lock );
791     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
792     {
793         switch ( p_aout->fifo[i_fifo].i_type )
794         {
795             case AOUT_EMPTY_FIFO:
796                 break;
797
798             case AOUT_INTF_MONO_FIFO:
799             case AOUT_INTF_STEREO_FIFO:
800                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
801                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
802                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
803                 break;
804
805             case AOUT_ADEC_MONO_FIFO:
806             case AOUT_ADEC_STEREO_FIFO:
807                 free( p_aout->fifo[i_fifo].buffer );
808                 free( p_aout->fifo[i_fifo].date );
809                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
810                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
811                 break;
812
813             default:
814                 break;
815         }
816     }
817     vlc_mutex_unlock( &p_aout->fifos_lock );
818 }
819
820 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
821 {
822 }
823
824 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
825 {
826 }