- le coup de gr�ce: all the code in audio output is now factorized (except
[vlc.git] / src / audio_output / aout_common.h
1 /*****************************************************************************
2  * aout_common.h: audio output inner functions
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: aout_common.h,v 1.8 2002/01/14 19:54:36 asmax Exp $
6  *
7  * Authors: Michel Kaempf <maxx@via.ecp.fr>
8  *          Cyril Deguet <asmax@via.ecp.fr>   
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25
26 /* Biggest difference allowed between scheduled playing date and actual date 
27    (in microseconds) */
28 #define MAX_DELTA 10000
29
30
31 /* Creating as many aout_Thread functions as configurations was one solution,
32  * examining the different cases in the Thread loop of an unique function was
33  * another. I chose the first solution. */
34 void aout_U8Thread            ( aout_thread_t * p_aout );
35 void aout_S8Thread            ( aout_thread_t * p_aout );
36 void aout_U16Thread           ( aout_thread_t * p_aout );
37 void aout_S16Thread           ( aout_thread_t * p_aout );
38 void aout_SpdifThread         ( aout_thread_t * p_aout );
39 void aout_FillBuffer          ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
40
41
42 /* Generic main thread function "aout_XXXThread"
43  */
44 #define DECLARE_AOUT_THREAD( format, type, buffer_copy )                      \
45 void aout_##format##Thread( aout_thread_t * p_aout )                          \
46 {                                                                             \
47                                                                               \
48     int i_fifo;                                                               \
49     long l_buffer, l_buffer_limit, l_bytes;                                   \
50                                                                               \
51     /* As the s32_buffer was created with calloc(), we don't have to set this \
52      * memory to zero and we can immediately jump into the thread's loop */   \
53     while ( ! p_aout->b_die )                                                 \
54     {                                                                         \
55         vlc_mutex_lock( &p_aout->fifos_lock );                                \
56                                                                               \
57         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )                 \
58         {                                                                     \
59             if( p_aout->fifo[i_fifo].b_die )                                  \
60             {                                                                 \
61                 aout_FreeFifo( &p_aout->fifo[i_fifo] );                       \
62             }                                                                 \
63             else                                                              \
64             {                                                                 \
65                 aout_FillBuffer( p_aout, &p_aout->fifo[i_fifo] );             \
66             }                                                                 \
67         }                                                                     \
68                                                                               \
69         vlc_mutex_unlock( &p_aout->fifos_lock );                              \
70                                                                               \
71         l_buffer_limit = p_aout->l_units << p_aout->b_stereo;                 \
72                                                                               \
73         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )           \
74         {                                                                     \
75             ((type *)p_aout->buffer)[l_buffer] = (type)( buffer_copy );       \
76             p_aout->s32_buffer[l_buffer] = 0;                                 \
77         }                                                                     \
78                                                                               \
79         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );            \
80                                                                               \
81         p_aout->date = mdate() + ((((mtime_t)((l_bytes + 4 *                  \
82                 p_aout->i_latency) /                                          \
83                 (sizeof(type) << p_aout->b_stereo))) * 1000000) /             \
84                 ((mtime_t)p_aout->l_rate)) + p_main->i_desync;                \
85                                                                               \
86         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit *   \
87                 sizeof(type) );                                               \
88                                                                               \
89         if ( l_bytes > (l_buffer_limit * sizeof(type)) )                      \
90         {                                                                     \
91             msleep( p_aout->l_msleep );                                       \
92         }                                                                     \
93     }                                                                         \
94                                                                               \
95     vlc_mutex_lock( &p_aout->fifos_lock );                                    \
96                                                                               \
97     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )                     \
98     {                                                                         \
99         aout_FreeFifo( &p_aout->fifo[i_fifo] );                               \
100     }                                                                         \
101                                                                               \
102     vlc_mutex_unlock( &p_aout->fifos_lock );                                  \
103                                                                               \
104 }                                                                             \
105
106
107 /*****************************************************************************
108  * InitializeIncrement
109  *****************************************************************************/
110 static __inline__ void InitializeIncrement( aout_increment_t * p_increment,
111                                             long l_numerator,
112                                             long l_denominator )
113 {
114     p_increment->l_remainder = -l_denominator;
115
116     p_increment->l_euclidean_integer = 0;
117     while ( l_numerator >= l_denominator )
118     {
119         p_increment->l_euclidean_integer++;
120         l_numerator -= l_denominator;
121     }
122
123     p_increment->l_euclidean_remainder = l_numerator;
124
125     p_increment->l_euclidean_denominator = l_denominator;
126 }
127
128
129 /*****************************************************************************
130  * UpdateIncrement
131  *****************************************************************************/
132 static __inline__ void UpdateIncrement( aout_increment_t * p_increment, 
133         long * p_integer )
134 {
135     if( (p_increment->l_remainder += p_increment->l_euclidean_remainder) >= 0 )
136     {
137         *p_integer += p_increment->l_euclidean_integer + 1;
138         p_increment->l_remainder -= p_increment->l_euclidean_denominator;
139     }
140     else
141     {
142         *p_integer += p_increment->l_euclidean_integer;
143     }
144 }
145