Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * Copyright (c) 2004 Michael Niedermayer |
||
3 | * Copyright (c) 2012 Justin Ruggles |
||
4 | * |
||
5 | * This file is part of FFmpeg. |
||
6 | * |
||
7 | * FFmpeg is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU Lesser General Public |
||
9 | * License as published by the Free Software Foundation; either |
||
10 | * version 2.1 of the License, or (at your option) any later version. |
||
11 | * |
||
12 | * FFmpeg is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
15 | * Lesser General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU Lesser General Public |
||
18 | * License along with FFmpeg; if not, write to the Free Software |
||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
||
20 | */ |
||
21 | |||
22 | #include "libavutil/common.h" |
||
23 | #include "libavutil/libm.h" |
||
24 | #include "libavutil/log.h" |
||
25 | #include "internal.h" |
||
26 | #include "resample.h" |
||
27 | #include "audio_data.h" |
||
28 | |||
29 | struct ResampleContext { |
||
30 | AVAudioResampleContext *avr; |
||
31 | AudioData *buffer; |
||
32 | uint8_t *filter_bank; |
||
33 | int filter_length; |
||
34 | int ideal_dst_incr; |
||
35 | int dst_incr; |
||
36 | int index; |
||
37 | int frac; |
||
38 | int src_incr; |
||
39 | int compensation_distance; |
||
40 | int phase_shift; |
||
41 | int phase_mask; |
||
42 | int linear; |
||
43 | enum AVResampleFilterType filter_type; |
||
44 | int kaiser_beta; |
||
45 | double factor; |
||
46 | void (*set_filter)(void *filter, double *tab, int phase, int tap_count); |
||
47 | void (*resample_one)(struct ResampleContext *c, int no_filter, void *dst0, |
||
48 | int dst_index, const void *src0, int src_size, |
||
49 | int index, int frac); |
||
50 | }; |
||
51 | |||
52 | |||
53 | /* double template */ |
||
54 | #define CONFIG_RESAMPLE_DBL |
||
55 | #include "resample_template.c" |
||
56 | #undef CONFIG_RESAMPLE_DBL |
||
57 | |||
58 | /* float template */ |
||
59 | #define CONFIG_RESAMPLE_FLT |
||
60 | #include "resample_template.c" |
||
61 | #undef CONFIG_RESAMPLE_FLT |
||
62 | |||
63 | /* s32 template */ |
||
64 | #define CONFIG_RESAMPLE_S32 |
||
65 | #include "resample_template.c" |
||
66 | #undef CONFIG_RESAMPLE_S32 |
||
67 | |||
68 | /* s16 template */ |
||
69 | #include "resample_template.c" |
||
70 | |||
71 | |||
72 | /* 0th order modified bessel function of the first kind. */ |
||
73 | static double bessel(double x) |
||
74 | { |
||
75 | double v = 1; |
||
76 | double lastv = 0; |
||
77 | double t = 1; |
||
78 | int i; |
||
79 | |||
80 | x = x * x / 4; |
||
81 | for (i = 1; v != lastv; i++) { |
||
82 | lastv = v; |
||
83 | t *= x / (i * i); |
||
84 | v += t; |
||
85 | } |
||
86 | return v; |
||
87 | } |
||
88 | |||
89 | /* Build a polyphase filterbank. */ |
||
90 | static int build_filter(ResampleContext *c) |
||
91 | { |
||
92 | int ph, i; |
||
93 | double x, y, w, factor; |
||
94 | double *tab; |
||
95 | int tap_count = c->filter_length; |
||
96 | int phase_count = 1 << c->phase_shift; |
||
97 | const int center = (tap_count - 1) / 2; |
||
98 | |||
99 | tab = av_malloc(tap_count * sizeof(*tab)); |
||
100 | if (!tab) |
||
101 | return AVERROR(ENOMEM); |
||
102 | |||
103 | /* if upsampling, only need to interpolate, no filter */ |
||
104 | factor = FFMIN(c->factor, 1.0); |
||
105 | |||
106 | for (ph = 0; ph < phase_count; ph++) { |
||
107 | double norm = 0; |
||
108 | for (i = 0; i < tap_count; i++) { |
||
109 | x = M_PI * ((double)(i - center) - (double)ph / phase_count) * factor; |
||
110 | if (x == 0) y = 1.0; |
||
111 | else y = sin(x) / x; |
||
112 | switch (c->filter_type) { |
||
113 | case AV_RESAMPLE_FILTER_TYPE_CUBIC: { |
||
114 | const float d = -0.5; //first order derivative = -0.5 |
||
115 | x = fabs(((double)(i - center) - (double)ph / phase_count) * factor); |
||
116 | if (x < 1.0) y = 1 - 3 * x*x + 2 * x*x*x + d * ( -x*x + x*x*x); |
||
117 | else y = d * (-4 + 8 * x - 5 * x*x + x*x*x); |
||
118 | break; |
||
119 | } |
||
120 | case AV_RESAMPLE_FILTER_TYPE_BLACKMAN_NUTTALL: |
||
121 | w = 2.0 * x / (factor * tap_count) + M_PI; |
||
122 | y *= 0.3635819 - 0.4891775 * cos( w) + |
||
123 | 0.1365995 * cos(2 * w) - |
||
124 | 0.0106411 * cos(3 * w); |
||
125 | break; |
||
126 | case AV_RESAMPLE_FILTER_TYPE_KAISER: |
||
127 | w = 2.0 * x / (factor * tap_count * M_PI); |
||
128 | y *= bessel(c->kaiser_beta * sqrt(FFMAX(1 - w * w, 0))); |
||
129 | break; |
||
130 | } |
||
131 | |||
132 | tab[i] = y; |
||
133 | norm += y; |
||
134 | } |
||
135 | /* normalize so that an uniform color remains the same */ |
||
136 | for (i = 0; i < tap_count; i++) |
||
137 | tab[i] = tab[i] / norm; |
||
138 | |||
139 | c->set_filter(c->filter_bank, tab, ph, tap_count); |
||
140 | } |
||
141 | |||
142 | av_free(tab); |
||
143 | return 0; |
||
144 | } |
||
145 | |||
146 | ResampleContext *ff_audio_resample_init(AVAudioResampleContext *avr) |
||
147 | { |
||
148 | ResampleContext *c; |
||
149 | int out_rate = avr->out_sample_rate; |
||
150 | int in_rate = avr->in_sample_rate; |
||
151 | double factor = FFMIN(out_rate * avr->cutoff / in_rate, 1.0); |
||
152 | int phase_count = 1 << avr->phase_shift; |
||
153 | int felem_size; |
||
154 | |||
155 | if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P && |
||
156 | avr->internal_sample_fmt != AV_SAMPLE_FMT_S32P && |
||
157 | avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP && |
||
158 | avr->internal_sample_fmt != AV_SAMPLE_FMT_DBLP) { |
||
159 | av_log(avr, AV_LOG_ERROR, "Unsupported internal format for " |
||
160 | "resampling: %s\n", |
||
161 | av_get_sample_fmt_name(avr->internal_sample_fmt)); |
||
162 | return NULL; |
||
163 | } |
||
164 | c = av_mallocz(sizeof(*c)); |
||
165 | if (!c) |
||
166 | return NULL; |
||
167 | |||
168 | c->avr = avr; |
||
169 | c->phase_shift = avr->phase_shift; |
||
170 | c->phase_mask = phase_count - 1; |
||
171 | c->linear = avr->linear_interp; |
||
172 | c->factor = factor; |
||
173 | c->filter_length = FFMAX((int)ceil(avr->filter_size / factor), 1); |
||
174 | c->filter_type = avr->filter_type; |
||
175 | c->kaiser_beta = avr->kaiser_beta; |
||
176 | |||
177 | switch (avr->internal_sample_fmt) { |
||
178 | case AV_SAMPLE_FMT_DBLP: |
||
179 | c->resample_one = resample_one_dbl; |
||
180 | c->set_filter = set_filter_dbl; |
||
181 | break; |
||
182 | case AV_SAMPLE_FMT_FLTP: |
||
183 | c->resample_one = resample_one_flt; |
||
184 | c->set_filter = set_filter_flt; |
||
185 | break; |
||
186 | case AV_SAMPLE_FMT_S32P: |
||
187 | c->resample_one = resample_one_s32; |
||
188 | c->set_filter = set_filter_s32; |
||
189 | break; |
||
190 | case AV_SAMPLE_FMT_S16P: |
||
191 | c->resample_one = resample_one_s16; |
||
192 | c->set_filter = set_filter_s16; |
||
193 | break; |
||
194 | } |
||
195 | |||
196 | felem_size = av_get_bytes_per_sample(avr->internal_sample_fmt); |
||
197 | c->filter_bank = av_mallocz(c->filter_length * (phase_count + 1) * felem_size); |
||
198 | if (!c->filter_bank) |
||
199 | goto error; |
||
200 | |||
201 | if (build_filter(c) < 0) |
||
202 | goto error; |
||
203 | |||
204 | memcpy(&c->filter_bank[(c->filter_length * phase_count + 1) * felem_size], |
||
205 | c->filter_bank, (c->filter_length - 1) * felem_size); |
||
206 | memcpy(&c->filter_bank[c->filter_length * phase_count * felem_size], |
||
207 | &c->filter_bank[(c->filter_length - 1) * felem_size], felem_size); |
||
208 | |||
209 | c->compensation_distance = 0; |
||
210 | if (!av_reduce(&c->src_incr, &c->dst_incr, out_rate, |
||
211 | in_rate * (int64_t)phase_count, INT32_MAX / 2)) |
||
212 | goto error; |
||
213 | c->ideal_dst_incr = c->dst_incr; |
||
214 | |||
215 | c->index = -phase_count * ((c->filter_length - 1) / 2); |
||
216 | c->frac = 0; |
||
217 | |||
218 | /* allocate internal buffer */ |
||
219 | c->buffer = ff_audio_data_alloc(avr->resample_channels, 0, |
||
220 | avr->internal_sample_fmt, |
||
221 | "resample buffer"); |
||
222 | if (!c->buffer) |
||
223 | goto error; |
||
224 | |||
225 | av_log(avr, AV_LOG_DEBUG, "resample: %s from %d Hz to %d Hz\n", |
||
226 | av_get_sample_fmt_name(avr->internal_sample_fmt), |
||
227 | avr->in_sample_rate, avr->out_sample_rate); |
||
228 | |||
229 | return c; |
||
230 | |||
231 | error: |
||
232 | ff_audio_data_free(&c->buffer); |
||
233 | av_free(c->filter_bank); |
||
234 | av_free(c); |
||
235 | return NULL; |
||
236 | } |
||
237 | |||
238 | void ff_audio_resample_free(ResampleContext **c) |
||
239 | { |
||
240 | if (!*c) |
||
241 | return; |
||
242 | ff_audio_data_free(&(*c)->buffer); |
||
243 | av_free((*c)->filter_bank); |
||
244 | av_freep(c); |
||
245 | } |
||
246 | |||
247 | int avresample_set_compensation(AVAudioResampleContext *avr, int sample_delta, |
||
248 | int compensation_distance) |
||
249 | { |
||
250 | ResampleContext *c; |
||
251 | AudioData *fifo_buf = NULL; |
||
252 | int ret = 0; |
||
253 | |||
254 | if (compensation_distance < 0) |
||
255 | return AVERROR(EINVAL); |
||
256 | if (!compensation_distance && sample_delta) |
||
257 | return AVERROR(EINVAL); |
||
258 | |||
259 | if (!avr->resample_needed) { |
||
260 | #if FF_API_RESAMPLE_CLOSE_OPEN |
||
261 | /* if resampling was not enabled previously, re-initialize the |
||
262 | AVAudioResampleContext and force resampling */ |
||
263 | int fifo_samples; |
||
264 | int restore_matrix = 0; |
||
265 | double matrix[AVRESAMPLE_MAX_CHANNELS * AVRESAMPLE_MAX_CHANNELS] = { 0 }; |
||
266 | |||
267 | /* buffer any remaining samples in the output FIFO before closing */ |
||
268 | fifo_samples = av_audio_fifo_size(avr->out_fifo); |
||
269 | if (fifo_samples > 0) { |
||
270 | fifo_buf = ff_audio_data_alloc(avr->out_channels, fifo_samples, |
||
271 | avr->out_sample_fmt, NULL); |
||
272 | if (!fifo_buf) |
||
273 | return AVERROR(EINVAL); |
||
274 | ret = ff_audio_data_read_from_fifo(avr->out_fifo, fifo_buf, |
||
275 | fifo_samples); |
||
276 | if (ret < 0) |
||
277 | goto reinit_fail; |
||
278 | } |
||
279 | /* save the channel mixing matrix */ |
||
280 | if (avr->am) { |
||
281 | ret = avresample_get_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS); |
||
282 | if (ret < 0) |
||
283 | goto reinit_fail; |
||
284 | restore_matrix = 1; |
||
285 | } |
||
286 | |||
287 | /* close the AVAudioResampleContext */ |
||
288 | avresample_close(avr); |
||
289 | |||
290 | avr->force_resampling = 1; |
||
291 | |||
292 | /* restore the channel mixing matrix */ |
||
293 | if (restore_matrix) { |
||
294 | ret = avresample_set_matrix(avr, matrix, AVRESAMPLE_MAX_CHANNELS); |
||
295 | if (ret < 0) |
||
296 | goto reinit_fail; |
||
297 | } |
||
298 | |||
299 | /* re-open the AVAudioResampleContext */ |
||
300 | ret = avresample_open(avr); |
||
301 | if (ret < 0) |
||
302 | goto reinit_fail; |
||
303 | |||
304 | /* restore buffered samples to the output FIFO */ |
||
305 | if (fifo_samples > 0) { |
||
306 | ret = ff_audio_data_add_to_fifo(avr->out_fifo, fifo_buf, 0, |
||
307 | fifo_samples); |
||
308 | if (ret < 0) |
||
309 | goto reinit_fail; |
||
310 | ff_audio_data_free(&fifo_buf); |
||
311 | } |
||
312 | #else |
||
313 | av_log(avr, AV_LOG_ERROR, "Unable to set resampling compensation\n"); |
||
314 | return AVERROR(EINVAL); |
||
315 | #endif |
||
316 | } |
||
317 | c = avr->resample; |
||
318 | c->compensation_distance = compensation_distance; |
||
319 | if (compensation_distance) { |
||
320 | c->dst_incr = c->ideal_dst_incr - c->ideal_dst_incr * |
||
321 | (int64_t)sample_delta / compensation_distance; |
||
322 | } else { |
||
323 | c->dst_incr = c->ideal_dst_incr; |
||
324 | } |
||
325 | return 0; |
||
326 | |||
327 | reinit_fail: |
||
328 | ff_audio_data_free(&fifo_buf); |
||
329 | return ret; |
||
330 | } |
||
331 | |||
332 | static int resample(ResampleContext *c, void *dst, const void *src, |
||
333 | int *consumed, int src_size, int dst_size, int update_ctx) |
||
334 | { |
||
335 | int dst_index; |
||
336 | int index = c->index; |
||
337 | int frac = c->frac; |
||
338 | int dst_incr_frac = c->dst_incr % c->src_incr; |
||
339 | int dst_incr = c->dst_incr / c->src_incr; |
||
340 | int compensation_distance = c->compensation_distance; |
||
341 | |||
342 | if (!dst != !src) |
||
343 | return AVERROR(EINVAL); |
||
344 | |||
345 | if (compensation_distance == 0 && c->filter_length == 1 && |
||
346 | c->phase_shift == 0) { |
||
347 | int64_t index2 = ((int64_t)index) << 32; |
||
348 | int64_t incr = (1LL << 32) * c->dst_incr / c->src_incr; |
||
349 | dst_size = FFMIN(dst_size, |
||
350 | (src_size-1-index) * (int64_t)c->src_incr / |
||
351 | c->dst_incr); |
||
352 | |||
353 | if (dst) { |
||
354 | for(dst_index = 0; dst_index < dst_size; dst_index++) { |
||
355 | c->resample_one(c, 1, dst, dst_index, src, 0, index2 >> 32, 0); |
||
356 | index2 += incr; |
||
357 | } |
||
358 | } else { |
||
359 | dst_index = dst_size; |
||
360 | } |
||
361 | index += dst_index * dst_incr; |
||
362 | index += (frac + dst_index * (int64_t)dst_incr_frac) / c->src_incr; |
||
363 | frac = (frac + dst_index * (int64_t)dst_incr_frac) % c->src_incr; |
||
364 | } else { |
||
365 | for (dst_index = 0; dst_index < dst_size; dst_index++) { |
||
366 | int sample_index = index >> c->phase_shift; |
||
367 | |||
368 | if (sample_index + c->filter_length > src_size || |
||
369 | -sample_index >= src_size) |
||
370 | break; |
||
371 | |||
372 | if (dst) |
||
373 | c->resample_one(c, 0, dst, dst_index, src, src_size, index, frac); |
||
374 | |||
375 | frac += dst_incr_frac; |
||
376 | index += dst_incr; |
||
377 | if (frac >= c->src_incr) { |
||
378 | frac -= c->src_incr; |
||
379 | index++; |
||
380 | } |
||
381 | if (dst_index + 1 == compensation_distance) { |
||
382 | compensation_distance = 0; |
||
383 | dst_incr_frac = c->ideal_dst_incr % c->src_incr; |
||
384 | dst_incr = c->ideal_dst_incr / c->src_incr; |
||
385 | } |
||
386 | } |
||
387 | } |
||
388 | if (consumed) |
||
389 | *consumed = FFMAX(index, 0) >> c->phase_shift; |
||
390 | |||
391 | if (update_ctx) { |
||
392 | if (index >= 0) |
||
393 | index &= c->phase_mask; |
||
394 | |||
395 | if (compensation_distance) { |
||
396 | compensation_distance -= dst_index; |
||
397 | if (compensation_distance <= 0) |
||
398 | return AVERROR_BUG; |
||
399 | } |
||
400 | c->frac = frac; |
||
401 | c->index = index; |
||
402 | c->dst_incr = dst_incr_frac + c->src_incr*dst_incr; |
||
403 | c->compensation_distance = compensation_distance; |
||
404 | } |
||
405 | |||
406 | return dst_index; |
||
407 | } |
||
408 | |||
409 | int ff_audio_resample(ResampleContext *c, AudioData *dst, AudioData *src) |
||
410 | { |
||
411 | int ch, in_samples, in_leftover, consumed = 0, out_samples = 0; |
||
412 | int ret = AVERROR(EINVAL); |
||
413 | |||
414 | in_samples = src ? src->nb_samples : 0; |
||
415 | in_leftover = c->buffer->nb_samples; |
||
416 | |||
417 | /* add input samples to the internal buffer */ |
||
418 | if (src) { |
||
419 | ret = ff_audio_data_combine(c->buffer, in_leftover, src, 0, in_samples); |
||
420 | if (ret < 0) |
||
421 | return ret; |
||
422 | } else if (!in_leftover) { |
||
423 | /* no remaining samples to flush */ |
||
424 | return 0; |
||
425 | } else { |
||
426 | /* TODO: pad buffer to flush completely */ |
||
427 | } |
||
428 | |||
429 | /* calculate output size and reallocate output buffer if needed */ |
||
430 | /* TODO: try to calculate this without the dummy resample() run */ |
||
431 | if (!dst->read_only && dst->allow_realloc) { |
||
432 | out_samples = resample(c, NULL, NULL, NULL, c->buffer->nb_samples, |
||
433 | INT_MAX, 0); |
||
434 | ret = ff_audio_data_realloc(dst, out_samples); |
||
435 | if (ret < 0) { |
||
436 | av_log(c->avr, AV_LOG_ERROR, "error reallocating output\n"); |
||
437 | return ret; |
||
438 | } |
||
439 | } |
||
440 | |||
441 | /* resample each channel plane */ |
||
442 | for (ch = 0; ch < c->buffer->channels; ch++) { |
||
443 | out_samples = resample(c, (void *)dst->data[ch], |
||
444 | (const void *)c->buffer->data[ch], &consumed, |
||
445 | c->buffer->nb_samples, dst->allocated_samples, |
||
446 | ch + 1 == c->buffer->channels); |
||
447 | } |
||
448 | if (out_samples < 0) { |
||
449 | av_log(c->avr, AV_LOG_ERROR, "error during resampling\n"); |
||
450 | return out_samples; |
||
451 | } |
||
452 | |||
453 | /* drain consumed samples from the internal buffer */ |
||
454 | ff_audio_data_drain(c->buffer, consumed); |
||
455 | |||
456 | av_dlog(c->avr, "resampled %d in + %d leftover to %d out + %d leftover\n", |
||
457 | in_samples, in_leftover, out_samples, c->buffer->nb_samples); |
||
458 | |||
459 | dst->nb_samples = out_samples; |
||
460 | return 0; |
||
461 | } |
||
462 | |||
463 | int avresample_get_delay(AVAudioResampleContext *avr) |
||
464 | { |
||
465 | if (!avr->resample_needed || !avr->resample) |
||
466 | return 0; |
||
467 | |||
468 | return avr->resample->buffer->nb_samples; |
||
469 | }>>>>=>>>><>><>>>>>>>>><>>>>>><> |