1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 * Crossover filter
22 *
23 * Split an audio stream into several bands.
24 */
25
33
39
41 #define MAX_BANDS MAX_SPLITS + 1
42
48
53
56
62
69
71
75
77
79
81
84
85 #define OFFSET(x) offsetof(AudioCrossoverContext, x)
86 #define AF AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
87
103 {
"precision",
"set processing precision",
OFFSET(precision),
AV_OPT_TYPE_INT, {.i64=0}, 0, 2,
AF,
"precision" },
104 {
"auto",
"set auto processing precision", 0,
AV_OPT_TYPE_CONST, {.i64=0}, 0, 0,
AF,
"precision" },
105 {
"float",
"set single-floating point processing precision", 0,
AV_OPT_TYPE_CONST, {.i64=1}, 0, 0,
AF,
"precision" },
106 {
"double",
"set double-floating point processing precision", 0,
AV_OPT_TYPE_CONST, {.i64=2}, 0, 0,
AF,
"precision" },
108 };
109
111
113 {
119 };
123 };
128
129 switch (
s->precision) {
130 case 0:
131 sample_fmts_list = auto_sample_fmts;
132 break;
133 case 1:
135 break;
136 case 2:
138 break;
139 default:
140 break;
141 }
145
147 }
148
150 {
152 char *p, *
arg, *saveptr =
NULL;
154
158 float gain;
160
162 break;
163
165
169 break;
170 }
171
172 if (
c[0] ==
'd' &&
c[1] ==
'B')
174 else
176 }
177
180
182 }
183
185 {
187 char *p, *
arg, *saveptr =
NULL;
189
193
196 float freq;
197
199 break;
200
202
206 }
207 if (freq <= 0) {
210 }
211
212 if (
i > 0 && freq <= s->splits[
i-1]) {
215 }
216
218 }
219
221
225
226 for (
i = 0;
i <=
s->nb_splits;
i++) {
229
235
238 }
239
241 }
242
244 {
245 double omega = 2. *
M_PI *
fc / sr;
246 double cosine = cos(omega);
247 double alpha = sin(omega) / (2. * q);
248
249 double b0 = (1. - cosine) / 2.;
250 double b1 = 1. - cosine;
251 double b2 = (1. - cosine) / 2.;
253 double a1 = -2. * cosine;
255
261
267 }
268
270 {
271 double omega = 2. *
M_PI *
fc / sr;
272 double cosine = cos(omega);
273 double alpha = sin(omega) / (2. * q);
274
275 double b0 = (1. + cosine) / 2.;
276 double b1 = -1. - cosine;
277 double b2 = (1. + cosine) / 2.;
279 double a1 = -2. * cosine;
281
287
293 }
294
296 {
297 double omega = 2. *
M_PI *
fc / sr;
298 double cosine = cos(omega);
299 double alpha = sin(omega) / (2. * q);
300
302 double a1 = -2. * cosine;
307
313
319 }
320
322 {
323 double omega = 2. *
M_PI *
fc / sr;
324
330
336 }
337
339 {
340 double n = order / 2.;
341
342 for (
int i = 0;
i < n / 2;
i++)
343 q[
i] = 1. / (-2. * cos(
M_PI * (2. * (
i + 1) + n - 1.) / (2. * n)));
344 }
345
346 #define BIQUAD_PROCESS(name, type) \
347 static void biquad_process_## name(const type *const c, \
348 type *b, \
349 type *dst, const type *src, \
350 int nb_samples) \
351 { \
352 const type b0 = c[B0]; \
353 const type b1 = c[B1]; \
354 const type b2 = c[B2]; \
355 const type a1 = c[A1]; \
356 const type a2 = c[A2]; \
357 type z1 = b[0]; \
358 type z2 = b[1]; \
359 \
360 for (int n = 0; n + 1 < nb_samples; n++) { \
361 type in = src[n]; \
362 type out; \
363 \
364 out = in * b0 + z1; \
365 z1 = b1 * in + z2 + a1 * out; \
366 z2 = b2 * in + a2 * out; \
367 dst[n] = out; \
368 \
369 n++; \
370 in = src[n]; \
371 out = in * b0 + z1; \
372 z1 = b1 * in + z2 + a1 * out; \
373 z2 = b2 * in + a2 * out; \
374 dst[n] = out; \
375 } \
376 \
377 if (nb_samples & 1) { \
378 const int n = nb_samples - 1; \
379 const type in = src[n]; \
380 type out; \
381 \
382 out = in * b0 + z1; \
383 z1 = b1 * in + z2 + a1 * out; \
384 z2 = b2 * in + a2 * out; \
385 dst[n] = out; \
386 } \
387 \
388 b[0] = z1; \
389 b[1] = z2; \
390 }
391
394
395 #define XOVER_PROCESS(name, type, one, ff) \
396 static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
397 { \
398 AudioCrossoverContext *s = ctx->priv; \
399 AVFrame *in = arg; \
400 AVFrame **frames = s->frames; \
401 const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \
402 const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \
403 const int nb_samples = in->nb_samples; \
404 const int nb_outs = ctx->nb_outputs; \
405 const int first_order = s->first_order; \
406 \
407 for (int ch = start; ch < end; ch++) { \
408 const type *src = (const type *)in->extended_data[ch]; \
409 type *xover = (type *)s->xover->extended_data[ch]; \
410 \
411 s->fdsp->vector_## ff ##mul_scalar((type *)frames[0]->extended_data[ch], src, \
412 s->level_in, FFALIGN(nb_samples, sizeof(type))); \
413 \
414 for (int band = 0; band < nb_outs; band++) { \
415 for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \
416 const type *prv = (const type *)frames[band]->extended_data[ch]; \
417 type *dst = (type *)frames[band + 1]->extended_data[ch]; \
418 const type *hsrc = f == 0 ? prv : dst; \
419 type *hp = xover + nb_outs * 20 + band * 20 + f * 2; \
420 const type *const hpc = (type *)&s->hp[band][f].c ## ff; \
421 \
422 biquad_process_## name(hpc, hp, dst, hsrc, nb_samples); \
423 } \
424 \
425 for (int f = 0; band + 1 < nb_outs && f < s->filter_count; f++) { \
426 type *dst = (type *)frames[band]->extended_data[ch]; \
427 const type *lsrc = dst; \
428 type *lp = xover + band * 20 + f * 2; \
429 const type *const lpc = (type *)&s->lp[band][f].c ## ff; \
430 \
431 biquad_process_## name(lpc, lp, dst, lsrc, nb_samples); \
432 } \
433 \
434 for (int aband = band + 1; aband + 1 < nb_outs; aband++) { \
435 if (first_order) { \
436 const type *asrc = (const type *)frames[band]->extended_data[ch]; \
437 type *dst = (type *)frames[band]->extended_data[ch]; \
438 type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20; \
439 const type *const apc = (type *)&s->ap[aband][0].c ## ff; \
440 \
441 biquad_process_## name(apc, ap, dst, asrc, nb_samples); \
442 } \
443 \
444 for (int f = first_order; f < s->ap_filter_count; f++) { \
445 const type *asrc = (const type *)frames[band]->extended_data[ch]; \
446 type *dst = (type *)frames[band]->extended_data[ch]; \
447 type *ap = xover + nb_outs * 40 + (aband * nb_outs + band) * 20 + f * 2;\
448 const type *const apc = (type *)&s->ap[aband][f].c ## ff; \
449 \
450 biquad_process_## name(apc, ap, dst, asrc, nb_samples); \
451 } \
452 } \
453 } \
454 \
455 for (int band = 0; band < nb_outs; band++) { \
456 const type gain = s->gains[band] * ((band & 1 && first_order) ? -one : one); \
457 type *dst = (type *)frames[band]->extended_data[ch]; \
458 \
459 s->fdsp->vector_## ff ##mul_scalar(dst, dst, gain, \
460 FFALIGN(nb_samples, sizeof(type))); \
461 } \
462 } \
463 \
464 return 0; \
465 }
466
469
471 {
475 double q[16];
476
477 s->order = (
s->order_opt + 1) * 2;
478 s->filter_count =
s->order / 2;
479 s->first_order =
s->filter_count & 1;
480 s->ap_filter_count =
s->filter_count / 2 +
s->first_order;
482
483 for (
int band = 0; band <=
s->nb_splits; band++) {
484 if (
s->first_order) {
487 }
488
489 for (
int n =
s->first_order; n < s->filter_count; n++) {
490 const int idx =
s->filter_count / 2 - ((n +
s->first_order) / 2 -
s->first_order) - 1;
491
494 }
495
498
499 for (
int n =
s->first_order; n < s->ap_filter_count; n++) {
500 const int idx = (
s->filter_count / 2 - ((n * 2 +
s->first_order) / 2 -
s->first_order) - 1);
501
503 }
504 }
505
510 }
511
513 ctx->nb_outputs *
ctx->nb_outputs * 10));
516
517 return 0;
518 }
519
521 {
526
527 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
531 break;
532 }
533
535 }
536
539
542
543 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
546 continue;
547 }
548
552 break;
553 }
554
556 for (
int i = 0;
i <
ctx->nb_outputs;
i++)
558
560 }
561
563 {
568
569 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
571 }
572
581 }
582
584 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
586 continue;
588 }
589 return 0;
590 }
591
592 for (
int i = 0;
i <
ctx->nb_outputs;
i++) {
594 continue;
595
598 return 0;
599 }
600 }
601
603 }
604
606 {
608
611 }
612
614 {
618 },
619 };
620
622 .
name =
"acrossover",
625 .priv_class = &acrossover_class,
634 };