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"
38 /******************************************************************************
40 ******************************************************************************/
42 /* Creating as much aout_Thread functions as configurations is one solution,
43 * examining the different cases in the Thread loop of an unique function is
44 * another. I chose the first solution. */
45 void aout_Thread_S8_Mono ( aout_thread_t * p_aout );
46 void aout_Thread_U8_Mono ( aout_thread_t * p_aout );
47 void aout_Thread_S16_Mono ( aout_thread_t * p_aout );
48 void aout_Thread_U16_Mono ( aout_thread_t * p_aout );
49 void aout_Thread_S8_Stereo ( aout_thread_t * p_aout );
50 void aout_Thread_U8_Stereo ( aout_thread_t * p_aout );
51 void aout_Thread_S16_Stereo ( aout_thread_t * p_aout );
52 void aout_Thread_U16_Stereo ( aout_thread_t * p_aout );
54 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
55 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ );
57 /******************************************************************************
59 ******************************************************************************/
60 int aout_Open( aout_thread_t * p_aout )
62 if ( aout_dspOpen( &p_aout->dsp ) )
67 if ( aout_dspReset( &p_aout->dsp ) )
69 aout_dspClose( &p_aout->dsp );
73 if ( aout_dspSetFormat( &p_aout->dsp ) )
75 aout_dspClose( &p_aout->dsp );
79 if ( aout_dspSetChannels( &p_aout->dsp ) )
81 aout_dspClose( &p_aout->dsp );
85 if ( aout_dspSetRate( &p_aout->dsp ) )
87 aout_dspClose( &p_aout->dsp );
91 intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, stereo=%i, rate=%li)\n",
92 p_aout->dsp.psz_device,
94 p_aout->dsp.b_stereo, p_aout->dsp.l_rate);
99 /******************************************************************************
101 ******************************************************************************/
102 int aout_SpawnThread( aout_thread_t * p_aout )
106 s64 s64_numerator, s64_denominator;
107 void * aout_thread = NULL;
109 intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
111 /* We want the audio output thread to live */
114 /* Initialize the fifos lock */
115 vlc_mutex_init( &p_aout->fifos_lock );
116 /* Initialize audio fifos : set all fifos as empty and initialize locks */
117 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
119 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
120 vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
121 vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
124 /* Compute the size (in audio units) of the audio output buffer. Although
125 * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
126 * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
127 p_aout->l_units = (long)( ((s64)p_aout->dsp.l_rate * AOUT_BUFFER_DURATION) / 1000000 );
129 /* Make aout_thread point to the right thread function, and compute the
130 * byte size of the audio output buffer */
131 switch ( p_aout->dsp.b_stereo )
133 /* Audio output is mono */
135 switch ( p_aout->dsp.i_format )
138 l_bytes = 1 * sizeof(u8) * p_aout->l_units;
139 aout_thread = (void *)aout_Thread_U8_Mono;
143 l_bytes = 1 * sizeof(s8) * p_aout->l_units;
144 aout_thread = (void *)aout_Thread_S8_Mono;
149 l_bytes = 1 * sizeof(u16) * p_aout->l_units;
150 aout_thread = (void *)aout_Thread_U16_Mono;
155 l_bytes = 1 * sizeof(s16) * p_aout->l_units;
156 aout_thread = (void *)aout_Thread_S16_Mono;
160 intf_ErrMsg("aout error: unknown audio output format (%i)\n",
161 p_aout->dsp.i_format);
166 /* Audio output is stereo */
168 switch ( p_aout->dsp.i_format )
171 l_bytes = 2 * sizeof(u8) * p_aout->l_units;
172 aout_thread = (void *)aout_Thread_U8_Stereo;
176 l_bytes = 2 * sizeof(s8) * p_aout->l_units;
177 aout_thread = (void *)aout_Thread_S8_Stereo;
182 l_bytes = 2 * sizeof(u16) * p_aout->l_units;
183 aout_thread = (void *)aout_Thread_U16_Stereo;
188 l_bytes = 2 * sizeof(s16) * p_aout->l_units;
189 aout_thread = (void *)aout_Thread_S16_Stereo;
193 intf_ErrMsg("aout error: unknown audio output format (%i)\n",
194 p_aout->dsp.i_format);
200 intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
201 p_aout->dsp.b_stereo + 1);
205 /* Allocate the memory needed by the audio output buffers, and set to zero
206 * the s32 buffer's memory */
207 if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
209 intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
212 if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << p_aout->dsp.b_stereo)) == NULL )
214 intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
215 free( p_aout->buffer );
219 /* Initialize the incremental structure that is used to work out the date
220 * of the first audio unit in the output buffer */
221 s64_numerator = (s64)p_aout->l_units * 1000000;
222 s64_denominator = (s64)p_aout->dsp.l_rate;
224 p_aout->date_increment.l_remainder = -(long)s64_denominator;
226 p_aout->date_increment.l_euclidean_integer = 0;
227 while ( s64_numerator >= s64_denominator )
229 p_aout->date_increment.l_euclidean_integer++;
230 s64_numerator -= s64_denominator;
233 p_aout->date_increment.l_euclidean_remainder = (long)s64_numerator;
235 p_aout->date_increment.l_euclidean_denominator = (long)s64_denominator;
237 /* Before launching the thread, we try to predict the date of the first
238 * audio unit in the first output buffer */
239 p_aout->date = mdate();
241 /* Launch the thread */
242 if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func)aout_thread, p_aout ) )
244 intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
245 free( p_aout->buffer );
246 free( p_aout->s32_buffer );
250 intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
254 /******************************************************************************
256 ******************************************************************************/
257 void aout_CancelThread( aout_thread_t * p_aout )
259 intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
261 /* Ask thread to kill itself and wait until it's done */
263 vlc_thread_join( p_aout->thread_id );
265 /* Free the allocated memory */
266 free( p_aout->buffer );
267 free( p_aout->s32_buffer );
270 /******************************************************************************
272 ******************************************************************************/
273 void aout_Close( aout_thread_t * p_aout )
275 aout_dspClose( &p_aout->dsp );
276 intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->dsp.psz_device);
279 /******************************************************************************
281 ******************************************************************************/
282 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
286 /* Take the fifos lock */
287 vlc_mutex_lock( &p_aout->fifos_lock );
289 /* Looking for a free fifo structure */
290 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
292 if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
297 if ( i_fifo == AOUT_MAX_FIFOS )
299 intf_ErrMsg("aout error: no empty fifo available\n");
300 vlc_mutex_unlock( &p_aout->fifos_lock );
304 /* Initialize the new fifo structure */
305 switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
307 case AOUT_INTF_MONO_FIFO:
308 case AOUT_INTF_STEREO_FIFO:
309 p_aout->fifo[i_fifo].b_die = 0;
311 p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
312 p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
314 p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
316 p_aout->fifo[i_fifo].l_unit = 0;
317 InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->dsp.l_rate );
318 p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
321 case AOUT_ADEC_MONO_FIFO:
322 case AOUT_ADEC_STEREO_FIFO:
325 p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
326 p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
328 p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
329 /* Allocate the memory needed to store the audio frames. As the
330 * fifo is a rotative fifo, we must be able to find out whether the
331 * fifo is full or empty, that's why we must in fact allocate memory
332 * for (AOUT_FIFO_SIZE+1) audio frames. */
333 if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
335 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
336 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
337 vlc_mutex_unlock( &p_aout->fifos_lock );
341 /* Allocate the memory needed to store the dates of the frames */
342 if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
344 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
345 free( p_aout->fifo[i_fifo].buffer );
346 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
347 vlc_mutex_unlock( &p_aout->fifos_lock );
351 /* Set the fifo's buffer as empty (the first frame that is to be
352 * played is also the first frame that is not to be played) */
353 p_aout->fifo[i_fifo].l_start_frame = 0;
354 /* p_aout->fifo[i_fifo].l_next_frame = 0; */
355 p_aout->fifo[i_fifo].l_end_frame = 0;
357 /* Waiting for the audio decoder to compute enough frames to work
358 * out the fifo's current rate (as soon as the decoder has decoded
359 * enough frames, the members of the fifo structure that are not
360 * initialized now will be calculated) */
361 p_aout->fifo[i_fifo].l_unit = 0; /* !! */
362 p_aout->fifo[i_fifo].b_start_frame = 0;
363 p_aout->fifo[i_fifo].b_next_frame = 0;
367 intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
368 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
369 vlc_mutex_unlock( &p_aout->fifos_lock );
373 /* Release the fifos lock */
374 vlc_mutex_unlock( &p_aout->fifos_lock );
376 /* Return the pointer to the fifo structure */
377 intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
378 return( &p_aout->fifo[i_fifo] );
381 /******************************************************************************
383 ******************************************************************************/
384 void aout_DestroyFifo( aout_fifo_t * p_fifo )
386 intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
390 /* Here are the local macros */
392 #define S32_TO_S16( sample ) \
395 #define UPDATE_INCREMENT( increment, integer ) \
396 if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 ) \
398 (integer) += (increment).l_euclidean_integer + 1; \
399 (increment).l_remainder -= (increment).l_euclidean_denominator; \
403 (integer) += (increment).l_euclidean_integer; \
406 /* Following functions are local */
408 /******************************************************************************
409 * InitializeIncrement
410 ******************************************************************************/
411 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
413 p_increment->l_remainder = -l_denominator;
415 p_increment->l_euclidean_integer = 0;
416 while ( l_numerator >= l_denominator )
418 p_increment->l_euclidean_integer++;
419 l_numerator -= l_denominator;
422 p_increment->l_euclidean_remainder = l_numerator;
424 p_increment->l_euclidean_denominator = l_denominator;
427 /******************************************************************************
429 ******************************************************************************/
430 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo/*, mtime_t aout_date*/ )
432 long l_units, l_rate;
434 /* We take the lock */
435 vlc_mutex_lock( &p_fifo->data_lock );
437 /* Are we looking for a dated start frame ? */
438 if ( !p_fifo->b_start_frame )
440 while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
442 if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
444 p_fifo->b_start_frame = 1;
445 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
448 p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
450 if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
452 vlc_mutex_unlock( &p_fifo->data_lock );
457 if ( aout_date < p_fifo->date[p_fifo->l_start_frame] )
459 fprintf(stderr, "+");
460 vlc_mutex_unlock( &p_fifo->data_lock );
464 /* We are looking for the next dated frame */
465 while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
467 if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
470 if ( aout_date < p_fifo->date[p_fifo->l_next_frame] )
474 if ( p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame] > 1000000 )
476 p_fifo->date[p_fifo->l_start_frame] = p_fifo->date[p_fifo->l_next_frame] - ((1000000 * AOUT_FRAME_SIZE * ((mtime_t)((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE)) >> p_fifo->b_stereo) / ((mtime_t)p_fifo->l_rate));
479 p_fifo->b_next_frame = 1;
485 fprintf(stderr, "-");
486 p_fifo->l_start_frame = p_fifo->l_next_frame;
490 p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
492 if ( p_fifo->l_next_frame == p_fifo->l_end_frame )
494 if ( (((p_fifo->l_end_frame + 1) - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) == 0 )
496 p_fifo->l_start_frame = 0;
497 p_fifo->b_start_frame = 0;
498 /* p_fifo->l_next_frame = 0; */
499 /* p_fifo->b_next_frame = 0; */
500 p_fifo->l_end_frame = 0;
502 vlc_mutex_unlock( &p_fifo->data_lock );
506 l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
508 l_rate = (long)( ((mtime_t)l_units * 1000000)
509 / (p_fifo->date[p_fifo->l_next_frame] - p_fifo->date[p_fifo->l_start_frame]) );
511 InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->dsp.l_rate );
513 p_fifo->l_units = (((l_units - (p_fifo->l_unit -
514 (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
515 * p_aout->dsp.l_rate) / l_rate) + 1;
517 /* We release the lock before leaving */
518 vlc_mutex_unlock( &p_fifo->data_lock );
522 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
526 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
530 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
534 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
538 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
542 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
546 long l_buffer, l_buffer_limit;
548 intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
550 /* As the s32_buffer was created with calloc(), we don't have to set this
551 * memory to zero and we can immediately jump into the thread's loop */
552 while ( !p_aout->b_die )
554 vlc_mutex_lock( &p_aout->fifos_lock );
555 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
557 switch ( p_aout->fifo[i_fifo].i_type )
559 case AOUT_EMPTY_FIFO:
562 case AOUT_INTF_MONO_FIFO:
563 if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
566 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
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 )
574 p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
579 while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
581 p_aout->s32_buffer[l_buffer++] +=
582 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
583 p_aout->s32_buffer[l_buffer++] +=
584 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
585 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
587 free( p_aout->fifo[i_fifo].buffer ); /* !! */
588 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
589 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
593 case AOUT_INTF_STEREO_FIFO:
594 if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
597 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->dsp.b_stereo == 1 */
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 )
605 p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
610 while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->dsp.b_stereo */
612 p_aout->s32_buffer[l_buffer++] +=
613 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
614 p_aout->s32_buffer[l_buffer++] +=
615 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
616 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
618 free( p_aout->fifo[i_fifo].buffer ); /* !! */
619 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
620 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
624 case AOUT_ADEC_MONO_FIFO:
625 l_units = p_aout->l_units;
627 while ( l_units > 0 )
629 if ( !p_aout->fifo[i_fifo].b_next_frame )
631 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)*/) )
637 if ( p_aout->fifo[i_fifo].l_units > l_units )
639 l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
640 while ( l_buffer < l_buffer_limit )
642 p_aout->s32_buffer[l_buffer++] +=
643 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
644 p_aout->s32_buffer[l_buffer++] +=
645 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
647 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
648 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
649 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
651 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
652 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
655 p_aout->fifo[i_fifo].l_units -= l_units;
660 l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
661 /* p_aout->dsp.b_stereo == 1 */
662 while ( l_buffer < l_buffer_limit )
664 p_aout->s32_buffer[l_buffer++] +=
665 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
666 p_aout->s32_buffer[l_buffer++] +=
667 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
669 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
670 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
671 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
673 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
674 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
677 l_units -= p_aout->fifo[i_fifo].l_units;
679 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
680 p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
681 vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
682 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
684 /* p_aout->fifo[i_fifo].b_start_frame = 1; */
685 p_aout->fifo[i_fifo].l_next_frame += 1;
686 p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
687 p_aout->fifo[i_fifo].b_next_frame = 0;
692 case AOUT_ADEC_STEREO_FIFO:
693 l_units = p_aout->l_units;
695 while ( l_units > 0 )
697 if ( !p_aout->fifo[i_fifo].b_next_frame )
699 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)*/) )
705 if ( p_aout->fifo[i_fifo].l_units > l_units )
707 l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
708 while ( l_buffer < l_buffer_limit )
710 p_aout->s32_buffer[l_buffer++] +=
711 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
712 p_aout->s32_buffer[l_buffer++] +=
713 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
715 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
716 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
717 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
719 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
720 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
723 p_aout->fifo[i_fifo].l_units -= l_units;
728 l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
729 /* p_aout->dsp.b_stereo == 1 */
730 while ( l_buffer < l_buffer_limit )
732 p_aout->s32_buffer[l_buffer++] +=
733 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
734 p_aout->s32_buffer[l_buffer++] +=
735 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
737 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
738 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
739 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
741 p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
742 ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
745 l_units -= p_aout->fifo[i_fifo].l_units;
747 vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
748 p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
749 vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
750 vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
752 /* p_aout->fifo[i_fifo].b_start_frame = 1; */
753 p_aout->fifo[i_fifo].l_next_frame += 1;
754 p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
755 p_aout->fifo[i_fifo].b_next_frame = 0;
761 intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
765 vlc_mutex_unlock( &p_aout->fifos_lock );
767 l_buffer_limit = p_aout->l_units << 1; /* p_aout->dsp.b_stereo == 1 */
769 for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
771 ((s16 *)p_aout->buffer)[l_buffer] = S32_TO_S16( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
772 p_aout->s32_buffer[l_buffer] = 0;
775 aout_dspGetBufInfo( &p_aout->dsp );
776 if ( p_aout->dsp.buf_info.fragments == p_aout->dsp.buf_info.fragstotal ) /* ?? */
778 aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
779 p_aout->date = mdate();
781 else if ( p_aout->dsp.buf_info.bytes >=
782 ((p_aout->dsp.buf_info.fragsize * p_aout->dsp.buf_info.fragstotal) -
783 (sizeof(s16) * l_buffer_limit)) )
785 aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
789 aout_dspPlaySamples( &p_aout->dsp, (byte_t *)p_aout->buffer, sizeof(s16) * l_buffer_limit );
790 msleep( p_aout->date_increment.l_euclidean_integer );
792 UPDATE_INCREMENT( p_aout->date_increment, p_aout->date )
795 vlc_mutex_lock( &p_aout->fifos_lock );
796 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
798 switch ( p_aout->fifo[i_fifo].i_type )
800 case AOUT_EMPTY_FIFO:
803 case AOUT_INTF_MONO_FIFO:
804 case AOUT_INTF_STEREO_FIFO:
805 free( p_aout->fifo[i_fifo].buffer ); /* !! */
806 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
807 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
810 case AOUT_ADEC_MONO_FIFO:
811 case AOUT_ADEC_STEREO_FIFO:
812 free( p_aout->fifo[i_fifo].buffer );
813 free( p_aout->fifo[i_fifo].date );
814 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
815 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
822 vlc_mutex_unlock( &p_aout->fifos_lock );
825 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
829 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )