1 /*****************************************************************************
2 * aout_u8.c: 8 bit unsigned audio output functions
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: aout_u8.c,v 1.8 2001/12/06 10:53:42 massiot Exp $
7 * Authors: Michel Kaempf <maxx@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
29 #include <stdio.h> /* "intf_msg.h" */
30 #include <stdlib.h> /* calloc(), malloc(), free() */
35 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
37 #include "mtime.h" /* mtime_t, mdate(), msleep() */
39 #include "audio_output.h"
40 #include "aout_common.h"
44 /*****************************************************************************
46 *****************************************************************************/
47 static void U8MonoPlay ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
48 static void U8StereoPlay ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
50 /*****************************************************************************
52 *****************************************************************************/
53 void aout_U8MonoThread( aout_thread_t * p_aout )
56 long l_buffer, l_buffer_limit, l_bytes;
58 /* As the s32_buffer was created with calloc(), we don't have to set this
59 * memory to zero and we can immediately jump into the thread's loop */
60 while ( ! p_aout->b_die )
62 vlc_mutex_lock( &p_aout->fifos_lock );
64 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
66 if( p_aout->fifo[i_fifo].b_die )
68 aout_FreeFifo( &p_aout->fifo[i_fifo] );
72 U8MonoPlay( p_aout, &p_aout->fifo[i_fifo] );
76 vlc_mutex_unlock( &p_aout->fifos_lock );
78 l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
80 for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
82 ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->i_volume / 256 );
83 p_aout->s32_buffer[l_buffer] = 0;
86 l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
87 /* sizeof(u8) << (p_aout->b_stereo) == 1 */
88 p_aout->date = mdate() + ((((mtime_t)((l_bytes + 4 * p_aout->i_latency) / 1)) * 1000000)
89 / ((mtime_t)p_aout->l_rate))
92 p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
93 if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
95 msleep( p_aout->l_msleep );
99 vlc_mutex_lock( &p_aout->fifos_lock );
101 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
103 aout_FreeFifo( &p_aout->fifo[i_fifo] );
106 vlc_mutex_unlock( &p_aout->fifos_lock );
109 void aout_U8StereoThread( aout_thread_t * p_aout )
112 long l_buffer, l_buffer_limit, l_bytes;
114 /* As the s32_buffer was created with calloc(), we don't have to set this
115 * memory to zero and we can immediately jump into the thread's loop */
116 while ( ! p_aout->b_die )
118 vlc_mutex_lock( &p_aout->fifos_lock );
120 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
122 if( p_aout->fifo[i_fifo].b_die )
124 aout_FreeFifo( &p_aout->fifo[i_fifo] );
128 U8StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
132 vlc_mutex_unlock( &p_aout->fifos_lock );
134 l_buffer_limit = p_aout->l_units << 1 ; /* p_aout->b_stereo == 1 */
136 for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
138 ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256) + 128 ) * p_aout->i_volume / 256 );
139 p_aout->s32_buffer[l_buffer] = 0;
141 l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
142 /* sizeof(u8) << (p_aout->b_stereo) == 2 */
143 p_aout->date = mdate() + ((((mtime_t)((l_bytes + 4 * p_aout->i_latency) / 2)) * 1000000)
144 / ((mtime_t)p_aout->l_rate))
147 p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
148 if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
150 msleep( p_aout->l_msleep );
154 vlc_mutex_lock( &p_aout->fifos_lock );
156 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
158 aout_FreeFifo( &p_aout->fifo[i_fifo] );
161 vlc_mutex_unlock( &p_aout->fifos_lock );
164 /* Following functions are local */
166 static void U8MonoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
169 long l_buffer_limit, l_units;
171 switch ( p_fifo->i_type )
173 case AOUT_EMPTY_FIFO:
177 case AOUT_INTF_MONO_FIFO:
179 if ( p_fifo->l_units > p_aout->l_units )
181 /* p_aout->b_stereo == 0 */
182 while ( l_buffer < (p_aout->l_units) )
184 p_aout->s32_buffer[l_buffer++] +=
185 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
186 p_aout->s32_buffer[l_buffer++] +=
187 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
188 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
190 p_fifo->l_units -= p_aout->l_units;
194 /* p_aout->b_stereo == 0 */
195 while ( l_buffer < (p_fifo->l_units) )
197 p_aout->s32_buffer[l_buffer++] +=
198 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
199 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
201 free( p_fifo->buffer ); /* !! */
202 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
203 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
207 case AOUT_INTF_STEREO_FIFO:
209 if ( p_fifo->l_units > p_aout->l_units )
211 /* p_aout->b_stereo == 0 */
212 while ( l_buffer < (p_aout->l_units) )
214 /* I mix half left - half right */
215 p_aout->s32_buffer[l_buffer++] +=
216 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
217 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
218 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
220 p_fifo->l_units -= p_aout->l_units;
224 /* p_aout->b_stereo == 0 */
225 while ( l_buffer < (p_fifo->l_units) )
227 /* I mix half left - half right */
228 p_aout->s32_buffer[l_buffer++] +=
229 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
230 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
231 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
233 free( p_fifo->buffer ); /* !! */
234 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
235 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
239 case AOUT_ADEC_MONO_FIFO:
241 l_units = p_aout->l_units;
243 while ( l_units > 0 )
245 if ( !p_fifo->b_next_frame )
247 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
253 if ( p_fifo->l_units > l_units )
255 /* p_aout->b_stereo == 0 */
256 l_buffer_limit = p_aout->l_units;
258 while ( l_buffer < l_buffer_limit )
260 p_aout->s32_buffer[l_buffer++] +=
261 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
263 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
264 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
265 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
267 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
268 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
271 p_fifo->l_units -= l_units;
276 /* p_aout->b_stereo == 0 */
277 l_buffer_limit = l_buffer + (p_fifo->l_units);
279 while ( l_buffer < l_buffer_limit )
281 p_aout->s32_buffer[l_buffer++] +=
282 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
284 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
285 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
286 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
288 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
289 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
292 l_units -= p_fifo->l_units;
294 vlc_mutex_lock( &p_fifo->data_lock );
295 p_fifo->l_start_frame = p_fifo->l_next_frame;
296 vlc_cond_signal( &p_fifo->data_wait );
297 vlc_mutex_unlock( &p_fifo->data_lock );
299 /* p_fifo->b_start_frame = 1; */
300 p_fifo->l_next_frame += 1;
301 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
302 p_fifo->b_next_frame = 0;
307 case AOUT_ADEC_STEREO_FIFO:
309 l_units = p_aout->l_units;
311 while ( l_units > 0 )
313 if ( !p_fifo->b_next_frame )
315 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
321 if ( p_fifo->l_units > l_units )
323 /* p_aout->b_stereo == 0 */
324 l_buffer_limit = p_aout->l_units;
326 while ( l_buffer < l_buffer_limit )
328 /* I mix half left - half right */
329 p_aout->s32_buffer[l_buffer++] +=
330 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
331 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
333 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
334 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
335 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
337 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
338 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
341 p_fifo->l_units -= l_units;
346 /* p_aout->b_stereo == 0 */
347 l_buffer_limit = l_buffer + (p_fifo->l_units);
349 while ( l_buffer < l_buffer_limit )
351 /* I mix half left - half right */
352 p_aout->s32_buffer[l_buffer++] +=
353 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
354 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
356 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
357 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
358 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
360 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
361 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
364 l_units -= p_fifo->l_units;
366 vlc_mutex_lock( &p_fifo->data_lock );
367 p_fifo->l_start_frame = p_fifo->l_next_frame;
368 vlc_cond_signal( &p_fifo->data_wait );
369 vlc_mutex_unlock( &p_fifo->data_lock );
371 /* p_fifo->b_start_frame = 1; */
372 p_fifo->l_next_frame += 1;
373 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
374 p_fifo->b_next_frame = 0;
381 intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
387 static void U8StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
390 long l_buffer_limit, l_units;
392 switch ( p_fifo->i_type )
394 case AOUT_EMPTY_FIFO:
398 case AOUT_INTF_MONO_FIFO:
400 if ( p_fifo->l_units > p_aout->l_units )
402 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
404 p_aout->s32_buffer[l_buffer++] +=
405 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
406 p_aout->s32_buffer[l_buffer++] +=
407 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
408 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
410 p_fifo->l_units -= p_aout->l_units;
414 while ( l_buffer < (p_fifo->l_units << 1) ) /* p_aout->b_stereo == 1 */
416 p_aout->s32_buffer[l_buffer++] +=
417 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
418 p_aout->s32_buffer[l_buffer++] +=
419 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
420 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
422 free( p_fifo->buffer ); /* !! */
423 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
424 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
428 case AOUT_INTF_STEREO_FIFO:
430 if ( p_fifo->l_units > p_aout->l_units )
432 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
434 p_aout->s32_buffer[l_buffer++] +=
435 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
436 p_aout->s32_buffer[l_buffer++] +=
437 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
438 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
440 p_fifo->l_units -= p_aout->l_units;
444 while ( l_buffer < (p_fifo->l_units << 1) ) /* p_aout->b_stereo == 1 */
446 p_aout->s32_buffer[l_buffer++] +=
447 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
448 p_aout->s32_buffer[l_buffer++] +=
449 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
450 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
452 free( p_fifo->buffer ); /* !! */
453 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
454 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
458 case AOUT_ADEC_MONO_FIFO:
460 l_units = p_aout->l_units;
462 while ( l_units > 0 )
464 if ( !p_fifo->b_next_frame )
466 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
472 if ( p_fifo->l_units > l_units )
474 l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
475 while ( l_buffer < l_buffer_limit )
477 p_aout->s32_buffer[l_buffer++] +=
478 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
479 p_aout->s32_buffer[l_buffer++] +=
480 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
482 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
483 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
484 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
486 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
487 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
490 p_fifo->l_units -= l_units;
495 /* p_aout->b_stereo == 1 */
496 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
498 while ( l_buffer < l_buffer_limit )
500 p_aout->s32_buffer[l_buffer++] +=
501 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
502 p_aout->s32_buffer[l_buffer++] +=
503 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
505 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
506 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
507 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
509 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
510 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
513 l_units -= p_fifo->l_units;
515 vlc_mutex_lock( &p_fifo->data_lock );
516 p_fifo->l_start_frame = p_fifo->l_next_frame;
517 vlc_cond_signal( &p_fifo->data_wait );
518 vlc_mutex_unlock( &p_fifo->data_lock );
520 /* p_fifo->b_start_frame = 1; */
521 p_fifo->l_next_frame += 1;
522 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
523 p_fifo->b_next_frame = 0;
528 case AOUT_ADEC_STEREO_FIFO:
530 l_units = p_aout->l_units;
532 while ( l_units > 0 )
534 if ( !p_fifo->b_next_frame )
536 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
542 if ( p_fifo->l_units > l_units )
544 l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
545 while ( l_buffer < l_buffer_limit )
547 p_aout->s32_buffer[l_buffer++] +=
548 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
549 p_aout->s32_buffer[l_buffer++] +=
550 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
552 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
553 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
554 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
556 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
557 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
560 p_fifo->l_units -= l_units;
565 /* p_aout->b_stereo == 1 */
566 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
568 while ( l_buffer < l_buffer_limit )
570 p_aout->s32_buffer[l_buffer++] +=
571 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
572 p_aout->s32_buffer[l_buffer++] +=
573 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
575 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
576 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
577 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
579 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
580 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
583 l_units -= p_fifo->l_units;
585 vlc_mutex_lock( &p_fifo->data_lock );
586 p_fifo->l_start_frame = p_fifo->l_next_frame;
587 vlc_cond_signal( &p_fifo->data_wait );
588 vlc_mutex_unlock( &p_fifo->data_lock );
590 /* p_fifo->b_start_frame = 1; */
591 p_fifo->l_next_frame += 1;
592 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
593 p_fifo->b_next_frame = 0;
599 intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);