]> git.sesse.net Git - vlc/blob - src/audio_output/aout_s16.c
26387d6e61c99ba73827af28a19f5c9f118be1b7
[vlc] / src / audio_output / aout_s16.c
1 /*****************************************************************************
2  * aout_s16.c: 16 bit signed audio output functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  *
6  * Authors: Michel Kaempf <maxx@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include "defs.h"
27
28 #include <stdio.h>                                           /* "intf_msg.h" */
29 #include <stdlib.h>                            /* calloc(), malloc(), free() */
30
31 #include "config.h"
32 #include "common.h"
33 #include "threads.h"
34 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
35
36 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
37
38 #include "audio_output.h"
39 #include "aout_common.h"
40
41 /*****************************************************************************
42  * Local prototypes
43  *****************************************************************************/
44 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
45
46 /*****************************************************************************
47  * Functions
48  *****************************************************************************/
49 void aout_S16MonoThread( aout_thread_t * p_aout )
50 {
51     intf_ErrMsg( "aout error: 16 bit signed mono thread unsupported" );
52 }
53
54 void aout_S16StereoThread( aout_thread_t * p_aout )
55 {
56     int  i_fifo;
57     long l_buffer, l_buffer_limit, l_bytes;
58
59     /* As the s32_buffer was created with calloc(), we don't have to set this
60      * memory to zero and we can immediately jump into the thread's loop */
61     while ( ! p_aout->b_die )
62     {
63         vlc_mutex_lock( &p_aout->fifos_lock );
64
65         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
66         {
67             if( p_aout->fifo[i_fifo].b_die )
68             {
69                 aout_FreeFifo( &p_aout->fifo[i_fifo] );
70             }
71             else
72             {
73                 S16StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
74             }
75         }
76
77         vlc_mutex_unlock( &p_aout->fifos_lock );
78
79         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
80
81         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
82         {
83             ((s16 *)p_aout->buffer)[l_buffer] =
84                      (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS )
85                             * p_aout->vol / 256 ) ;
86             p_aout->s32_buffer[l_buffer] = 0;
87         }
88
89         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
90 #if 0
91         fprintf(stderr,"l_bytes 1: %li\n",l_bytes);
92         fprintf(stderr,"  playing...\n");
93 #endif
94
95         /* sizeof(s16) << (p_aout->b_stereo) == 4 */
96         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000)
97                                    / ((mtime_t)p_aout->l_rate));
98         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
99                          l_buffer_limit * sizeof(s16) );
100 #if 0
101         fprintf( stderr,"l_bytes #: %li\n",
102                  p_aout->pf_getbufinfo( p_aout, l_buffer_limit ) );
103 #endif
104
105         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
106         {
107             msleep( p_aout->l_msleep );
108 #if 0
109             fprintf(stderr,"  sleeping...\n");
110             msleep( p_aout->l_msleep / 2);
111             l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
112             fprintf(stderr,"l_bytes *: %li\n",l_bytes);
113             msleep( p_aout->l_msleep / 2);
114         }
115         else
116         {
117             fprintf(stderr,"  not sleeping.\n");
118             l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
119             fprintf(stderr,"l_bytes 2: %li\n\n",l_bytes);
120 #endif
121         }
122     }
123
124     vlc_mutex_lock( &p_aout->fifos_lock );
125
126     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
127     {
128         aout_FreeFifo( &p_aout->fifo[i_fifo] );
129     }
130
131     vlc_mutex_unlock( &p_aout->fifos_lock );
132 }
133
134 /* Following functions are local */
135
136 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
137 {
138     long l_buffer = 0;
139     long l_buffer_limit, l_units;
140
141     switch ( p_fifo->i_type )
142     {
143     case AOUT_EMPTY_FIFO:
144
145         break;
146
147     case AOUT_INTF_MONO_FIFO:
148
149         if ( p_fifo->l_units > p_aout->l_units )
150         {
151             /* p_aout->b_stereo == 1 */
152             while ( l_buffer < (p_aout->l_units << 1) )
153             {
154                 p_aout->s32_buffer[l_buffer++] +=
155                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
156                 p_aout->s32_buffer[l_buffer++] +=
157                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
158                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
159             }
160             p_fifo->l_units -= p_aout->l_units;
161         }
162         else
163         {
164             /* p_aout->b_stereo == 1 */
165             while ( l_buffer < (p_fifo->l_units << 1) )
166             {
167                 p_aout->s32_buffer[l_buffer++] +=
168                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
169                 p_aout->s32_buffer[l_buffer++] +=
170                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
171                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
172             }
173             free( p_fifo->buffer ); /* !! */
174             p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
175         }
176         break;
177
178     case AOUT_INTF_STEREO_FIFO:
179
180         if ( p_fifo->l_units > p_aout->l_units )
181         {
182             /* p_aout->b_stereo == 1 */
183             while ( l_buffer < (p_aout->l_units << 1) )
184             {
185                 p_aout->s32_buffer[l_buffer++] +=
186                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
187                 p_aout->s32_buffer[l_buffer++] +=
188                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
189                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
190             }
191             p_fifo->l_units -= p_aout->l_units;
192         }
193         else
194         {
195             /* p_aout->b_stereo == 1 */
196             while ( l_buffer < (p_fifo->l_units << 1) )
197             {
198                 p_aout->s32_buffer[l_buffer++] +=
199                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
200                 p_aout->s32_buffer[l_buffer++] +=
201                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
202                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
203             }
204             free( p_fifo->buffer );
205             p_fifo->i_type = AOUT_EMPTY_FIFO;
206         }
207         break;
208
209     case AOUT_ADEC_MONO_FIFO:
210
211         l_units = p_aout->l_units;
212         while ( l_units > 0 )
213         {
214             if ( !p_fifo->b_next_frame )
215             {
216                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
217                 {
218                     break;
219                 }
220             }
221
222             if ( p_fifo->l_units > l_units )
223             {
224                 /* p_aout->b_stereo == 1 */
225                 l_buffer_limit = p_aout->l_units << 1;
226
227                 while ( l_buffer < l_buffer_limit )
228                 {
229                     p_aout->s32_buffer[l_buffer++] +=
230                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
231                     p_aout->s32_buffer[l_buffer++] +=
232                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
233
234                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
235                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
236                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
237                     {
238                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
239                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
240                     }
241                 }
242                 p_fifo->l_units -= l_units;
243                 break;
244             }
245             else
246             {
247                 /* p_aout->b_stereo == 1 */
248                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
249
250                 while ( l_buffer < l_buffer_limit )
251                 {
252                     p_aout->s32_buffer[l_buffer++] +=
253                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
254                     p_aout->s32_buffer[l_buffer++] +=
255                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
256
257                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
258                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
259                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
260                     {
261                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
262                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
263                     }
264                 }
265                 l_units -= p_fifo->l_units;
266
267                 vlc_mutex_lock( &p_fifo->data_lock );
268                 p_fifo->l_start_frame = p_fifo->l_next_frame;
269                 vlc_cond_signal( &p_fifo->data_wait );
270                 vlc_mutex_unlock( &p_fifo->data_lock );
271
272                 /* p_fifo->b_start_frame = 1; */
273                 p_fifo->l_next_frame += 1;
274                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
275                 p_fifo->b_next_frame = 0;
276             }
277         }
278         break;
279
280     case AOUT_ADEC_STEREO_FIFO:
281
282         l_units = p_aout->l_units;
283         while ( l_units > 0 )
284         {
285             if ( !p_fifo->b_next_frame )
286             {
287                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
288                 {
289                     break;
290                 }
291             }
292
293             if ( p_fifo->l_units > l_units )
294             {
295                 /* p_aout->b_stereo == 1 */
296                 l_buffer_limit = p_aout->l_units << 1;
297
298                 while ( l_buffer < l_buffer_limit )
299                 {
300                     p_aout->s32_buffer[l_buffer++] +=
301                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
302                     p_aout->s32_buffer[l_buffer++] +=
303                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
304
305                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
306                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
307                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
308                     {
309                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
310                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
311                     }
312                 }
313                 p_fifo->l_units -= l_units;
314                 break;
315             }
316             else
317             {
318                 /* p_aout->b_stereo == 1 */
319                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
320
321                 while ( l_buffer < l_buffer_limit )
322                 {
323                     p_aout->s32_buffer[l_buffer++] +=
324                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
325                     p_aout->s32_buffer[l_buffer++] +=
326                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
327
328                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
329                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
330                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
331                     {
332                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
333                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
334                     }
335                 }
336                 l_units -= p_fifo->l_units;
337
338                 vlc_mutex_lock( &p_fifo->data_lock );
339                 p_fifo->l_start_frame = p_fifo->l_next_frame;
340                 vlc_cond_signal( &p_fifo->data_wait );
341                 vlc_mutex_unlock( &p_fifo->data_lock );
342
343                 /* p_fifo->b_start_frame = 1; */
344                 p_fifo->l_next_frame += 1;
345                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
346                 p_fifo->b_next_frame = 0;
347             }
348         }
349         break;
350
351     default:
352
353         intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
354         break;
355     }
356 }
357