b04ac36437593a325b68a22ab4d38ea1f9956b9b
[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.7 2002/01/14 12:15:10 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 #define UPDATE_INCREMENT( increment, integer ) \
43     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
44     { \
45         (integer) += (increment).l_euclidean_integer + 1; \
46         (increment).l_remainder -= (increment).l_euclidean_denominator; \
47     } \
48     else \
49     { \
50         (integer) += (increment).l_euclidean_integer; \
51     }
52
53 /*****************************************************************************
54  * InitializeIncrement
55  *****************************************************************************/
56 static __inline__ void InitializeIncrement( aout_increment_t * p_increment,
57                                             long l_numerator,
58                                             long l_denominator )
59 {
60     p_increment->l_remainder = -l_denominator;
61
62     p_increment->l_euclidean_integer = 0;
63     while ( l_numerator >= l_denominator )
64     {
65         p_increment->l_euclidean_integer++;
66         l_numerator -= l_denominator;
67     }
68
69     p_increment->l_euclidean_remainder = l_numerator;
70
71     p_increment->l_euclidean_denominator = l_denominator;
72 }
73
74 /*****************************************************************************
75  * NextFrame
76  *****************************************************************************/
77 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo,
78                                  mtime_t aout_date )
79 {
80     long l_units, l_rate;
81     u64 l_delta;    
82
83     /* We take the lock */
84     vlc_mutex_lock( &p_fifo->data_lock );
85
86     /* Are we looking for a dated start frame ? */
87     if ( !p_fifo->b_start_frame )
88     {
89         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
90         {
91             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
92             {
93                 p_fifo->b_start_frame = 1;
94                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
95                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
96                 break;
97             }
98             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
99         }
100
101         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
102         {
103             vlc_mutex_unlock( &p_fifo->data_lock );
104             return( -1 );
105         }
106     }
107
108     /* We are looking for the next dated frame */
109     /* FIXME : is the output fifo full ?? */
110     while ( !p_fifo->b_next_frame )
111     {
112         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
113         {
114             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
115             {
116                 p_fifo->b_next_frame = 1;
117                 break;
118             }
119             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
120         }
121
122         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
123         {
124             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
125             if ( p_fifo->b_die )
126             {
127                 vlc_mutex_unlock( &p_fifo->data_lock );
128                 return( -1 );
129             }
130         }
131     }
132
133     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
134
135     l_delta = aout_date - p_fifo->date[p_fifo->l_start_frame];
136
137 /* Resample if delta is too long */
138     if( abs(l_delta) > MAX_DELTA )
139     {
140         l_rate = p_fifo->l_rate + (l_delta / 256);
141     }
142     else
143     {
144         l_rate = p_fifo->l_rate;
145     }
146
147     intf_DbgMsg( "aout debug: %lli (%li);", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
148
149     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
150
151     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
152         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
153         * p_aout->l_rate) / l_rate) + 1;
154
155     /* We release the lock before leaving */
156     vlc_mutex_unlock( &p_fifo->data_lock );
157     return( 0 );
158 }
159