1 /*****************************************************************************
2 * aout_u8.c: 8 bit unsigned audio output functions
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: aout_u8.c,v 1.4 2001/05/06 04:32:02 sam 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 "mtime.h" /* mtime_t, mdate(), msleep() */
37 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
39 #include "audio_output.h"
40 #include "aout_common.h"
42 /*****************************************************************************
44 *****************************************************************************/
45 static void U8MonoPlay ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
46 static void U8StereoPlay ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
48 /*****************************************************************************
50 *****************************************************************************/
51 void aout_U8MonoThread( aout_thread_t * p_aout )
54 long l_buffer, l_buffer_limit, l_bytes;
56 /* As the s32_buffer was created with calloc(), we don't have to set this
57 * memory to zero and we can immediately jump into the thread's loop */
58 while ( ! p_aout->b_die )
60 vlc_mutex_lock( &p_aout->fifos_lock );
62 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
64 if( p_aout->fifo[i_fifo].b_die )
66 aout_FreeFifo( &p_aout->fifo[i_fifo] );
70 U8MonoPlay( p_aout, &p_aout->fifo[i_fifo] );
74 vlc_mutex_unlock( &p_aout->fifos_lock );
76 l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
78 for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
80 ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->i_volume / 256 );
81 p_aout->s32_buffer[l_buffer] = 0;
84 l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
85 p_aout->date = mdate() + ((((mtime_t)(l_bytes / 1 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 1 */
86 p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
87 if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
89 msleep( p_aout->l_msleep );
93 vlc_mutex_lock( &p_aout->fifos_lock );
95 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
97 aout_FreeFifo( &p_aout->fifo[i_fifo] );
100 vlc_mutex_unlock( &p_aout->fifos_lock );
103 void aout_U8StereoThread( aout_thread_t * p_aout )
106 long l_buffer, l_buffer_limit, l_bytes;
108 intf_DbgMsg("adec debug: running audio output U8_S_thread (%p) (pid == %i)", p_aout, getpid());
110 /* As the s32_buffer was created with calloc(), we don't have to set this
111 * memory to zero and we can immediately jump into the thread's loop */
112 while ( ! p_aout->b_die )
114 vlc_mutex_lock( &p_aout->fifos_lock );
116 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
118 if( p_aout->fifo[i_fifo].b_die )
120 aout_FreeFifo( &p_aout->fifo[i_fifo] );
124 U8StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
128 vlc_mutex_unlock( &p_aout->fifos_lock );
130 l_buffer_limit = p_aout->l_units << 1 ; /* p_aout->b_stereo == 1 */
132 for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
134 ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256) + 128 ) * p_aout->i_volume / 256 );
135 p_aout->s32_buffer[l_buffer] = 0;
137 l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
138 p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
139 p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
140 if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
142 msleep( p_aout->l_msleep );
146 vlc_mutex_lock( &p_aout->fifos_lock );
148 for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
150 aout_FreeFifo( &p_aout->fifo[i_fifo] );
153 vlc_mutex_unlock( &p_aout->fifos_lock );
156 /* Following functions are local */
158 static void U8MonoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
161 long l_buffer_limit, l_units;
163 switch ( p_fifo->i_type )
165 case AOUT_EMPTY_FIFO:
169 case AOUT_INTF_MONO_FIFO:
171 if ( p_fifo->l_units > p_aout->l_units )
173 /* p_aout->b_stereo == 0 */
174 while ( l_buffer < (p_aout->l_units) )
176 p_aout->s32_buffer[l_buffer++] +=
177 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
178 p_aout->s32_buffer[l_buffer++] +=
179 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
180 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
182 p_fifo->l_units -= p_aout->l_units;
186 /* p_aout->b_stereo == 0 */
187 while ( l_buffer < (p_fifo->l_units) )
189 p_aout->s32_buffer[l_buffer++] +=
190 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
191 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
193 free( p_fifo->buffer ); /* !! */
194 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
195 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
199 case AOUT_INTF_STEREO_FIFO:
201 if ( p_fifo->l_units > p_aout->l_units )
203 /* p_aout->b_stereo == 0 */
204 while ( l_buffer < (p_aout->l_units) )
206 /* I mix half left - half right */
207 p_aout->s32_buffer[l_buffer++] +=
208 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
209 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
210 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
212 p_fifo->l_units -= p_aout->l_units;
216 /* p_aout->b_stereo == 0 */
217 while ( l_buffer < (p_fifo->l_units) )
219 /* I mix half left - half right */
220 p_aout->s32_buffer[l_buffer++] +=
221 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
222 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
223 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
225 free( p_fifo->buffer ); /* !! */
226 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
227 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
231 case AOUT_ADEC_MONO_FIFO:
233 l_units = p_aout->l_units;
235 while ( l_units > 0 )
237 if ( !p_fifo->b_next_frame )
239 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
245 if ( p_fifo->l_units > l_units )
247 /* p_aout->b_stereo == 0 */
248 l_buffer_limit = p_aout->l_units;
250 while ( l_buffer < l_buffer_limit )
252 p_aout->s32_buffer[l_buffer++] +=
253 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
255 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
256 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
257 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
259 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
260 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
263 p_fifo->l_units -= l_units;
268 /* p_aout->b_stereo == 0 */
269 l_buffer_limit = l_buffer + (p_fifo->l_units);
271 while ( l_buffer < l_buffer_limit )
273 p_aout->s32_buffer[l_buffer++] +=
274 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
276 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
277 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
278 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
280 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
281 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
284 l_units -= p_fifo->l_units;
286 vlc_mutex_lock( &p_fifo->data_lock );
287 p_fifo->l_start_frame = p_fifo->l_next_frame;
288 vlc_cond_signal( &p_fifo->data_wait );
289 vlc_mutex_unlock( &p_fifo->data_lock );
291 /* p_fifo->b_start_frame = 1; */
292 p_fifo->l_next_frame += 1;
293 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
294 p_fifo->b_next_frame = 0;
299 case AOUT_ADEC_STEREO_FIFO:
301 l_units = p_aout->l_units;
303 while ( l_units > 0 )
305 if ( !p_fifo->b_next_frame )
307 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
313 if ( p_fifo->l_units > l_units )
315 /* p_aout->b_stereo == 0 */
316 l_buffer_limit = p_aout->l_units;
318 while ( l_buffer < l_buffer_limit )
320 /* I mix half left - half right */
321 p_aout->s32_buffer[l_buffer++] +=
322 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
323 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
325 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
326 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
327 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
329 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
330 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
333 p_fifo->l_units -= l_units;
338 /* p_aout->b_stereo == 0 */
339 l_buffer_limit = l_buffer + (p_fifo->l_units);
341 while ( l_buffer < l_buffer_limit )
343 /* I mix half left - half right */
344 p_aout->s32_buffer[l_buffer++] +=
345 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
346 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
348 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
349 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
350 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
352 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
353 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
356 l_units -= p_fifo->l_units;
358 vlc_mutex_lock( &p_fifo->data_lock );
359 p_fifo->l_start_frame = p_fifo->l_next_frame;
360 vlc_cond_signal( &p_fifo->data_wait );
361 vlc_mutex_unlock( &p_fifo->data_lock );
363 /* p_fifo->b_start_frame = 1; */
364 p_fifo->l_next_frame += 1;
365 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
366 p_fifo->b_next_frame = 0;
373 intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
379 static void U8StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
382 long l_buffer_limit, l_units;
384 switch ( p_fifo->i_type )
386 case AOUT_EMPTY_FIFO:
390 case AOUT_INTF_MONO_FIFO:
392 if ( p_fifo->l_units > p_aout->l_units )
394 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
396 p_aout->s32_buffer[l_buffer++] +=
397 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
398 p_aout->s32_buffer[l_buffer++] +=
399 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
400 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
402 p_fifo->l_units -= p_aout->l_units;
406 while ( l_buffer < (p_fifo->l_units << 1) ) /* p_aout->b_stereo == 1 */
408 p_aout->s32_buffer[l_buffer++] +=
409 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
410 p_aout->s32_buffer[l_buffer++] +=
411 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
412 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
414 free( p_fifo->buffer ); /* !! */
415 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
416 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
420 case AOUT_INTF_STEREO_FIFO:
422 if ( p_fifo->l_units > p_aout->l_units )
424 while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
426 p_aout->s32_buffer[l_buffer++] +=
427 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
428 p_aout->s32_buffer[l_buffer++] +=
429 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
430 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
432 p_fifo->l_units -= p_aout->l_units;
436 while ( l_buffer < (p_fifo->l_units << 1) ) /* p_aout->b_stereo == 1 */
438 p_aout->s32_buffer[l_buffer++] +=
439 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
440 p_aout->s32_buffer[l_buffer++] +=
441 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
442 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
444 free( p_fifo->buffer ); /* !! */
445 p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
446 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
450 case AOUT_ADEC_MONO_FIFO:
452 l_units = p_aout->l_units;
454 while ( l_units > 0 )
456 if ( !p_fifo->b_next_frame )
458 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
464 if ( p_fifo->l_units > l_units )
466 l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
467 while ( l_buffer < l_buffer_limit )
469 p_aout->s32_buffer[l_buffer++] +=
470 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
471 p_aout->s32_buffer[l_buffer++] +=
472 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
474 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
475 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
476 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
478 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
479 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
482 p_fifo->l_units -= l_units;
487 /* p_aout->b_stereo == 1 */
488 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
490 while ( l_buffer < l_buffer_limit )
492 p_aout->s32_buffer[l_buffer++] +=
493 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
494 p_aout->s32_buffer[l_buffer++] +=
495 (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
497 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
498 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
499 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
501 p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
502 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
505 l_units -= p_fifo->l_units;
507 vlc_mutex_lock( &p_fifo->data_lock );
508 p_fifo->l_start_frame = p_fifo->l_next_frame;
509 vlc_cond_signal( &p_fifo->data_wait );
510 vlc_mutex_unlock( &p_fifo->data_lock );
512 /* p_fifo->b_start_frame = 1; */
513 p_fifo->l_next_frame += 1;
514 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
515 p_fifo->b_next_frame = 0;
520 case AOUT_ADEC_STEREO_FIFO:
522 l_units = p_aout->l_units;
524 while ( l_units > 0 )
526 if ( !p_fifo->b_next_frame )
528 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
534 if ( p_fifo->l_units > l_units )
536 l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
537 while ( l_buffer < l_buffer_limit )
539 p_aout->s32_buffer[l_buffer++] +=
540 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
541 p_aout->s32_buffer[l_buffer++] +=
542 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
544 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
545 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
546 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
548 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
549 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
552 p_fifo->l_units -= l_units;
557 /* p_aout->b_stereo == 1 */
558 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
560 while ( l_buffer < l_buffer_limit )
562 p_aout->s32_buffer[l_buffer++] +=
563 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
564 p_aout->s32_buffer[l_buffer++] +=
565 (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
567 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
568 if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
569 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
571 p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
572 ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
575 l_units -= p_fifo->l_units;
577 vlc_mutex_lock( &p_fifo->data_lock );
578 p_fifo->l_start_frame = p_fifo->l_next_frame;
579 vlc_cond_signal( &p_fifo->data_wait );
580 vlc_mutex_unlock( &p_fifo->data_lock );
582 /* p_fifo->b_start_frame = 1; */
583 p_fifo->l_next_frame += 1;
584 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
585 p_fifo->b_next_frame = 0;
591 intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);