1 /******************************************************************************
2 * audio_output.c : audio output thread
4 ******************************************************************************/
8 * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
10 * - Faire les optimisations dans les fonctions threads :
11 * = Stocker les "petits calculs" dans des variables au lieu de les refaire
13 * = Utiliser des tables pour les gros calculs
14 * - Faire une structure différente pour intf/adec fifo
15 * - Rajouter des vlc_cond_signal ?
19 /******************************************************************************
21 ******************************************************************************/
24 #include <sys/soundcard.h>
25 #include <stdio.h> /* "intf_msg.h" */
26 #include <stdlib.h> /* calloc(), malloc(), free() */
30 #include "mtime.h" /* mtime_t, mdate(), msleep() */
31 #include "vlc_thread.h"
33 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
35 #include "audio_output.h"
36 #include "audio_dsp.h"
39 /******************************************************************************
41 ******************************************************************************/
44 static int aout_SpawnThread( aout_thread_t * p_aout );
46 /* Creating as much aout_Thread functions as configurations is one solution,
47 * examining the different cases in the Thread loop of an unique function is
48 * another. I chose the first solution. */
49 void aout_Thread_S8_Mono ( aout_thread_t * p_aout );
50 void aout_Thread_U8_Mono ( aout_thread_t * p_aout );
51 void aout_Thread_S16_Mono ( aout_thread_t * p_aout );
52 void aout_Thread_U16_Mono ( aout_thread_t * p_aout );
53 void aout_Thread_S8_Stereo ( aout_thread_t * p_aout );
54 void aout_Thread_U8_Stereo ( aout_thread_t * p_aout );
55 void aout_Thread_S16_Stereo ( aout_thread_t * p_aout );
56 void aout_Thread_U16_Stereo ( aout_thread_t * p_aout );
58 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
59 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ );
61 /******************************************************************************
62 * aout_CreateThread: initialize audio thread
63 ******************************************************************************/
64 aout_thread_t *aout_CreateThread( int *pi_status )
66 aout_thread_t * p_aout; /* thread descriptor */
67 int i_status; /* thread status */
69 /* Allocate descriptor */
70 p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
76 //???? kludge to initialize some audio parameters - place this section somewhere
78 p_aout->dsp.i_format = AOUT_DEFAULT_FORMAT;
79 p_aout->dsp.psz_device = main_GetPszVariable( AOUT_DSP_VAR, AOUT_DSP_DEFAULT );
80 p_aout->dsp.b_stereo = main_GetIntVariable( AOUT_STEREO_VAR, AOUT_STEREO_DEFAULT );
81 p_aout->dsp.l_rate = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );
87 if ( aout_dspOpen( &p_aout->dsp ) )
92 if ( aout_dspReset( &p_aout->dsp ) )
94 aout_dspClose( &p_aout->dsp );
98 if ( aout_dspSetFormat( &p_aout->dsp ) )
100 aout_dspClose( &p_aout->dsp );
104 if ( aout_dspSetChannels( &p_aout->dsp ) )
106 aout_dspClose( &p_aout->dsp );
110 if ( aout_dspSetRate( &p_aout->dsp ) )
112 aout_dspClose( &p_aout->dsp );
116 intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, stereo=%i, rate=%li)\n",
117 p_aout->dsp.psz_device,
118 p_aout->dsp.i_format,
119 p_aout->dsp.b_stereo, p_aout->dsp.l_rate);
121 //?? maybe it would be cleaner to change SpawnThread prototype
122 //?? see vout to handle status correctly - however, it is not critical since
123 //?? this thread is only called in main is all calls are blocking
124 if( aout_SpawnThread( p_aout ) )
126 aout_dspClose( &p_aout->dsp );
134 /******************************************************************************
136 ******************************************************************************/
137 static int aout_SpawnThread( aout_thread_t * p_aout )
141 s64 s64_numerator, s64_denominator;
142 void * aout_thread = NULL;
144 intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
146 /* We want the audio output thread to live */
149 /* Initialize the fifos lock */
150 vlc_mutex_init( &p_aout->fifos_lock );
151 /* Initialize audio fifos : set all fifos as empty and initialize locks */
152 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
154 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
155 vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
156 vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
159 /* Compute the size (in audio units) of the audio output buffer. Although
160 * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
161 * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
162 p_aout->l_units = (long)( ((s64)p_aout->dsp.l_rate * AOUT_BUFFER_DURATION) / 1000000 );
164 /* Make aout_thread point to the right thread function, and compute the
165 * byte size of the audio output buffer */
166 switch ( p_aout->dsp.b_stereo )
168 /* Audio output is mono */
170 switch ( p_aout->dsp.i_format )
173 l_bytes = 1 * sizeof(u8) * p_aout->l_units;
174 aout_thread = (void *)aout_Thread_U8_Mono;
178 l_bytes = 1 * sizeof(s8) * p_aout->l_units;
179 aout_thread = (void *)aout_Thread_S8_Mono;
184 l_bytes = 1 * sizeof(u16) * p_aout->l_units;
185 aout_thread = (void *)aout_Thread_U16_Mono;
190 l_bytes = 1 * sizeof(s16) * p_aout->l_units;
191 aout_thread = (void *)aout_Thread_S16_Mono;
195 intf_ErrMsg("aout error: unknown audio output format (%i)\n",
196 p_aout->dsp.i_format);
201 /* Audio output is stereo */
203 switch ( p_aout->dsp.i_format )
206 l_bytes = 2 * sizeof(u8) * p_aout->l_units;
207 aout_thread = (void *)aout_Thread_U8_Stereo;
211 l_bytes = 2 * sizeof(s8) * p_aout->l_units;
212 aout_thread = (void *)aout_Thread_S8_Stereo;
217 l_bytes = 2 * sizeof(u16) * p_aout->l_units;
218 aout_thread = (void *)aout_Thread_U16_Stereo;
223 l_bytes = 2 * sizeof(s16) * p_aout->l_units;
224 aout_thread = (void *)aout_Thread_S16_Stereo;
228 intf_ErrMsg("aout error: unknown audio output format (%i)\n",
229 p_aout->dsp.i_format);
235 intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
236 p_aout->dsp.b_stereo + 1);
240 /* Allocate the memory needed by the audio output buffers, and set to zero
241 * the s32 buffer's memory */
242 if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
244 intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
247 if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << p_aout->dsp.b_stereo)) == NULL )
249 intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
250 free( p_aout->buffer );
254 /* Initialize the incremental structure that is used to work out the date
255 * of the first audio unit in the output buffer */
256 s64_numerator = (s64)p_aout->l_units * 1000000;
257 s64_denominator = (s64)p_aout->dsp.l_rate;
259 p_aout->date_increment.l_remainder = -(long)s64_denominator;
261 p_aout->date_increment.l_euclidean_integer = 0;
262 while ( s64_numerator >= s64_denominator )
264 p_aout->date_increment.l_euclidean_integer++;
265 s64_numerator -= s64_denominator;
268 p_aout->date_increment.l_euclidean_remainder = (long)s64_numerator;
270 p_aout->date_increment.l_euclidean_denominator = (long)s64_denominator;
272 /* Before launching the thread, we try to predict the date of the first
273 * audio unit in the first output buffer */
274 p_aout->date = mdate();
276 /* Launch the thread */
277 if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
279 intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
280 free( p_aout->buffer );
281 free( p_aout->s32_buffer );
285 intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
289 /******************************************************************************
291 ******************************************************************************/
292 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
294 //???? pi_status is not handled correctly: check vout how to do!
296 intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
298 /* Ask thread to kill itself and wait until it's done */
300 vlc_thread_join( p_aout->thread_id ); // only if pi_status is NULL
302 /* Free the allocated memory */
303 free( p_aout->buffer );
304 free( p_aout->s32_buffer );
306 /* Free the structure */
307 aout_dspClose( &p_aout->dsp );
308 intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->dsp.psz_device);
312 /******************************************************************************
314 ******************************************************************************/
315 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
319 /* Take the fifos lock */
320 vlc_mutex_lock( &p_aout->fifos_lock );
322 /* Looking for a free fifo structure */
323 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
325 if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
330 if ( i_fifo == AOUT_MAX_FIFOS )
332 intf_ErrMsg("aout error: no empty fifo available\n");
333 vlc_mutex_unlock( &p_aout->fifos_lock );
337 /* Initialize the new fifo structure */
338 switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
340 case AOUT_INTF_MONO_FIFO:
341 case AOUT_INTF_STEREO_FIFO:
342 p_aout->fifo[i_fifo].b_die = 0;
344 p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
345 p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
347 p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
349 p_aout->fifo[i_fifo].l_unit = 0;
350 InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->dsp.l_rate );
351 p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
354 case AOUT_ADEC_MONO_FIFO:
355 case AOUT_ADEC_STEREO_FIFO:
356 p_aout->fifo[i_fifo].b_die = 0;
358 p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
359 p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
361 p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
362 /* Allocate the memory needed to store the audio frames. As the
363 * fifo is a rotative fifo, we must be able to find out whether the
364 * fifo is full or empty, that's why we must in fact allocate memory
365 * for (AOUT_FIFO_SIZE+1) audio frames. */
366 if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
368 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
369 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
370 vlc_mutex_unlock( &p_aout->fifos_lock );
374 /* Allocate the memory needed to store the dates of the frames */
375 if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
377 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
378 free( p_aout->fifo[i_fifo].buffer );
379 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
380 vlc_mutex_unlock( &p_aout->fifos_lock );
384 /* Set the fifo's buffer as empty (the first frame that is to be
385 * played is also the first frame that is not to be played) */
386 p_aout->fifo[i_fifo].l_start_frame = 0;
387 /* p_aout->fifo[i_fifo].l_next_frame = 0; */
388 p_aout->fifo[i_fifo].l_end_frame = 0;
390 /* Waiting for the audio decoder to compute enough frames to work
391 * out the fifo's current rate (as soon as the decoder has decoded
392 * enough frames, the members of the fifo structure that are not
393 * initialized now will be calculated) */
394 p_aout->fifo[i_fifo].l_unit = 0; /* !! */
395 p_aout->fifo[i_fifo].b_start_frame = 0;
396 p_aout->fifo[i_fifo].b_next_frame = 0;
400 intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
401 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
402 vlc_mutex_unlock( &p_aout->fifos_lock );
406 /* Release the fifos lock */
407 vlc_mutex_unlock( &p_aout->fifos_lock );
409 /* Return the pointer to the fifo structure */
410 intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
411 return( &p_aout->fifo[i_fifo] );
414 /******************************************************************************
416 ******************************************************************************/
417 void aout_DestroyFifo( aout_fifo_t * p_fifo )
419 intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
423 /* Here are the local macros */
425 #define S32_TO_S16( sample ) \
428 #define UPDATE_INCREMENT( increment, integer ) \
429 if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 ) \
431 (integer) += (increment).l_euclidean_integer + 1; \
432 (increment).l_remainder -= (increment).l_euclidean_denominator; \
436 (integer) += (increment).l_euclidean_integer; \
439 /* Following functions are local */
441 /******************************************************************************
442 * InitializeIncrement
443 ******************************************************************************/
444 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
446 p_increment->l_remainder = -l_denominator;
448 p_increment->l_euclidean_integer = 0;
449 while ( l_numerator >= l_denominator )
451 p_increment->l_euclidean_integer++;
452 l_numerator -= l_denominator;
455 p_increment->l_euclidean_remainder = l_numerator;
457 p_increment->l_euclidean_denominator = l_denominator;
460 /******************************************************************************
462 ******************************************************************************/
463 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ )
465 long l_units, l_rate;
467 /* We take the lock */
468 vlc_mutex_lock( &p_fifo->data_lock );
470 /* Are we looking for a dated start frame ? */
471 if ( !p_fifo->b_start_frame )
473 while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
475 if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
477 p_fifo->b_start_frame = 1;
478 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
481 p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
483 if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
485 vlc_mutex_unlock( &p_fifo->data_lock );
490 if ( aout_date < p_fifo->date[p_fifo->l_start_frame] )
492 fprintf(stderr, "+");
493 vlc_mutex_unlock( &p_fifo->data_lock );
497 /* We are looking for the next dated frame */
498 while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
500 if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
503 if ( aout_date < p_fifo->date[p_fifo->l_next_frame] )
507 if ( p_fifo->date[p_fifo->l_start_frame] >= p_fifo->date[p_fifo->l_next_frame] )
509 fprintf( stderr, "aout debug: %lli >= %lli\n", p_fifo->date[p_fifo->l_start_frame], p_fifo->date[p_fifo->l_next_frame] );
510 p_fifo->date[p_fifo->l_start_frame] = p_fifo->date[p_fifo->l_next_frame] - ((1000000 * ((mtime_t)(p_fifo->l_frame_size * ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE))) >> p_fifo->b_stereo) / ((mtime_t)p_fifo->l_rate));
513 else if ( (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) > 1000000 )
515 fprintf( stderr, "aout debug: (%lli - %lli) > 1000000\n", p_fifo->date[p_fifo->l_next_frame], p_fifo->date[p_fifo->l_start_frame] );
516 p_fifo->date[p_fifo->l_start_frame] = p_fifo->date[p_fifo->l_next_frame] - ((1000000 * ((mtime_t)(p_fifo->l_frame_size * ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE))) >> p_fifo->b_stereo) / ((mtime_t)p_fifo->l_rate));
519 p_fifo->b_next_frame = 1;
526 fprintf(stderr, "-");
527 p_fifo->l_start_frame = p_fifo->l_next_frame;
531 p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
533 if ( p_fifo->l_next_frame == p_fifo->l_end_frame )
535 if ( (((p_fifo->l_end_frame + 1) - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) == 0 )
537 p_fifo->l_start_frame = 0;
538 p_fifo->b_start_frame = 0;
539 /* p_fifo->l_next_frame = 0; */
540 /* p_fifo->b_next_frame = 0; */
541 p_fifo->l_end_frame = 0;
543 vlc_mutex_unlock( &p_fifo->data_lock );
547 l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
549 l_rate = (long)( ((mtime_t)l_units * 1000000)
550 / (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) );
551 // fprintf( stderr, "aout debug: l_rate == %li\n", l_rate );
553 InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->dsp.l_rate );
555 p_fifo->l_units = (((l_units - (p_fifo->l_unit -
556 (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
557 * p_aout->dsp.l_rate) / l_rate) + 1;
559 /* We release the lock before leaving */
560 vlc_mutex_unlock( &p_fifo->data_lock );
564 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
568 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
572 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
576 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
580 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
584 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
588 long l_buffer, l_buffer_limit;
590 intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
592 /* As the s32_buffer was created with calloc(), we don't have to set this
593 * memory to zero and we can immediately jump into the thread's loop */
594 while ( !p_aout->b_die )
596 vlc_mutex_lock( &p_aout->fifos_lock );
597 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
599 switch ( p_aout->fifo[i_fifo].i_type )
601 case AOUT_EMPTY_FIFO:
604 case AOUT_INTF_MONO_FIFO:
605 if ( p_aout->fifo[i_fifo].b_die )
607 free( p_aout->fifo[i_fifo].buffer ); /* !! */
608 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
609 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
613 if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
616 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
618 p_aout->s32_buffer[l_buffer++] +=
619 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
620 p_aout->s32_buffer[l_buffer++] +=
621 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
622 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
624 p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
629 while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
631 p_aout->s32_buffer[l_buffer++] +=
632 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
633 p_aout->s32_buffer[l_buffer++] +=
634 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
635 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
637 free( p_aout->fifo[i_fifo].buffer ); /* !! */
638 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
639 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
643 case AOUT_INTF_STEREO_FIFO:
644 if ( p_aout->fifo[i_fifo].b_die )
646 free( p_aout->fifo[i_fifo].buffer ); /* !! */
647 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
648 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
652 if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
655 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
657 p_aout->s32_buffer[l_buffer++] +=
658 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
659 p_aout->s32_buffer[l_buffer++] +=
660 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
661 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
663 p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
668 while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo */
670 p_aout->s32_buffer[l_buffer++] +=
671 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
672 p_aout->s32_buffer[l_buffer++] +=
673 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
674 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
676 free( p_aout->fifo[i_fifo].buffer ); /* !! */
677 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
678 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
682 case AOUT_ADEC_MONO_FIFO:
683 if ( p_aout->fifo[i_fifo].b_die )
685 free( p_aout->fifo[i_fifo].buffer );
686 free( p_aout->fifo[i_fifo].date );
687 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
688 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
692 l_units = p_aout->l_units;
694 while ( l_units > 0 )
696 if ( !p_aout->fifo[i_fifo].b_next_frame )
698 if ( NextFrame(p_aout, &p_aout->fifo[i_fifo]/*, p_aout->date + (mtime_t)((l_buffer >> p_aout->dsp.b_stereo) / p_aout->dsp.l_rate)*/) )
704 if ( p_aout->fifo[i_fifo].l_units > l_units )
706 l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
707 while ( l_buffer < l_buffer_limit )
709 p_aout->s32_buffer[l_buffer++] +=
710 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
711 p_aout->s32_buffer[l_buffer++] +=
712 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
714 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
715 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
716 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
718 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
719 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
722 p_aout->fifo[i_fifo].l_units -= l_units;
727 l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
728 /* p_aout->dsp.b_stereo == 1 */
729 while ( l_buffer < l_buffer_limit )
731 p_aout->s32_buffer[l_buffer++] +=
732 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
733 p_aout->s32_buffer[l_buffer++] +=
734 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
736 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
737 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
738 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
740 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
741 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
744 l_units -= p_aout->fifo[i_fifo].l_units;
746 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
747 p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
748 vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
749 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
751 /* p_aout->fifo[i_fifo].b_start_frame = 1; */
752 p_aout->fifo[i_fifo].l_next_frame += 1;
753 p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
754 p_aout->fifo[i_fifo].b_next_frame = 0;
759 case AOUT_ADEC_STEREO_FIFO:
760 if ( p_aout->fifo[i_fifo].b_die )
762 free( p_aout->fifo[i_fifo].buffer );
763 free( p_aout->fifo[i_fifo].date );
764 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
765 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
769 l_units = p_aout->l_units;
771 while ( l_units > 0 )
773 if ( !p_aout->fifo[i_fifo].b_next_frame )
775 if ( NextFrame(p_aout, &p_aout->fifo[i_fifo]/*, p_aout->date + (mtime_t)((l_buffer >> p_aout->dsp.b_stereo) / p_aout->dsp.l_rate)*/) )
781 if ( p_aout->fifo[i_fifo].l_units > l_units )
783 l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
784 while ( l_buffer < l_buffer_limit )
786 p_aout->s32_buffer[l_buffer++] +=
787 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
788 p_aout->s32_buffer[l_buffer++] +=
789 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
791 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
792 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
793 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
795 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
796 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
799 p_aout->fifo[i_fifo].l_units -= l_units;
804 l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
805 /* p_aout->dsp.b_stereo == 1 */
806 while ( l_buffer < l_buffer_limit )
808 p_aout->s32_buffer[l_buffer++] +=
809 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
810 p_aout->s32_buffer[l_buffer++] +=
811 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
813 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
814 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
815 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
817 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
818 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
821 l_units -= p_aout->fifo[i_fifo].l_units;
823 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
824 p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
825 vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
826 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
828 /* p_aout->fifo[i_fifo].b_start_frame = 1; */
829 p_aout->fifo[i_fifo].l_next_frame += 1;
830 p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
831 p_aout->fifo[i_fifo].b_next_frame = 0;
837 intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
841 vlc_mutex_unlock( &p_aout->fifos_lock );
843 l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
845 for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
847 ((s16 *)p_aout->buffer)[l_buffer] = S32_TO_S16( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
848 p_aout->s32_buffer[l_buffer] = 0;
851 aout_dspGetBufInfo( &p_aout->dsp );
852 if ( p_aout->dsp.buf_info.fragments == p_aout->dsp.buf_info.fragstotal ) /* ?? */
854 aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
855 p_aout->date = mdate();
857 else if ( p_aout->dsp.buf_info.bytes >=
858 ((p_aout->dsp.buf_info.fragsize * p_aout->dsp.buf_info.fragstotal) -
859 (sizeof(s16) * l_buffer_limit)) )
861 aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
865 aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
866 msleep( p_aout->date_increment.l_euclidean_integer );
868 UPDATE_INCREMENT( p_aout->date_increment, p_aout->date )
871 vlc_mutex_lock( &p_aout->fifos_lock );
872 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
874 switch ( p_aout->fifo[i_fifo].i_type )
876 case AOUT_EMPTY_FIFO:
879 case AOUT_INTF_MONO_FIFO:
880 case AOUT_INTF_STEREO_FIFO:
881 free( p_aout->fifo[i_fifo].buffer ); /* !! */
882 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
883 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
886 case AOUT_ADEC_MONO_FIFO:
887 case AOUT_ADEC_STEREO_FIFO:
888 free( p_aout->fifo[i_fifo].buffer );
889 free( p_aout->fifo[i_fifo].date );
890 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
891 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
898 vlc_mutex_unlock( &p_aout->fifos_lock );
901 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
905 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )