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