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 / 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];
223 last_ratio = resample_ratio;
226 void Resample::read_chunk(double *input, long len, int &reseek, int iteration)
228 //printf("Resample::read_chunk 1\n");
231 file->set_audio_position(file->current_sample, 0);
237 // Resume at the end of the last resample call
238 file->set_audio_position(input_chunk_end[file->current_channel], 0);
241 file->read_samples(input, len, 0);
242 input_chunk_end[file->current_channel] = file->current_sample;
244 //printf("Resample::read_chunk 2\n");
247 int Resample::resample(double *output,
258 #define REPOSITION(x, y) \
259 (labs((x) - (y)) > 1)
263 //printf("Resample::resample 1 last_out_end=%d out_position=%d\n", last_out_end[channel], out_position);
265 if(REPOSITION(last_out_end[channel], out_position))
276 output_temp_start[channel] = file->get_audio_position(out_rate) + out_len;
277 last_out_end[channel] = out_position + out_len;
282 // Drain output buffer
283 if(output_size[channel])
285 int fragment_len = output_size[channel];
286 if(fragment_len > out_len) fragment_len = out_len;
288 //printf("Resample::resample 1 %d %d %d\n", out_len, output_size[channel], channel);
289 bcopy(output_temp[channel], output, fragment_len * sizeof(double));
291 // Shift leftover forward
292 for(int i = fragment_len; i < output_size[channel]; i++)
293 output_temp[channel][i - fragment_len] = output_temp[channel][i];
295 output_size[channel] -= fragment_len;
296 out_len -= fragment_len;
297 output += fragment_len;
300 // Import new samples
301 //printf("Resample::resample 2 %d %d\n", out_len, channel);
304 //printf("Resample::resample 3 input_size=%d reseek=%d out_position=%d channel=%d\n", input_size, reseek, out_position, channel);
305 read_chunk(input, input_size, reseek, i);
306 resample_chunk(input,
311 total_input += input_size;
316 //printf("Resample::resample 2 %d %d\n", last_out_end[channel], out_position);
317 //printf("Resample::resample 2 %d %d %d\n", out_len, output_size[channel], channel);
319 //printf("Resample::resample 2 %d %d\n", channel, output_size[channel]);