]> git.sesse.net Git - vlc/blob - src/audio_output/aout_s16.c
* Header cleaning: filled all empty authors fields, added CVS $Id stuff.
[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  * $Id: aout_s16.c,v 1.2 2001/03/21 13:42:34 sam Exp $
6  *
7  * Authors: Michel Kaempf <maxx@via.ecp.fr>
8  *
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.
13  * 
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "defs.h"
28
29 #include <stdio.h>                                           /* "intf_msg.h" */
30 #include <stdlib.h>                            /* calloc(), malloc(), free() */
31
32 #include "config.h"
33 #include "common.h"
34 #include "threads.h"
35 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
36
37 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
38
39 #include "audio_output.h"
40 #include "aout_common.h"
41
42 /*****************************************************************************
43  * Local prototypes
44  *****************************************************************************/
45 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
46
47 /*****************************************************************************
48  * Functions
49  *****************************************************************************/
50 void aout_S16MonoThread( aout_thread_t * p_aout )
51 {
52     intf_ErrMsg( "aout error: 16 bit signed mono thread unsupported" );
53 }
54
55 void aout_S16StereoThread( aout_thread_t * p_aout )
56 {
57     int  i_fifo;
58     long l_buffer, l_buffer_limit, l_bytes;
59
60     /* As the s32_buffer was created with calloc(), we don't have to set this
61      * memory to zero and we can immediately jump into the thread's loop */
62     while ( ! p_aout->b_die )
63     {
64         vlc_mutex_lock( &p_aout->fifos_lock );
65
66         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
67         {
68             if( p_aout->fifo[i_fifo].b_die )
69             {
70                 aout_FreeFifo( &p_aout->fifo[i_fifo] );
71             }
72             else
73             {
74                 S16StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
75             }
76         }
77
78         vlc_mutex_unlock( &p_aout->fifos_lock );
79
80         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
81
82         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
83         {
84             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
85             p_aout->s32_buffer[l_buffer] = 0;
86         }
87
88         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
89         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
90         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
91         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
92         {
93             msleep( p_aout->l_msleep );
94         }
95     }
96
97     vlc_mutex_lock( &p_aout->fifos_lock );
98
99     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
100     {
101         aout_FreeFifo( &p_aout->fifo[i_fifo] );
102     }
103
104     vlc_mutex_unlock( &p_aout->fifos_lock );
105 }
106
107 /* Following functions are local */
108
109 static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
110 {
111     long l_buffer = 0;
112     long l_buffer_limit, l_units;
113
114     switch ( p_fifo->i_type )
115     {
116     case AOUT_EMPTY_FIFO:
117
118         break;
119
120     case AOUT_INTF_MONO_FIFO:
121
122         if ( p_fifo->l_units > p_aout->l_units )
123         {
124             /* p_aout->b_stereo == 1 */
125             while ( l_buffer < (p_aout->l_units << 1) )
126             {
127                 p_aout->s32_buffer[l_buffer++] +=
128                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
129                 p_aout->s32_buffer[l_buffer++] +=
130                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
131                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
132             }
133             p_fifo->l_units -= p_aout->l_units;
134         }
135         else
136         {
137             /* p_aout->b_stereo == 1 */
138             while ( l_buffer < (p_fifo->l_units << 1) )
139             {
140                 p_aout->s32_buffer[l_buffer++] +=
141                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
142                 p_aout->s32_buffer[l_buffer++] +=
143                     (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
144                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
145             }
146             free( p_fifo->buffer ); /* !! */
147             p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
148         }
149         break;
150
151     case AOUT_INTF_STEREO_FIFO:
152
153         if ( p_fifo->l_units > p_aout->l_units )
154         {
155             /* p_aout->b_stereo == 1 */
156             while ( l_buffer < (p_aout->l_units << 1) )
157             {
158                 p_aout->s32_buffer[l_buffer++] +=
159                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
160                 p_aout->s32_buffer[l_buffer++] +=
161                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
162                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
163             }
164             p_fifo->l_units -= p_aout->l_units;
165         }
166         else
167         {
168             /* p_aout->b_stereo == 1 */
169             while ( l_buffer < (p_fifo->l_units << 1) )
170             {
171                 p_aout->s32_buffer[l_buffer++] +=
172                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
173                 p_aout->s32_buffer[l_buffer++] +=
174                     (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
175                 UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
176             }
177             free( p_fifo->buffer );
178             p_fifo->i_type = AOUT_EMPTY_FIFO;
179         }
180         break;
181
182     case AOUT_ADEC_MONO_FIFO:
183
184         l_units = p_aout->l_units;
185         while ( l_units > 0 )
186         {
187             if ( !p_fifo->b_next_frame )
188             {
189                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
190                 {
191                     break;
192                 }
193             }
194
195             if ( p_fifo->l_units > l_units )
196             {
197                 /* p_aout->b_stereo == 1 */
198                 l_buffer_limit = p_aout->l_units << 1;
199
200                 while ( l_buffer < l_buffer_limit )
201                 {
202                     p_aout->s32_buffer[l_buffer++] +=
203                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
204                     p_aout->s32_buffer[l_buffer++] +=
205                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
206
207                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
208                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
209                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
210                     {
211                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
212                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
213                     }
214                 }
215                 p_fifo->l_units -= l_units;
216                 break;
217             }
218             else
219             {
220                 /* p_aout->b_stereo == 1 */
221                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
222
223                 while ( l_buffer < l_buffer_limit )
224                 {
225                     p_aout->s32_buffer[l_buffer++] +=
226                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
227                     p_aout->s32_buffer[l_buffer++] +=
228                         (s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
229
230                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
231                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
232                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
233                     {
234                         p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
235                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
236                     }
237                 }
238                 l_units -= p_fifo->l_units;
239
240                 vlc_mutex_lock( &p_fifo->data_lock );
241                 p_fifo->l_start_frame = p_fifo->l_next_frame;
242                 vlc_cond_signal( &p_fifo->data_wait );
243                 vlc_mutex_unlock( &p_fifo->data_lock );
244
245                 /* p_fifo->b_start_frame = 1; */
246                 p_fifo->l_next_frame += 1;
247                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
248                 p_fifo->b_next_frame = 0;
249             }
250         }
251         break;
252
253     case AOUT_ADEC_STEREO_FIFO:
254
255         l_units = p_aout->l_units;
256         while ( l_units > 0 )
257         {
258             if ( !p_fifo->b_next_frame )
259             {
260                 if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
261                 {
262                     break;
263                 }
264             }
265
266             if ( p_fifo->l_units > l_units )
267             {
268                 /* p_aout->b_stereo == 1 */
269                 l_buffer_limit = p_aout->l_units << 1;
270
271                 while ( l_buffer < l_buffer_limit )
272                 {
273                     p_aout->s32_buffer[l_buffer++] +=
274                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
275                     p_aout->s32_buffer[l_buffer++] +=
276                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
277
278                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
279                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
280                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
281                     {
282                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
283                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
284                     }
285                 }
286                 p_fifo->l_units -= l_units;
287                 break;
288             }
289             else
290             {
291                 /* p_aout->b_stereo == 1 */
292                 l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
293
294                 while ( l_buffer < l_buffer_limit )
295                 {
296                     p_aout->s32_buffer[l_buffer++] +=
297                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
298                     p_aout->s32_buffer[l_buffer++] +=
299                         (s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
300
301                     UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
302                     if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
303                          ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
304                     {
305                         p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
306                             ((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
307                     }
308                 }
309                 l_units -= p_fifo->l_units;
310
311                 vlc_mutex_lock( &p_fifo->data_lock );
312                 p_fifo->l_start_frame = p_fifo->l_next_frame;
313                 vlc_cond_signal( &p_fifo->data_wait );
314                 vlc_mutex_unlock( &p_fifo->data_lock );
315
316                 /* p_fifo->b_start_frame = 1; */
317                 p_fifo->l_next_frame += 1;
318                 p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
319                 p_fifo->b_next_frame = 0;
320             }
321         }
322         break;
323
324     default:
325
326         intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
327         break;
328     }
329 }
330