]> git.sesse.net Git - vlc/blob - src/audio_output/aout_s16.c
* Updated the TODO list.
[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] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
84             p_aout->s32_buffer[l_buffer] = 0;
85         }
86
87         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
88         //fprintf(stderr,"l_bytes 1: %li\n",l_bytes);
89         //fprintf(stderr,"  playing...\n");
90         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
91         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
92         //fprintf(stderr,"l_bytes #: %li\n",p_aout->pf_getbufinfo( p_aout, l_buffer_limit ));
93         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
94         {
95         //fprintf(stderr,"  sleeping...\n");
96             msleep( p_aout->l_msleep / 2);
97         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
98         //fprintf(stderr,"l_bytes *: %li\n",l_bytes);
99             msleep( p_aout->l_msleep / 2);
100         }
101         else
102         //fprintf(stderr,"  not sleeping.\n");
103         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
104         //fprintf(stderr,"l_bytes 2: %li\n\n",l_bytes);
105     }
106
107     vlc_mutex_lock( &p_aout->fifos_lock );
108
109     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
110     {
111         aout_FreeFifo( &p_aout->fifo[i_fifo] );
112     }
113
114     vlc_mutex_unlock( &p_aout->fifos_lock );
115 }
116
117 /* Following functions are local */
118
119 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
120 {
121     long l_buffer = 0;
122     long l_buffer_limit, l_units;
123
124     switch ( p_fifo->i_type )
125     {
126     case AOUT_EMPTY_FIFO:
127
128         break;
129
130     case AOUT_INTF_MONO_FIFO:
131
132         if ( p_fifo->l_units > p_aout->l_units )
133         {
134             /* p_aout->b_stereo == 1 */
135             while ( l_buffer < (p_aout->l_units << 1) )
136             {
137                 p_aout->s32_buffer[l_buffer++] +=
138                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
139                 p_aout->s32_buffer[l_buffer++] +=
140                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
141                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
142             }
143             p_fifo->l_units -= p_aout->l_units;
144         }
145         else
146         {
147             /* p_aout->b_stereo == 1 */
148             while ( l_buffer < (p_fifo->l_units << 1) )
149             {
150                 p_aout->s32_buffer[l_buffer++] +=
151                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
152                 p_aout->s32_buffer[l_buffer++] +=
153                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
154                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
155             }
156             free( p_fifo->buffer ); /* !! */
157             p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
158         }
159         break;
160
161     case AOUT_INTF_STEREO_FIFO:
162
163         if ( p_fifo->l_units > p_aout->l_units )
164         {
165             /* p_aout->b_stereo == 1 */
166             while ( l_buffer < (p_aout->l_units << 1) )
167             {
168                 p_aout->s32_buffer[l_buffer++] +=
169                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
170                 p_aout->s32_buffer[l_buffer++] +=
171                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
172                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
173             }
174             p_fifo->l_units -= p_aout->l_units;
175         }
176         else
177         {
178             /* p_aout->b_stereo == 1 */
179             while ( l_buffer < (p_fifo->l_units << 1) )
180             {
181                 p_aout->s32_buffer[l_buffer++] +=
182                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
183                 p_aout->s32_buffer[l_buffer++] +=
184                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
185                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
186             }
187             free( p_fifo->buffer );
188             p_fifo->i_type = AOUT_EMPTY_FIFO;
189         }
190         break;
191
192     case AOUT_ADEC_MONO_FIFO:
193
194         l_units = p_aout->l_units;
195         while ( l_units > 0 )
196         {
197             if ( !p_fifo->b_next_frame )
198             {
199                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
200                 {
201                     break;
202                 }
203             }
204
205             if ( p_fifo->l_units > l_units )
206             {
207                 /* p_aout->b_stereo == 1 */
208                 l_buffer_limit = p_aout->l_units << 1;
209
210                 while ( l_buffer < l_buffer_limit )
211                 {
212                     p_aout->s32_buffer[l_buffer++] +=
213                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
214                     p_aout->s32_buffer[l_buffer++] +=
215                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
216
217                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
218                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
219                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
220                     {
221                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
222                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
223                     }
224                 }
225                 p_fifo->l_units -= l_units;
226                 break;
227             }
228             else
229             {
230                 /* p_aout->b_stereo == 1 */
231                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
232
233                 while ( l_buffer < l_buffer_limit )
234                 {
235                     p_aout->s32_buffer[l_buffer++] +=
236                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
237                     p_aout->s32_buffer[l_buffer++] +=
238                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
239
240                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
241                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
242                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
243                     {
244                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
245                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
246                     }
247                 }
248                 l_units -= p_fifo->l_units;
249
250                 vlc_mutex_lock( &p_fifo->data_lock );
251                 p_fifo->l_start_frame = p_fifo->l_next_frame;
252                 vlc_cond_signal( &p_fifo->data_wait );
253                 vlc_mutex_unlock( &p_fifo->data_lock );
254
255                 /* p_fifo->b_start_frame = 1; */
256                 p_fifo->l_next_frame += 1;
257                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
258                 p_fifo->b_next_frame = 0;
259             }
260         }
261         break;
262
263     case AOUT_ADEC_STEREO_FIFO:
264
265         l_units = p_aout->l_units;
266         while ( l_units > 0 )
267         {
268             if ( !p_fifo->b_next_frame )
269             {
270                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
271                 {
272                     break;
273                 }
274             }
275
276             if ( p_fifo->l_units > l_units )
277             {
278                 /* p_aout->b_stereo == 1 */
279                 l_buffer_limit = p_aout->l_units << 1;
280
281                 while ( l_buffer < l_buffer_limit )
282                 {
283                     p_aout->s32_buffer[l_buffer++] +=
284                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
285                     p_aout->s32_buffer[l_buffer++] +=
286                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
287
288                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
289                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
290                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
291                     {
292                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
293                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
294                     }
295                 }
296                 p_fifo->l_units -= l_units;
297                 break;
298             }
299             else
300             {
301                 /* p_aout->b_stereo == 1 */
302                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
303
304                 while ( l_buffer < l_buffer_limit )
305                 {
306                     p_aout->s32_buffer[l_buffer++] +=
307                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
308                     p_aout->s32_buffer[l_buffer++] +=
309                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
310
311                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
312                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
313                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
314                     {
315                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
316                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
317                     }
318                 }
319                 l_units -= p_fifo->l_units;
320
321                 vlc_mutex_lock( &p_fifo->data_lock );
322                 p_fifo->l_start_frame = p_fifo->l_next_frame;
323                 vlc_cond_signal( &p_fifo->data_wait );
324                 vlc_mutex_unlock( &p_fifo->data_lock );
325
326                 /* p_fifo->b_start_frame = 1; */
327                 p_fifo->l_next_frame += 1;
328                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
329                 p_fifo->b_next_frame = 0;
330             }
331         }
332         break;
333
334     default:
335
336         intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
337         break;
338     }
339 }
340