Mercurial > mplayer.hg
comparison libao2/pl_resample.c @ 4171:585f0c77d8f5
Sync problem when using fractional resampling fixed + speed increased.
author | anders |
---|---|
date | Tue, 15 Jan 2002 13:21:45 +0000 |
parents | d6f8feeac656 |
children | 0a95c5074c50 |
comparison
equal
deleted
inserted
replaced
4170:32ad3c2833cf | 4171:585f0c77d8f5 |
---|---|
22 | 22 |
23 #include "audio_out.h" | 23 #include "audio_out.h" |
24 #include "audio_plugin.h" | 24 #include "audio_plugin.h" |
25 #include "audio_plugin_internal.h" | 25 #include "audio_plugin_internal.h" |
26 #include "afmt.h" | 26 #include "afmt.h" |
27 //#include "../config.h" | 27 // #include "../config.h" |
28 | 28 |
29 static ao_info_t info = | 29 static ao_info_t info = |
30 { | 30 { |
31 "Sample frequency conversion audio plugin", | 31 "Sample frequency conversion audio plugin", |
32 "resample", | 32 "resample", |
44 length of the filter. This definition affects the computational | 44 length of the filter. This definition affects the computational |
45 complexity (see play()), the performance (see filter.h) and the | 45 complexity (see play()), the performance (see filter.h) and the |
46 memory usage. For now the filterlenght is choosen to 4 and without | 46 memory usage. For now the filterlenght is choosen to 4 and without |
47 assembly optimization if no SSE is present. | 47 assembly optimization if no SSE is present. |
48 */ | 48 */ |
49 #ifdef HAVE_SSE | 49 |
50 // #ifdef HAVE_SSE | |
50 #define L8 1 // Filter bank type | 51 #define L8 1 // Filter bank type |
51 #define W W8 // Filter bank parameters | 52 #define W W8 // Filter bank parameters |
52 #define L 8 // Filter length | 53 #define L 8 // Filter length |
53 #else | 54 // #else |
54 #define L4 1 | 55 // #define L4 1 |
55 #define W W4 | 56 // #define W W4 |
56 #define L 4 | 57 // #define L 4 |
57 #endif | 58 // #endif |
58 | 59 |
59 #define CH 6 // Max number of channels | 60 #define CH 6 // Max number of channels |
60 #define UP 128 /* Up sampling factor. Increasing this value will | 61 #define UP 128 /* Up sampling factor. Increasing this value will |
61 improve frequency accuracy. Think about the L1 | 62 improve frequency accuracy. Think about the L1 |
62 cashing of filter parameters - how big can it be? */ | 63 cashing of filter parameters - how big can it be? */ |
71 int16_t* w; // Current filter weights | 72 int16_t* w; // Current filter weights |
72 uint16_t dn; // Down sampling factor | 73 uint16_t dn; // Down sampling factor |
73 uint16_t up; // Up sampling factor | 74 uint16_t up; // Up sampling factor |
74 int channels; // Number of channels | 75 int channels; // Number of channels |
75 int len; // Lenght of buffer | 76 int len; // Lenght of buffer |
76 int bypass; // Bypass this plugin | |
77 int16_t ws[UP*L]; // List of all available filters | 77 int16_t ws[UP*L]; // List of all available filters |
78 int16_t xs[CH][L*2]; // Circular buffers | 78 int16_t xs[CH][L*2]; // Circular buffers |
79 } pl_resample_t; | 79 } pl_resample_t; |
80 | 80 |
81 static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,0,W}; | 81 static pl_resample_t pl_resample = {NULL,NULL,1,1,1,0,W}; |
82 | 82 |
83 // to set/get/query special features/parameters | 83 // to set/get/query special features/parameters |
84 static int control(int cmd,int arg){ | 84 static int control(int cmd,int arg){ |
85 switch(cmd){ | 85 switch(cmd){ |
86 case AOCONTROL_PLUGIN_SET_LEN: | 86 case AOCONTROL_PLUGIN_SET_LEN: |
115 if((float)max(fin,fout)/(float)min(fin,fout) > 10){ | 115 if((float)max(fin,fout)/(float)min(fin,fout) > 10){ |
116 fprintf(stderr,"[pl_resample] The difference between fin and fout is too large.\n"); | 116 fprintf(stderr,"[pl_resample] The difference between fin and fout is too large.\n"); |
117 return 0; | 117 return 0; |
118 } | 118 } |
119 pl_resample.dn=(int)(0.5+((float)(fin*pl_resample.up))/((float)fout)); | 119 pl_resample.dn=(int)(0.5+((float)(fin*pl_resample.up))/((float)fout)); |
120 if(pl_resample.dn == pl_resample.up){ | 120 |
121 fprintf(stderr,"[pl_resample] Fin is too close to fout no conversion is needed.\n"); | |
122 pl_resample.bypass=1; | |
123 return 1; | |
124 } | |
125 pl_resample.channels=ao_plugin_data.channels; | 121 pl_resample.channels=ao_plugin_data.channels; |
126 if(ao_plugin_data.channels>CH){ | 122 if(ao_plugin_data.channels>CH){ |
127 fprintf(stderr,"[pl_resample] Too many channels, max is 6.\n"); | 123 fprintf(stderr,"[pl_resample] Too many channels, max is 6.\n"); |
128 return 0; | 124 return 0; |
129 } | 125 } |
153 | 149 |
154 // processes 'ao_plugin_data.len' bytes of 'data' | 150 // processes 'ao_plugin_data.len' bytes of 'data' |
155 // called for every block of data | 151 // called for every block of data |
156 // FIXME: this routine needs to be optimized (it is probably possible to do a lot here) | 152 // FIXME: this routine needs to be optimized (it is probably possible to do a lot here) |
157 static int play(){ | 153 static int play(){ |
154 if(pl_resample.up==pl_resample.dn){ | |
155 register int16_t* in = ((int16_t*)ao_plugin_data.data); | |
156 register int16_t* end = in+ao_plugin_data.len/2; | |
157 while(in < end) *in=(*in++)>>1; | |
158 return 1; | |
159 } | |
160 if(pl_resample.up>pl_resample.dn) | |
161 return upsample(); | |
162 if(pl_resample.up<pl_resample.dn) | |
163 return downsample(); | |
164 } | |
165 | |
166 int upsample(){ | |
167 static uint16_t pwi = 0; // Index for w | |
168 static uint16_t pxi = 0; // Index for circular queue | |
169 | |
170 uint16_t ci = pl_resample.channels; // Index for channels | |
171 uint16_t nch = pl_resample.channels; // Number of channels | |
172 uint16_t len = 0; // Number of input samples | |
173 uint16_t inc = pl_resample.up/pl_resample.dn; | |
174 uint16_t level = pl_resample.up%pl_resample.dn; | |
175 uint16_t up = pl_resample.up; | |
176 uint16_t dn = pl_resample.dn; | |
177 | |
178 register int16_t* w = pl_resample.w; | |
179 register uint16_t wi,xi; // Temporary indexes | |
180 | |
181 // Index current channel | |
182 while(ci--){ | |
183 // Temporary pointers | |
184 register int16_t* x = pl_resample.xs[ci]; | |
185 register int16_t* in = ((int16_t*)ao_plugin_data.data)+ci; | |
186 register int16_t* out = pl_resample.data+ci; | |
187 int16_t* end = in+ao_plugin_data.len/2; // Block loop end | |
188 | |
189 wi = pwi; xi = pxi; | |
190 | |
191 LOAD_QUE(x); | |
192 while(in < end){ | |
193 register uint16_t i = inc; | |
194 if(wi<level) i++; | |
195 | |
196 UPDATE_QUE(in); | |
197 in+=nch; | |
198 | |
199 while(i--){ | |
200 // Run the FIR filter | |
201 FIR((&x[xi]),(&w[wi*L]),out); | |
202 len++; out+=nch; | |
203 // Update wi to point at the correct polyphase component | |
204 wi=(wi+dn)%up; | |
205 } | |
206 } | |
207 SAVE_QUE(x); | |
208 } | |
209 | |
210 // Save values that needs to be kept for next time | |
211 pwi = wi; | |
212 pxi = xi; | |
213 | |
214 // Set new data | |
215 ao_plugin_data.len=len*2; | |
216 ao_plugin_data.data=pl_resample.data; | |
217 return 1; | |
218 } | |
219 | |
220 int downsample(){ | |
158 static uint16_t pwi = 0; // Index for w | 221 static uint16_t pwi = 0; // Index for w |
159 static uint16_t pxi = 0; // Index for circular queue | 222 static uint16_t pxi = 0; // Index for circular queue |
160 static uint16_t pi = 1; // Number of new samples to put in x queue | 223 static uint16_t pi = 1; // Number of new samples to put in x queue |
161 | 224 |
162 uint16_t ci = pl_resample.channels; // Index for channels | 225 uint16_t ci = pl_resample.channels; // Index for channels |
163 uint16_t len = 0; // Number of output samples | 226 uint16_t len = 0; // Number of input samples |
164 uint16_t nch = pl_resample.channels; // Number of channels | 227 uint16_t nch = pl_resample.channels; // Number of channels |
165 uint16_t inc = pl_resample.dn/pl_resample.up; | 228 uint16_t inc = pl_resample.dn/pl_resample.up; |
166 uint16_t level = pl_resample.dn%pl_resample.up; | 229 uint16_t level = pl_resample.dn%pl_resample.up; |
167 uint16_t up = pl_resample.up; | 230 uint16_t up = pl_resample.up; |
168 uint16_t dn = pl_resample.dn; | 231 uint16_t dn = pl_resample.dn; |
169 | 232 |
170 register uint16_t i,wi,xi; // Temporary indexes | 233 register uint16_t i,wi,xi; // Temporary indexes |
171 | 234 |
172 if(pl_resample.bypass) | |
173 return 1; | |
174 | 235 |
175 // Index current channel | 236 // Index current channel |
176 while(ci--){ | 237 while(ci--){ |
177 // Temporary pointers | 238 // Temporary pointers |
178 register int16_t* x = pl_resample.xs[ci]; | 239 register int16_t* x = pl_resample.xs[ci]; |
181 // Block loop end | 242 // Block loop end |
182 register int16_t* end = in+ao_plugin_data.len/2; | 243 register int16_t* end = in+ao_plugin_data.len/2; |
183 i = pi; wi = pwi; xi = pxi; | 244 i = pi; wi = pwi; xi = pxi; |
184 | 245 |
185 LOAD_QUE(x); | 246 LOAD_QUE(x); |
186 if(0!=i) goto L1; | |
187 while(in < end){ | 247 while(in < end){ |
188 // Update wi to point at the correct polyphase component | 248 |
189 wi=(wi+dn)%up; | 249 UPDATE_QUE(in); |
190 | 250 in+=nch; |
191 /* Update circular buffer x. This loop will be updated 0 or 1 time | 251 |
192 for upsamling and inc or inc + 1 times for downsampling */ | 252 if(!--i){ |
193 if(wi<level) goto L3; | 253 // Run the FIR filter |
194 if(0==i) goto L2; | 254 FIR((&x[xi]),(&pl_resample.w[wi*L]),out); |
195 L1: i--; | 255 len++; out+=nch; |
196 L3: UPDATE_QUE(in); | 256 |
197 in+=nch; | 257 // Update wi to point at the correct polyphase component |
198 if(in >= end) goto L2; | 258 wi=(wi+dn)%up; |
199 if(i) goto L1; | 259 |
200 L2: if(i) goto L5; | 260 // Insert i number of new samples in queue |
201 i=inc; | 261 i = inc; |
202 | 262 if(wi<level) i++; |
203 /* Get the correct polyphase component and the correct startpoint | 263 } |
204 in the circular bufer and run the FIR filter */ | |
205 FIR((&x[xi]),(&pl_resample.w[wi*L]),out); | |
206 len++; | |
207 out+=nch; | |
208 } | 264 } |
209 L5: | |
210 SAVE_QUE(x); | 265 SAVE_QUE(x); |
211 } | 266 } |
212 | |
213 // Save values that needs to be kept for next time | 267 // Save values that needs to be kept for next time |
214 pwi = wi; | 268 pwi = wi; |
215 pxi = xi; | 269 pxi = xi; |
216 pi = i; | 270 pi = i; |
217 // Set new data | 271 // Set new data |
218 ao_plugin_data.len=len*2; | 272 ao_plugin_data.len=len*2; |
219 ao_plugin_data.data=pl_resample.data; | 273 ao_plugin_data.data=pl_resample.data; |
220 return 1; | 274 return 1; |
221 } | 275 } |
222 | |
223 | |
224 | |
225 | |
226 |