9 // Resampling from Lame
11 Resample::Resample(File *file, int channels)
13 //printf("Resample::Resample 1 %d\n", channels);
15 this->channels = channels;
17 old = new double*[channels];
18 for(int i = 0; i < channels; i++)
20 old[i] = new double[BLACKSIZE];
22 itime = new double[channels];
23 output_temp_start = new long[channels];
24 bzero(output_temp_start, sizeof(long) * channels);
25 resample_init = new int[channels];
26 bzero(resample_init, sizeof(int) * channels);
29 output_size = new long[channels];
30 bzero(output_size, sizeof(long) * channels);
31 output_allocation = 0;
32 input_size = RESAMPLE_CHUNKSIZE;
33 input_chunk_end = new long[channels];
34 bzero(input_chunk_end, sizeof(long) * channels);
35 input = new double[input_size];
36 last_out_end = new long[channels];
37 bzero(last_out_end, sizeof(long) * channels);
38 //printf("Resample::Resample 2 %d\n", channels);
44 for(int i = 0; i < channels; i++)
50 for(int i = 0; i < channels; i++)
52 delete [] output_temp[i];
54 delete [] output_temp;
57 delete [] input_chunk_end;
61 delete [] output_temp_start;
62 delete [] output_size;
63 delete [] last_out_end;
66 void Resample::reset(int channel)
68 //printf("Resample::reset 1 channel=%d normalized_sample_rate=%d\n", channel, file->normalized_sample_rate);
71 bzero(resample_init, sizeof(int) * channels);
72 bzero(output_size, sizeof(long) * channels);
73 bzero(last_out_end, sizeof(long) * channels);
74 bzero(input_chunk_end, sizeof(long) * channels);
78 resample_init[channel] = 0;
79 output_size[channel] = 0;
80 last_out_end[channel] = 0;
81 input_chunk_end[channel] = 0;
85 double Resample::blackman(int i, double offset, double fcn, int l)
87 /* This algorithm from:
88 SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C
89 S.D. Stearns and R.A. David, Prentice-Hall, 1992
93 double wcn = (M_PI * fcn);
100 bkwn = 0.42 - 0.5 * cos((x * 2) * M_PI /l) + 0.08 * cos((x * 4) * M_PI /l);
101 if(fabs(x - dly) < 1e-9)
104 return (sin((wcn * (x - dly))) / (M_PI * (x - dly)) * bkwn);
108 int Resample::get_output_size(int channel)
110 return output_size[channel];
113 void Resample::read_output(double *output, int channel, int size)
115 memcpy(output, output_temp[channel], size * sizeof(double));
116 // Shift leftover forward
117 for(int i = size; i < output_size[channel]; i++)
118 output_temp[channel][i - size] = output_temp[channel][i];
119 output_size[channel] -= size;
124 void Resample::resample_chunk(double *input,
130 double resample_ratio = (double)in_rate / out_rate;
132 double fcn, intratio;
133 double offset, xvalue;
137 intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < .0001);
138 fcn = .90 / resample_ratio;
139 if(fcn > .90) fcn = .90;
140 filter_l = BLACKSIZE - 6;
142 if(0 == filter_l % 2 ) --filter_l;
144 /* if resample_ratio = int, filter_l should be even */
145 filter_l += (int)intratio;
147 // Blackman filter initialization must be called whenever there is a
148 // sampling ratio change
149 if(!resample_init[channel] || last_ratio != resample_ratio)
151 resample_init[channel] = 1;
153 bzero(old[channel], sizeof(double) * BLACKSIZE);
155 // precompute blackman filter coefficients
156 for (j = 0; j <= 2 * BPC; ++j)
158 for(j = 0; j <= 2 * BPC; j++)
160 offset = (double)(j - BPC) / (2 * BPC);
161 for(i = 0; i <= filter_l; i++)
163 blackfilt[j][i] = blackman(i, offset, fcn, filter_l);
170 double *inbuf_old = old[channel];
176 time0 = k * resample_ratio;
177 j = (int)floor(time0 - itime[channel]);
179 // if(j + filter_l / 2 >= input_size) break;
180 if(j + (filter_l + 1) / 2 >= in_len) break;
182 /* blackman filter. by default, window centered at j+.5(filter_l%2) */
183 /* but we want a window centered at time0. */
184 offset = (time0 - itime[channel] - (j + .5 * (filter_l % 2)));
185 joff = (int)floor((offset * 2 * BPC) + BPC + .5);
188 for(i = 0; i <= filter_l; i++)
190 int j2 = i + j - filter_l / 2;
191 double y = ((j2 < 0) ? inbuf_old[BLACKSIZE + j2] : input[j2]);
193 xvalue += y * blackfilt[joff][i];
196 if(output_allocation <= output_size[channel])
198 double **new_output = new double*[channels];
199 long new_allocation = output_allocation ? (output_allocation * 2) : 16384;
200 for(int l = 0; l < channels; l++)
202 new_output[l] = new double[new_allocation];
205 bcopy(output_temp[l], new_output[l], output_allocation * sizeof(double));
206 delete [] output_temp[l];
210 if(output_temp) delete [] output_temp;
211 output_temp = new_output;
212 output_allocation = new_allocation;
215 output_temp[channel][output_size[channel]++] = xvalue;
218 num_used = MIN(in_len, j + filter_l / 2);
219 itime[channel] += num_used - k * resample_ratio;
220 // for(i = 0; i < BLACKSIZE; i++)
221 // inbuf_old[i] = input[num_used + i - BLACKSIZE];
222 bcopy(input + num_used - BLACKSIZE, inbuf_old, BLACKSIZE * sizeof(double));
224 last_ratio = resample_ratio;
227 void Resample::read_chunk(double *input, long len, int &reseek, int iteration)
229 //printf("Resample::read_chunk 1\n");
232 file->set_audio_position(file->current_sample, 0);
238 // Resume at the end of the last resample call
239 file->set_audio_position(input_chunk_end[file->current_channel], 0);
242 file->read_samples(input, len, 0);
243 input_chunk_end[file->current_channel] = file->current_sample;
245 //printf("Resample::read_chunk 2\n");
248 int Resample::resample(double *output,
259 #define REPOSITION(x, y) \
260 (labs((x) - (y)) > 1)
264 //printf("Resample::resample 1 last_out_end=%d out_position=%d\n", last_out_end[channel], out_position);
266 if(REPOSITION(last_out_end[channel], out_position))
277 output_temp_start[channel] = file->get_audio_position(out_rate) + out_len;
278 last_out_end[channel] = out_position + out_len;
283 // Drain output buffer
284 if(output_size[channel])
286 int fragment_len = output_size[channel];
287 if(fragment_len > out_len) fragment_len = out_len;
289 //printf("Resample::resample 1 %d %d %d\n", out_len, output_size[channel], channel);
290 bcopy(output_temp[channel], output, fragment_len * sizeof(double));
292 // Shift leftover forward
293 // for(int i = fragment_len; i < output_size[channel]; i++)
294 // output_temp[channel][i - fragment_len] = output_temp[channel][i];
295 bcopy(output_temp[channel] + fragment_len, output_temp[channel], (output_size[channel] - fragment_len) * sizeof(double));
297 output_size[channel] -= fragment_len;
298 out_len -= fragment_len;
299 output += fragment_len;
302 // Import new samples
303 //printf("Resample::resample 2 %d %d\n", out_len, channel);
306 //printf("Resample::resample 3 input_size=%d reseek=%d out_position=%d channel=%d\n", input_size, reseek, out_position, channel);
307 read_chunk(input, input_size, reseek, i);
308 resample_chunk(input,
313 total_input += input_size;
318 //printf("Resample::resample 2 %d %d\n", last_out_end[channel], out_position);
319 //printf("Resample::resample 2 %d %d %d\n", out_len, output_size[channel], channel);
321 //printf("Resample::resample 2 %d %d\n", channel, output_size[channel]);
327 Resample_float::Resample_float(File *file, int channels)
329 //printf("Resample_float::Resample_float 1 %d\n", channels);
331 this->channels = channels;
333 old = new float*[channels];
334 for(int i = 0; i < channels; i++)
336 old[i] = new float[BLACKSIZE];
338 itime = new float[channels];
339 output_temp_start = new long[channels];
340 bzero(output_temp_start, sizeof(long) * channels);
341 resample_init = new int[channels];
342 bzero(resample_init, sizeof(int) * channels);
345 output_size = new long[channels];
346 bzero(output_size, sizeof(long) * channels);
347 output_allocation = 0;
348 input_size = RESAMPLE_CHUNKSIZE;
349 input_chunk_end = new long[channels];
350 bzero(input_chunk_end, sizeof(long) * channels);
351 input = new float[input_size];
352 last_out_end = new long[channels];
353 bzero(last_out_end, sizeof(long) * channels);
357 Resample_float::~Resample_float()
359 for(int i = 0; i < channels; i++)
365 for(int i = 0; i < channels; i++)
367 delete [] output_temp[i];
369 delete [] output_temp;
372 delete [] input_chunk_end;
376 delete [] output_temp_start;
377 delete [] output_size;
378 delete [] last_out_end;
381 void Resample_float::reset(int channel)
383 //printf("Resample_float::reset 1 channel=%d normalized_sample_rate=%d\n", channel, file->normalized_sample_rate);
386 bzero(resample_init, sizeof(int) * channels);
387 bzero(output_size, sizeof(long) * channels);
388 bzero(last_out_end, sizeof(long) * channels);
389 bzero(input_chunk_end, sizeof(long) * channels);
393 resample_init[channel] = 0;
394 output_size[channel] = 0;
395 last_out_end[channel] = 0;
396 input_chunk_end[channel] = 0;
400 float Resample_float::blackman(int i, float offset, float fcn, int l)
402 /* This algorithm from:
403 SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C
404 S.D. Stearns and R.A. David, Prentice-Hall, 1992
408 float wcn = (M_PI * fcn);
415 bkwn = 0.42 - 0.5 * cos((x * 2) * M_PI /l) + 0.08 * cos((x * 4) * M_PI /l);
416 if(fabs(x - dly) < 1e-9)
419 return (sin((wcn * (x - dly))) / (M_PI * (x - dly)) * bkwn);
423 int Resample_float::get_output_size(int channel)
425 return output_size[channel];
428 void Resample_float::read_output(double *output, int channel, int size)
430 memcpy(output, output_temp[channel], size * sizeof(double));
431 // Shift leftover forward
432 for(int i = size; i < output_size[channel]; i++)
433 output_temp[channel][i - size] = output_temp[channel][i];
434 output_size[channel] -= size;
439 void Resample_float::resample_chunk(float *input,
445 float resample_ratio = (float)in_rate / out_rate;
448 float offset, xvalue;
452 //printf("Resample_float::resample_chunk 1\n");
453 intratio = (fabs(resample_ratio - floor(.5 + resample_ratio)) < .0001);
454 fcn = .90 / resample_ratio;
455 if(fcn > .90) fcn = .90;
456 filter_l = BLACKSIZE - 6;
458 if(0 == filter_l % 2 ) --filter_l;
460 //printf("Resample_float::resample_chunk 2\n");
461 /* if resample_ratio = int, filter_l should be even */
462 filter_l += (int)intratio;
464 //printf("Resample_float::resample_chunk 3\n");
465 // Blackman filter initialization must be called whenever there is a
466 // sampling ratio change
467 if(!resample_init[channel] || last_ratio != resample_ratio)
469 resample_init[channel] = 1;
471 bzero(old[channel], sizeof(float) * BLACKSIZE);
473 //printf("Resample_float::resample_chunk 4\n");
474 // precompute blackman filter coefficients
475 for (j = 0; j <= 2 * BPC; ++j)
477 for(j = 0; j <= 2 * BPC; j++)
479 offset = (float)(j - BPC) / (2 * BPC);
480 for(i = 0; i <= filter_l; i++)
482 blackfilt[j][i] = blackman(i, offset, fcn, filter_l);
488 //printf("Resample_float::resample_chunk 5\n");
490 float *inbuf_old = old[channel];
496 //printf("Resample_float::resample_chunk 6\n");
497 time0 = k * resample_ratio;
498 j = (int)floor(time0 - itime[channel]);
500 // if(j + filter_l / 2 >= input_size) break;
501 if(j + (filter_l + 1) / 2 >= in_len) break;
503 //printf("Resample_float::resample_chunk 7\n");
504 /* blackman filter. by default, window centered at j+.5(filter_l%2) */
505 /* but we want a window centered at time0. */
506 offset = (time0 - itime[channel] - (j + .5 * (filter_l % 2)));
507 joff = (int)floor((offset * 2 * BPC) + BPC + .5);
510 //printf("Resample_float::resample_chunk 8\n");
511 for(i = 0; i <= filter_l; i++)
513 int j2 = i + j - filter_l / 2;
514 float y = ((j2 < 0) ? inbuf_old[BLACKSIZE + j2] : input[j2]);
516 //printf("Resample_float::resample_chunk 9\n");
517 xvalue += (double)y * blackfilt[joff][i];
520 //printf("Resample_float::resample_chunk 10\n");
521 if(output_allocation <= output_size[channel])
523 double **new_output = new double*[channels];
524 long new_allocation = output_allocation ? (output_allocation * 2) : 16384;
525 for(int l = 0; l < channels; l++)
527 new_output[l] = new double[new_allocation];
530 bcopy(output_temp[l], new_output[l], output_allocation * sizeof(double));
531 delete [] output_temp[l];
535 if(output_temp) delete [] output_temp;
536 output_temp = new_output;
537 output_allocation = new_allocation;
540 //printf("Resample_float::resample_chunk 11 %d %d\n", output_size[channel], output_allocation);
541 output_temp[channel][output_size[channel]++] = xvalue;
544 //printf("Resample_float::resample_chunk 12\n");
545 num_used = MIN(in_len, j + filter_l / 2);
546 itime[channel] += num_used - k * resample_ratio;
547 // for(i = 0; i < BLACKSIZE; i++)
548 // inbuf_old[i] = input[num_used + i - BLACKSIZE];
549 bcopy(input + num_used - BLACKSIZE, inbuf_old, BLACKSIZE * sizeof(float));
551 //printf("Resample_float::resample_chunk 13\n");
552 last_ratio = resample_ratio;
555 void Resample_float::read_chunk(float *input, long len, int &reseek, int iteration)
557 //printf("Resample_float::read_chunk 1\n");
560 file->set_audio_position(file->current_sample, 0);
566 // Resume at the end of the last resample call
567 file->set_audio_position(input_chunk_end[file->current_channel], 0);
570 file->read_samples(0, len, 0, input);
571 input_chunk_end[file->current_channel] = file->current_sample;
573 //printf("Resample_float::read_chunk 2\n");
576 int Resample_float::resample(double *output,
587 #define REPOSITION(x, y) \
588 (labs((x) - (y)) > 1)
592 //printf("Resample_float::resample 1 last_out_end=%d out_position=%d\n", last_out_end[channel], out_position);
594 if(REPOSITION(last_out_end[channel], out_position))
600 output_temp_start[channel] = file->get_audio_position(out_rate) + out_len;
601 last_out_end[channel] = out_position + out_len;
606 // Drain output buffer
607 if(output_size[channel])
609 int fragment_len = output_size[channel];
610 if(fragment_len > out_len) fragment_len = out_len;
612 //printf("Resample_float::resample 1 %d %d %d\n", out_len, output_size[channel], channel);
613 bcopy(output_temp[channel], output, fragment_len * sizeof(double));
616 // Shift leftover forward
617 //for(int i = fragment_len; i < output_size[channel]; i++)
618 // output_temp[channel][i - fragment_len] = output_temp[channel][i];
619 bcopy(output_temp[channel] + fragment_len, output_temp[channel], (output_size[channel] - fragment_len) * sizeof(double));
621 output_size[channel] -= fragment_len;
622 out_len -= fragment_len;
623 output += fragment_len;
626 // Import new samples
627 //printf("Resample_float::resample 2 %d %d\n", out_len, channel);
630 //printf("Resample_float::resample 3 input_size=%d reseek=%d out_position=%d channel=%d\n", input_size, reseek, out_position, channel);
631 read_chunk(input, input_size, reseek, i);
632 resample_chunk(input,
637 total_input += input_size;
642 //printf("Resample_float::resample 2 %d %d\n", last_out_end[channel], out_position);
643 //printf("Resample_float::resample 2 %d %d %d\n", out_len, output_size[channel], channel);
645 //printf("Resample_float::resample 2 %d %d\n", channel, output_size[channel]);
652 // c-file-style: "linux"