Mercurial > mplayer.hg
comparison libaf/af_resample.c @ 8867:558f0b1f45ee
New auto config for volume and resample and added support for float flag in configuration
author | anders |
---|---|
date | Fri, 10 Jan 2003 01:01:38 +0000 |
parents | 906f7a2dc085 |
children | 398e3fb7c103 |
comparison
equal
deleted
inserted
replaced
8866:f84a5237f914 | 8867:558f0b1f45ee |
---|---|
32 #endif | 32 #endif |
33 | 33 |
34 #include "af_resample.h" | 34 #include "af_resample.h" |
35 | 35 |
36 // Filtering types | 36 // Filtering types |
37 #define TYPE_LIN 0 // Linear interpolation | 37 #define RSMP_LIN (0<<0) // Linear interpolation |
38 #define TYPE_INT 1 // 16 bit integer | 38 #define RSMP_INT (1<<0) // 16 bit integer |
39 #define TYPE_FLOAT 2 // 32 bit floating point | 39 #define RSMP_FLOAT (2<<0) // 32 bit floating point |
40 #define RSMP_MASK (3<<0) | |
41 | |
42 // Defines for sloppy or exact resampling | |
43 #define FREQ_SLOPPY (0<<2) | |
44 #define FREQ_EXACT (1<<2) | |
45 #define FREQ_MASK (1<<2) | |
40 | 46 |
41 // Accuracy for linear interpolation | 47 // Accuracy for linear interpolation |
42 #define STEPACCURACY 32 | 48 #define STEPACCURACY 32 |
43 | 49 |
44 // local data | 50 // local data |
51 uint32_t i; // Number of new samples to put in x queue | 57 uint32_t i; // Number of new samples to put in x queue |
52 uint32_t dn; // Down sampling factor | 58 uint32_t dn; // Down sampling factor |
53 uint32_t up; // Up sampling factor | 59 uint32_t up; // Up sampling factor |
54 uint64_t step; // Step size for linear interpolation | 60 uint64_t step; // Step size for linear interpolation |
55 uint64_t pt; // Pointer remainder for linear interpolation | 61 uint64_t pt; // Pointer remainder for linear interpolation |
56 int sloppy; // Enable sloppy resampling to reduce memory usage | 62 int setup; // Setup parameters cmdline or through postcreate |
57 int type; // Filter type | |
58 } af_resample_t; | 63 } af_resample_t; |
59 | 64 |
60 // Euclids algorithm for calculating Greatest Common Divisor GCD(a,b) | 65 // Euclids algorithm for calculating Greatest Common Divisor GCD(a,b) |
61 static inline int gcd(register int a, register int b) | 66 static inline int gcd(register int a, register int b) |
62 { | 67 { |
118 s->pt=pt & ((1LL<<STEPACCURACY)-1); | 123 s->pt=pt & ((1LL<<STEPACCURACY)-1); |
119 } | 124 } |
120 return len; | 125 return len; |
121 } | 126 } |
122 | 127 |
128 /* Determine resampling type and format */ | |
129 static int set_types(struct af_instance_s* af, af_data_t* data) | |
130 { | |
131 af_resample_t* s = af->setup; | |
132 int rv = AF_OK; | |
133 float rd = 0; | |
134 | |
135 // Make sure this filter isn't redundant | |
136 if((af->data->rate == data->rate) || (af->data->rate == 0)) | |
137 return AF_DETACH; | |
138 | |
139 /* If sloppy and small resampling difference (2%) */ | |
140 rd = abs((float)af->data->rate - (float)data->rate)/(float)data->rate; | |
141 if((((s->setup & FREQ_MASK) == FREQ_SLOPPY) && (rd < 0.02) && | |
142 (data->format != (AF_FORMAT_NE | AF_FORMAT_F))) || | |
143 ((s->setup & RSMP_MASK) == RSMP_LIN)){ | |
144 s->setup = (s->setup & ~RSMP_MASK) | RSMP_LIN; | |
145 af->data->format = AF_FORMAT_NE | AF_FORMAT_SI; | |
146 af->data->bps = 2; | |
147 af_msg(AF_MSG_VERBOSE,"[resample] Using linear interpolation. \n"); | |
148 } | |
149 else{ | |
150 /* If the input format is float or if float is explicitly selected | |
151 use float, otherwise use int */ | |
152 if((data->format == (AF_FORMAT_NE | AF_FORMAT_F)) || | |
153 ((s->setup & RSMP_MASK) == RSMP_FLOAT)){ | |
154 s->setup = (s->setup & ~RSMP_MASK) | RSMP_FLOAT; | |
155 af->data->format = AF_FORMAT_NE | AF_FORMAT_F; | |
156 af->data->bps = 4; | |
157 } | |
158 else{ | |
159 s->setup = (s->setup & ~RSMP_MASK) | RSMP_INT; | |
160 af->data->format = AF_FORMAT_NE | AF_FORMAT_SI; | |
161 af->data->bps = 2; | |
162 } | |
163 af_msg(AF_MSG_VERBOSE,"[resample] Using %s processing and %s frequecy" | |
164 " conversion.\n", | |
165 ((s->setup & RSMP_MASK) == RSMP_FLOAT)?"floating point":"integer", | |
166 ((s->setup & FREQ_MASK) == FREQ_SLOPPY)?"inexact":"exact"); | |
167 } | |
168 | |
169 if(af->data->format != data->format || af->data->bps != data->bps) | |
170 rv = AF_FALSE; | |
171 data->format = af->data->format; | |
172 data->bps = af->data->bps; | |
173 af->data->nch = data->nch; | |
174 return rv; | |
175 } | |
176 | |
123 // Initialization and runtime control | 177 // Initialization and runtime control |
124 static int control(struct af_instance_s* af, int cmd, void* arg) | 178 static int control(struct af_instance_s* af, int cmd, void* arg) |
125 { | 179 { |
126 switch(cmd){ | 180 switch(cmd){ |
127 case AF_CONTROL_REINIT:{ | 181 case AF_CONTROL_REINIT:{ |
128 af_resample_t* s = (af_resample_t*)af->setup; | 182 af_resample_t* s = (af_resample_t*)af->setup; |
129 af_data_t* n = (af_data_t*)arg; // New configureation | 183 af_data_t* n = (af_data_t*)arg; // New configureation |
130 int i,d = 0; | 184 int i,d = 0; |
131 int rv = AF_OK; | 185 int rv = AF_OK; |
132 size_t tsz = (s->type==TYPE_INT) ? sizeof(int16_t) : sizeof(float); | 186 |
133 | 187 // Free space for circular bufers |
134 // Make sure this filter isn't redundant | 188 if(s->xq){ |
135 if((af->data->rate == n->rate) || (af->data->rate == 0)) | 189 for(i=1;i<af->data->nch;i++) |
190 if(s->xq[i]) | |
191 free(s->xq[i]); | |
192 free(s->xq); | |
193 } | |
194 | |
195 if(AF_DETACH == (rv = set_types(af,n))) | |
136 return AF_DETACH; | 196 return AF_DETACH; |
137 | 197 |
138 // If linear interpolation | 198 // If linear interpolation |
139 if(s->type == TYPE_LIN){ | 199 if((s->setup & RSMP_MASK) == RSMP_LIN){ |
140 s->pt=0LL; | 200 s->pt=0LL; |
141 s->step=((uint64_t)n->rate<<STEPACCURACY)/(uint64_t)af->data->rate+1LL; | 201 s->step=((uint64_t)n->rate<<STEPACCURACY)/(uint64_t)af->data->rate+1LL; |
142 af_msg(AF_MSG_VERBOSE,"[resample] Linear interpolation step: 0x%016X.\n", | 202 af_msg(AF_MSG_DEBUG0,"[resample] Linear interpolation step: 0x%016X.\n", |
143 s->step); | 203 s->step); |
144 af->mul.n = af->data->rate; | 204 af->mul.n = af->data->rate; |
145 af->mul.d = n->rate; | 205 af->mul.d = n->rate; |
146 } | 206 return AF_OK; |
147 | 207 } |
148 // Create space for circular bufers (if nesessary) | |
149 if((af->data->nch != n->nch) && (s->type != TYPE_LIN)){ | |
150 // First free the old ones | |
151 if(s->xq){ | |
152 for(i=1;i<af->data->nch;i++) | |
153 if(s->xq[i]) | |
154 free(s->xq[i]); | |
155 free(s->xq); | |
156 } | |
157 // ... then create new | |
158 s->xq = malloc(n->nch*sizeof(void*)); | |
159 for(i=0;i<n->nch;i++) | |
160 s->xq[i] = malloc(2*L*tsz); | |
161 s->xi = 0; | |
162 } | |
163 | |
164 // Set parameters | |
165 af->data->nch = n->nch; | |
166 if(s->type == TYPE_INT || s->type == TYPE_LIN){ | |
167 af->data->format = AF_FORMAT_NE | AF_FORMAT_SI; | |
168 af->data->bps = 2; | |
169 } | |
170 else{ | |
171 af->data->format = AF_FORMAT_NE | AF_FORMAT_F; | |
172 af->data->bps = 4; | |
173 } | |
174 if(af->data->format != n->format || af->data->bps != n->bps) | |
175 rv = AF_FALSE; | |
176 n->format = af->data->format; | |
177 n->bps = af->data->bps; | |
178 | |
179 // If linear interpolation is used the setup is done. | |
180 if(s->type == TYPE_LIN) | |
181 return rv; | |
182 | 208 |
183 // Calculate up and down sampling factors | 209 // Calculate up and down sampling factors |
184 d=gcd(af->data->rate,n->rate); | 210 d=gcd(af->data->rate,n->rate); |
185 | 211 |
186 // If sloppy resampling is enabled limit the upsampling factor | 212 // If sloppy resampling is enabled limit the upsampling factor |
187 if(s->sloppy && (af->data->rate/d > 5000)){ | 213 if(((s->setup & FREQ_MASK) == FREQ_SLOPPY) && (af->data->rate/d > 5000)){ |
188 int up=af->data->rate/2; | 214 int up=af->data->rate/2; |
189 int dn=n->rate/2; | 215 int dn=n->rate/2; |
190 int m=2; | 216 int m=2; |
191 while(af->data->rate/(d*m) > 5000){ | 217 while(af->data->rate/(d*m) > 5000){ |
192 d=gcd(up,dn); | 218 d=gcd(up,dn); |
193 up/=2; dn/=2; m*=2; | 219 up/=2; dn/=2; m*=2; |
194 } | 220 } |
195 d*=m; | 221 d*=m; |
196 } | 222 } |
223 | |
224 // Create space for circular bufers | |
225 s->xq = malloc(n->nch*sizeof(void*)); | |
226 for(i=0;i<n->nch;i++) | |
227 s->xq[i] = malloc(2*L*af->data->bps); | |
228 s->xi = 0; | |
197 | 229 |
198 // Check if the the design needs to be redone | 230 // Check if the the design needs to be redone |
199 if(s->up != af->data->rate/d || s->dn != n->rate/d){ | 231 if(s->up != af->data->rate/d || s->dn != n->rate/d){ |
200 float* w; | 232 float* w; |
201 float* wt; | 233 float* wt; |
208 fc = 1/(float)(max(s->up,s->dn)); | 240 fc = 1/(float)(max(s->up,s->dn)); |
209 // Allocate space for polyphase filter bank and protptype filter | 241 // Allocate space for polyphase filter bank and protptype filter |
210 w = malloc(sizeof(float) * s->up *L); | 242 w = malloc(sizeof(float) * s->up *L); |
211 if(NULL != s->w) | 243 if(NULL != s->w) |
212 free(s->w); | 244 free(s->w); |
213 s->w = malloc(L*s->up*tsz); | 245 s->w = malloc(L*s->up*af->data->bps); |
214 | 246 |
215 // Design prototype filter type using Kaiser window with beta = 10 | 247 // Design prototype filter type using Kaiser window with beta = 10 |
216 if(NULL == w || NULL == s->w || | 248 if(NULL == w || NULL == s->w || |
217 -1 == design_fir(s->up*L, w, &fc, LP|KAISER , 10.0)){ | 249 -1 == design_fir(s->up*L, w, &fc, LP|KAISER , 10.0)){ |
218 af_msg(AF_MSG_ERROR,"[resample] Unable to design prototype filter.\n"); | 250 af_msg(AF_MSG_ERROR,"[resample] Unable to design prototype filter.\n"); |
220 } | 252 } |
221 // Copy data from prototype to polyphase filter | 253 // Copy data from prototype to polyphase filter |
222 wt=w; | 254 wt=w; |
223 for(j=0;j<L;j++){//Columns | 255 for(j=0;j<L;j++){//Columns |
224 for(i=0;i<s->up;i++){//Rows | 256 for(i=0;i<s->up;i++){//Rows |
225 if(s->type == TYPE_INT){ | 257 if((s->setup & RSMP_MASK) == RSMP_INT){ |
226 float t=(float)s->up*32767.0*(*wt); | 258 float t=(float)s->up*32767.0*(*wt); |
227 ((int16_t*)s->w)[i*L+j] = (int16_t)((t>=0.0)?(t+0.5):(t-0.5)); | 259 ((int16_t*)s->w)[i*L+j] = (int16_t)((t>=0.0)?(t+0.5):(t-0.5)); |
228 } | 260 } |
229 else | 261 else |
230 ((float*)s->w)[i*L+j] = (float)s->up*(*wt); | 262 ((float*)s->w)[i*L+j] = (float)s->up*(*wt); |
243 return rv; | 275 return rv; |
244 } | 276 } |
245 case AF_CONTROL_COMMAND_LINE:{ | 277 case AF_CONTROL_COMMAND_LINE:{ |
246 af_resample_t* s = (af_resample_t*)af->setup; | 278 af_resample_t* s = (af_resample_t*)af->setup; |
247 int rate=0; | 279 int rate=0; |
248 int lin=0; | 280 int type=RSMP_INT; |
249 sscanf((char*)arg,"%i:%i:%i", &rate, &(s->sloppy), &lin); | 281 int sloppy=1; |
250 if(lin) | 282 sscanf((char*)arg,"%i:%i:%i", &rate, &type, &sloppy); |
251 s->type = TYPE_LIN; | 283 s->setup = (sloppy?FREQ_SLOPPY:FREQ_EXACT) | |
284 (clamp(type,RSMP_LIN,RSMP_FLOAT)); | |
252 return af->control(af,AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET, &rate); | 285 return af->control(af,AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET, &rate); |
253 } | 286 } |
254 case AF_CONTROL_POST_CREATE: | 287 case AF_CONTROL_POST_CREATE: |
255 ((af_resample_t*)af->setup)->type = | 288 if((((af_cfg_t*)arg)->force & AF_INIT_FORMAT_MASK) == AF_INIT_FLOAT) |
256 ((af_cfg_t*)arg)->force == AF_INIT_SLOW ? TYPE_INT : TYPE_FLOAT; | 289 ((af_resample_t*)af->setup)->setup |= RSMP_FLOAT; |
257 return AF_OK; | 290 return AF_OK; |
258 case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: | 291 case AF_CONTROL_RESAMPLE_RATE | AF_CONTROL_SET: |
259 // Reinit must be called after this function has been called | 292 // Reinit must be called after this function has been called |
260 | 293 |
261 // Sanity check | 294 // Sanity check |
291 | 324 |
292 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | 325 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) |
293 return NULL; | 326 return NULL; |
294 | 327 |
295 // Run resampling | 328 // Run resampling |
296 switch(s->type){ | 329 switch(s->setup & RSMP_MASK){ |
297 case(TYPE_INT): | 330 case(RSMP_INT): |
298 # define FORMAT_I 1 | 331 # define FORMAT_I 1 |
299 if(s->up>s->dn){ | 332 if(s->up>s->dn){ |
300 # define UP | 333 # define UP |
301 # include "af_resample.h" | 334 # include "af_resample.h" |
302 # undef UP | 335 # undef UP |
305 # define DN | 338 # define DN |
306 # include "af_resample.h" | 339 # include "af_resample.h" |
307 # undef DN | 340 # undef DN |
308 } | 341 } |
309 break; | 342 break; |
310 case(TYPE_FLOAT): | 343 case(RSMP_FLOAT): |
311 # undef FORMAT_I | 344 # undef FORMAT_I |
312 # define FORMAT_F 1 | 345 # define FORMAT_F 1 |
313 if(s->up>s->dn){ | 346 if(s->up>s->dn){ |
314 # define UP | 347 # define UP |
315 # include "af_resample.h" | 348 # include "af_resample.h" |
319 # define DN | 352 # define DN |
320 # include "af_resample.h" | 353 # include "af_resample.h" |
321 # undef DN | 354 # undef DN |
322 } | 355 } |
323 break; | 356 break; |
324 case(TYPE_LIN): | 357 case(RSMP_LIN): |
325 len = linint(c, l, s); | 358 len = linint(c, l, s); |
326 break; | 359 break; |
327 } | 360 } |
328 | 361 |
329 // Set output data | 362 // Set output data |
343 af->mul.d=1; | 376 af->mul.d=1; |
344 af->data=calloc(1,sizeof(af_data_t)); | 377 af->data=calloc(1,sizeof(af_data_t)); |
345 af->setup=calloc(1,sizeof(af_resample_t)); | 378 af->setup=calloc(1,sizeof(af_resample_t)); |
346 if(af->data == NULL || af->setup == NULL) | 379 if(af->data == NULL || af->setup == NULL) |
347 return AF_ERROR; | 380 return AF_ERROR; |
381 ((af_resample_t*)af->setup)->setup = RSMP_INT | FREQ_SLOPPY; | |
348 return AF_OK; | 382 return AF_OK; |
349 } | 383 } |
350 | 384 |
351 // Description of this plugin | 385 // Description of this plugin |
352 af_info_t af_info_resample = { | 386 af_info_t af_info_resample = { |