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