b1b7e081495d6f3b36c6c37f4bc414dc7cc601e0
[vlc.git] / src / audio_output / aout_s16.c
1 /*****************************************************************************
2  * aout_s16.c: 16 bit signed audio output functions
3  *****************************************************************************
4  * Copyright (C) 1999-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 <stdio.h>                                           /* "intf_msg.h" */
27 #include <stdlib.h>                            /* calloc(), malloc(), free() */
28 #include <string.h>
29
30 #include <videolan/vlc.h>
31
32 #include "audio_output.h"
33 #include "aout_common.h"
34
35 /*****************************************************************************
36  * Local prototypes
37  *****************************************************************************/
38 static void S16Play( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
39
40 /*****************************************************************************
41  * Functions
42  *****************************************************************************/
43 void aout_S16MonoThread( aout_thread_t * p_aout )
44 {
45     int  i_fifo;
46     long l_buffer, l_buffer_limit, l_bytes;
47
48     /* As the s32_buffer was created with calloc(), we don't have to set this
49      * memory to zero and we can immediately jump into the thread's loop */
50     while ( ! p_aout->b_die )
51     {
52         vlc_mutex_lock( &p_aout->fifos_lock );
53
54         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
55         {
56             if( p_aout->fifo[i_fifo].b_die )
57             {
58                 aout_FreeFifo( &p_aout->fifo[i_fifo] );
59             }
60             else
61             {
62                 S16Play( p_aout, &p_aout->fifo[i_fifo] );
63             }
64         }
65
66         vlc_mutex_unlock( &p_aout->fifos_lock );
67
68         l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
69
70         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
71         {
72             ((s16 *)p_aout->buffer)[l_buffer] =
73                      (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS )
74                             * p_aout->i_volume / 256 ) ;
75             p_aout->s32_buffer[l_buffer] = 0;
76         }
77
78         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
79
80         /* sizeof(s16) << (p_aout->b_stereo) == 2 */
81         p_aout->date = mdate() + ((((mtime_t)((l_bytes + 2 * p_aout->i_latency) / 2)) * 1000000)
82                                    / ((mtime_t)p_aout->l_rate))
83                         + p_main->i_desync;
84         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
85                          l_buffer_limit * sizeof(s16) );
86
87         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
88         {
89             msleep( p_aout->l_msleep );
90         }
91     }
92
93     vlc_mutex_lock( &p_aout->fifos_lock );
94
95     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
96     {
97         aout_FreeFifo( &p_aout->fifo[i_fifo] );
98     }
99
100     vlc_mutex_unlock( &p_aout->fifos_lock );
101
102 }
103
104 void aout_S16StereoThread( aout_thread_t * p_aout )
105 {
106     int  i_fifo;
107     long l_buffer, l_buffer_limit, l_bytes;
108
109     /* As the s32_buffer was created with calloc(), we don't have to set this
110      * memory to zero and we can immediately jump into the thread's loop */
111     while ( ! p_aout->b_die )
112     {
113         vlc_mutex_lock( &p_aout->fifos_lock );
114
115         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
116         {
117             if( p_aout->fifo[i_fifo].b_die )
118             {
119                 aout_FreeFifo( &p_aout->fifo[i_fifo] );
120             }
121             else
122             {
123                 S16Play( p_aout, &p_aout->fifo[i_fifo] );
124             }
125         }
126
127         vlc_mutex_unlock( &p_aout->fifos_lock );
128
129         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
130
131         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
132         {
133             ((s16 *)p_aout->buffer)[l_buffer] =
134                      (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS )
135                             * p_aout->i_volume / 256 ) ;
136             p_aout->s32_buffer[l_buffer] = 0;
137         }
138
139         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
140
141         /* sizeof(s16) << (p_aout->b_stereo) == 4 */
142         p_aout->date = mdate() + ((((mtime_t)((l_bytes + 4 * p_aout->i_latency) / 4)) * 1000000)
143                                    / ((mtime_t)p_aout->l_rate))
144                         + p_main->i_desync;
145         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
146                          l_buffer_limit * sizeof(s16) );
147
148         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
149         {
150             msleep( p_aout->l_msleep );
151         }
152     }
153
154     vlc_mutex_lock( &p_aout->fifos_lock );
155
156     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
157     {
158         aout_FreeFifo( &p_aout->fifo[i_fifo] );
159     }
160
161     vlc_mutex_unlock( &p_aout->fifos_lock );
162 }
163
164 /* Following functions are local */
165
166 static void S16Play( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
167 {
168     long l_buffer = 0;
169     long l_buffer_limit, l_units;
170
171     switch ( p_fifo->i_type )
172     {
173     case AOUT_EMPTY_FIFO:
174
175         break;
176
177     case AOUT_INTF_MONO_FIFO:
178
179         if ( p_fifo->l_units > p_aout->l_units )
180         {
181             /* p_aout->b_stereo == 1 */
182             while ( l_buffer < (p_aout->l_units << 1) )
183             {
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 )
189             }
190             p_fifo->l_units -= p_aout->l_units;
191         }
192         else /* p_fifo->l_units <= p_aout->l_units */
193         {
194             /* p_aout->b_stereo == 1 */
195             while ( l_buffer < (p_fifo->l_units << 1) )
196             {
197                 p_aout->s32_buffer[l_buffer++] +=
198                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
199                 p_aout->s32_buffer[l_buffer++] +=
200                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
201                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
202             }
203             free( p_fifo->buffer ); /* !! */
204             p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
205         }
206         break;
207
208     case AOUT_INTF_STEREO_FIFO:
209
210         if ( p_fifo->l_units > p_aout->l_units )
211         {
212             /* p_aout->b_stereo == 1 */
213             while ( l_buffer < (p_aout->l_units << 1) )
214             {
215                 p_aout->s32_buffer[l_buffer++] +=
216                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
217                 p_aout->s32_buffer[l_buffer++] +=
218                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
219                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
220             }
221             p_fifo->l_units -= p_aout->l_units;
222         }
223         else /* p_fifo->l_units <= p_aout->l_units */
224         {
225             /* p_aout->b_stereo == 1 */
226             while ( l_buffer < (p_fifo->l_units << 1) )
227             {
228                 p_aout->s32_buffer[l_buffer++] +=
229                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
230                 p_aout->s32_buffer[l_buffer++] +=
231                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
232                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
233             }
234             free( p_fifo->buffer );
235             p_fifo->i_type = AOUT_EMPTY_FIFO;
236         }
237         break;
238
239     case AOUT_ADEC_MONO_FIFO:
240
241         l_units = p_aout->l_units;
242         while ( l_units > 0 )
243         {
244             if ( !p_fifo->b_next_frame )
245             {
246                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
247                 {
248                     break;
249                 }
250             }
251
252             if ( p_fifo->l_units > l_units )
253             {
254                 /* p_aout->b_stereo == 1 */
255                 l_buffer_limit = p_aout->l_units << 1;
256
257                 while ( l_buffer < l_buffer_limit )
258                 {
259                     p_aout->s32_buffer[l_buffer++] +=
260                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
261                     p_aout->s32_buffer[l_buffer++] +=
262                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
263
264                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
265                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
266                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
267                     {
268                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
269                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
270                     }
271                 }
272                 p_fifo->l_units -= l_units;
273                 break;
274             }
275             else /* p_fifo->l_units <= l_units */
276             {
277                 /* p_aout->b_stereo == 1 */
278                 l_buffer_limit = p_fifo->l_units << 1;
279
280                 while ( l_buffer < l_buffer_limit )
281                 {
282                     p_aout->s32_buffer[l_buffer++] +=
283                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
284                     p_aout->s32_buffer[l_buffer++] +=
285                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
286
287                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
288                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
289                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
290                     {
291                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
292                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
293                     }
294                 }
295                 l_units -= p_fifo->l_units;
296
297                 vlc_mutex_lock( &p_fifo->data_lock );
298                 p_fifo->l_start_frame = p_fifo->l_next_frame;
299                 vlc_cond_signal( &p_fifo->data_wait );
300                 vlc_mutex_unlock( &p_fifo->data_lock );
301
302                 /* p_fifo->b_start_frame = 1; */
303                 p_fifo->l_next_frame += 1;
304                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
305                 p_fifo->b_next_frame = 0;
306             }
307         }
308         break;
309
310     case AOUT_ADEC_STEREO_FIFO:
311
312         l_units = p_aout->l_units;
313         while ( l_units > 0 )
314         {
315             if ( !p_fifo->b_next_frame )
316             {
317                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
318                 {
319                     break;
320                 }
321             }
322
323             if ( p_fifo->l_units > l_units )
324             {
325                 /* p_aout->b_stereo == 1 */
326                 l_buffer_limit = p_aout->l_units << 1;
327
328                 while ( l_buffer < l_buffer_limit )
329                 {
330                     p_aout->s32_buffer[l_buffer++] +=
331                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
332                     p_aout->s32_buffer[l_buffer++] +=
333                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
334
335                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
336                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
337                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
338                     {
339                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
340                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
341                     }
342                 }
343                 p_fifo->l_units -= l_units;
344                 break;
345             }
346             else /* p_fifo->l_units <= l_units */
347             {
348                 /* p_aout->b_stereo == 1 */
349                 l_buffer_limit = p_fifo->l_units << 1;
350
351                 while ( l_buffer < l_buffer_limit )
352                 {
353                     p_aout->s32_buffer[l_buffer++] +=
354                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
355                     p_aout->s32_buffer[l_buffer++] +=
356                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
357
358                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
359                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
360                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
361                     {
362                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
363                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
364                     }
365                 }
366                 l_units -= p_fifo->l_units;
367
368                 vlc_mutex_lock( &p_fifo->data_lock );
369                 p_fifo->l_start_frame = p_fifo->l_next_frame;
370                 vlc_cond_signal( &p_fifo->data_wait );
371                 vlc_mutex_unlock( &p_fifo->data_lock );
372
373                 /* p_fifo->b_start_frame = 1; */
374                 p_fifo->l_next_frame += 1;
375                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
376                 p_fifo->b_next_frame = 0;
377             }
378         }
379         break;
380
381     default:
382
383         intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
384         break;
385     }
386 }
387