• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * COpyright (c) 2002 Daniel Pouzzner
3  * Copyright (c) 1999 Chris Bagwell
4  * Copyright (c) 1999 Nick Bailey
5  * Copyright (c) 2007 Rob Sykes <robs@users.sourceforge.net>
6  * Copyright (c) 2013 Paul B Mahol
7  * Copyright (c) 2014 Andrew Kelley
8  *
9  * This file is part of FFmpeg.
10  *
11  * FFmpeg is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * FFmpeg is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with FFmpeg; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  */
25 
26 /**
27  * @file
28  * audio multiband compand filter
29  */
30 
31 #include "libavutil/avstring.h"
32 #include "libavutil/ffmath.h"
33 #include "libavutil/opt.h"
34 #include "libavutil/samplefmt.h"
35 #include "audio.h"
36 #include "avfilter.h"
37 #include "internal.h"
38 
39 typedef struct CompandSegment {
40     double x, y;
41     double a, b;
42 } CompandSegment;
43 
44 typedef struct CompandT {
45     CompandSegment *segments;
46     int nb_segments;
47     double in_min_lin;
48     double out_min_lin;
49     double curve_dB;
50     double gain_dB;
51 } CompandT;
52 
53 #define N 4
54 
55 typedef struct PrevCrossover {
56     double in;
57     double out_low;
58     double out_high;
59 } PrevCrossover[N * 2];
60 
61 typedef struct Crossover {
62   PrevCrossover *previous;
63   size_t         pos;
64   double         coefs[3 *(N+1)];
65 } Crossover;
66 
67 typedef struct CompBand {
68     CompandT transfer_fn;
69     double *attack_rate;
70     double *decay_rate;
71     double *volume;
72     double delay;
73     double topfreq;
74     Crossover filter;
75     AVFrame *delay_buf;
76     size_t delay_size;
77     ptrdiff_t delay_buf_ptr;
78     size_t delay_buf_cnt;
79 } CompBand;
80 
81 typedef struct MCompandContext {
82     const AVClass *class;
83 
84     char *args;
85 
86     int nb_bands;
87     CompBand *bands;
88     AVFrame *band_buf1, *band_buf2, *band_buf3;
89     int band_samples;
90     size_t delay_buf_size;
91 } MCompandContext;
92 
93 #define OFFSET(x) offsetof(MCompandContext, x)
94 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
95 
96 static const AVOption mcompand_options[] = {
97     { "args", "set parameters for each band", OFFSET(args), AV_OPT_TYPE_STRING, { .str = "0.005,0.1 6 -47/-40,-34/-34,-17/-33 100 | 0.003,0.05 6 -47/-40,-34/-34,-17/-33 400 | 0.000625,0.0125 6 -47/-40,-34/-34,-15/-33 1600 | 0.0001,0.025 6 -47/-40,-34/-34,-31/-31,-0/-30 6400 | 0,0.025 6 -38/-31,-28/-28,-0/-25 22000" }, 0, 0, A },
98     { NULL }
99 };
100 
101 AVFILTER_DEFINE_CLASS(mcompand);
102 
uninit(AVFilterContext * ctx)103 static av_cold void uninit(AVFilterContext *ctx)
104 {
105     MCompandContext *s = ctx->priv;
106     int i;
107 
108     av_frame_free(&s->band_buf1);
109     av_frame_free(&s->band_buf2);
110     av_frame_free(&s->band_buf3);
111 
112     if (s->bands) {
113         for (i = 0; i < s->nb_bands; i++) {
114             av_freep(&s->bands[i].attack_rate);
115             av_freep(&s->bands[i].decay_rate);
116             av_freep(&s->bands[i].volume);
117             av_freep(&s->bands[i].transfer_fn.segments);
118             av_freep(&s->bands[i].filter.previous);
119             av_frame_free(&s->bands[i].delay_buf);
120         }
121     }
122     av_freep(&s->bands);
123 }
124 
count_items(char * item_str,int * nb_items,char delimiter)125 static void count_items(char *item_str, int *nb_items, char delimiter)
126 {
127     char *p;
128 
129     *nb_items = 1;
130     for (p = item_str; *p; p++) {
131         if (*p == delimiter)
132             (*nb_items)++;
133     }
134 }
135 
update_volume(CompBand * cb,double in,int ch)136 static void update_volume(CompBand *cb, double in, int ch)
137 {
138     double delta = in - cb->volume[ch];
139 
140     if (delta > 0.0)
141         cb->volume[ch] += delta * cb->attack_rate[ch];
142     else
143         cb->volume[ch] += delta * cb->decay_rate[ch];
144 }
145 
get_volume(CompandT * s,double in_lin)146 static double get_volume(CompandT *s, double in_lin)
147 {
148     CompandSegment *cs;
149     double in_log, out_log;
150     int i;
151 
152     if (in_lin <= s->in_min_lin)
153         return s->out_min_lin;
154 
155     in_log = log(in_lin);
156 
157     for (i = 1; i < s->nb_segments; i++)
158         if (in_log <= s->segments[i].x)
159             break;
160     cs = &s->segments[i - 1];
161     in_log -= cs->x;
162     out_log = cs->y + in_log * (cs->a * in_log + cs->b);
163 
164     return exp(out_log);
165 }
166 
parse_points(char * points,int nb_points,double radius,CompandT * s,AVFilterContext * ctx)167 static int parse_points(char *points, int nb_points, double radius,
168                         CompandT *s, AVFilterContext *ctx)
169 {
170     int new_nb_items, num;
171     char *saveptr = NULL;
172     char *p = points;
173     int i;
174 
175 #define S(x) s->segments[2 * ((x) + 1)]
176     for (i = 0, new_nb_items = 0; i < nb_points; i++) {
177         char *tstr = av_strtok(p, ",", &saveptr);
178         p = NULL;
179         if (!tstr || sscanf(tstr, "%lf/%lf", &S(i).x, &S(i).y) != 2) {
180             av_log(ctx, AV_LOG_ERROR,
181                     "Invalid and/or missing input/output value.\n");
182             return AVERROR(EINVAL);
183         }
184         if (i && S(i - 1).x > S(i).x) {
185             av_log(ctx, AV_LOG_ERROR,
186                     "Transfer function input values must be increasing.\n");
187             return AVERROR(EINVAL);
188         }
189         S(i).y -= S(i).x;
190         av_log(ctx, AV_LOG_DEBUG, "%d: x=%f y=%f\n", i, S(i).x, S(i).y);
191         new_nb_items++;
192     }
193     num = new_nb_items;
194 
195     /* Add 0,0 if necessary */
196     if (num == 0 || S(num - 1).x)
197         num++;
198 
199 #undef S
200 #define S(x) s->segments[2 * (x)]
201     /* Add a tail off segment at the start */
202     S(0).x = S(1).x - 2 * s->curve_dB;
203     S(0).y = S(1).y;
204     num++;
205 
206     /* Join adjacent colinear segments */
207     for (i = 2; i < num; i++) {
208         double g1 = (S(i - 1).y - S(i - 2).y) * (S(i - 0).x - S(i - 1).x);
209         double g2 = (S(i - 0).y - S(i - 1).y) * (S(i - 1).x - S(i - 2).x);
210         int j;
211 
212         if (fabs(g1 - g2))
213             continue;
214         num--;
215         for (j = --i; j < num; j++)
216             S(j) = S(j + 1);
217     }
218 
219     for (i = 0; i < s->nb_segments; i += 2) {
220         s->segments[i].y += s->gain_dB;
221         s->segments[i].x *= M_LN10 / 20;
222         s->segments[i].y *= M_LN10 / 20;
223     }
224 
225 #define L(x) s->segments[i - (x)]
226     for (i = 4; i < s->nb_segments; i += 2) {
227         double x, y, cx, cy, in1, in2, out1, out2, theta, len, r;
228 
229         L(4).a = 0;
230         L(4).b = (L(2).y - L(4).y) / (L(2).x - L(4).x);
231 
232         L(2).a = 0;
233         L(2).b = (L(0).y - L(2).y) / (L(0).x - L(2).x);
234 
235         theta = atan2(L(2).y - L(4).y, L(2).x - L(4).x);
236         len = hypot(L(2).x - L(4).x, L(2).y - L(4).y);
237         r = FFMIN(radius, len);
238         L(3).x = L(2).x - r * cos(theta);
239         L(3).y = L(2).y - r * sin(theta);
240 
241         theta = atan2(L(0).y - L(2).y, L(0).x - L(2).x);
242         len = hypot(L(0).x - L(2).x, L(0).y - L(2).y);
243         r = FFMIN(radius, len / 2);
244         x = L(2).x + r * cos(theta);
245         y = L(2).y + r * sin(theta);
246 
247         cx = (L(3).x + L(2).x + x) / 3;
248         cy = (L(3).y + L(2).y + y) / 3;
249 
250         L(2).x = x;
251         L(2).y = y;
252 
253         in1  = cx - L(3).x;
254         out1 = cy - L(3).y;
255         in2  = L(2).x - L(3).x;
256         out2 = L(2).y - L(3).y;
257         L(3).a = (out2 / in2 - out1 / in1) / (in2 - in1);
258         L(3).b = out1 / in1 - L(3).a * in1;
259     }
260     L(3).x = 0;
261     L(3).y = L(2).y;
262 
263     s->in_min_lin  = exp(s->segments[1].x);
264     s->out_min_lin = exp(s->segments[1].y);
265 
266     return 0;
267 }
268 
square_quadratic(double const * x,double * y)269 static void square_quadratic(double const *x, double *y)
270 {
271     y[0] = x[0] * x[0];
272     y[1] = 2 * x[0] * x[1];
273     y[2] = 2 * x[0] * x[2] + x[1] * x[1];
274     y[3] = 2 * x[1] * x[2];
275     y[4] = x[2] * x[2];
276 }
277 
crossover_setup(AVFilterLink * outlink,Crossover * p,double frequency)278 static int crossover_setup(AVFilterLink *outlink, Crossover *p, double frequency)
279 {
280     double w0 = 2 * M_PI * frequency / outlink->sample_rate;
281     double Q = sqrt(.5), alpha = sin(w0) / (2*Q);
282     double x[9], norm;
283     int i;
284 
285     if (w0 > M_PI)
286         return AVERROR(EINVAL);
287 
288     x[0] =  (1 - cos(w0))/2;           /* Cf. filter_LPF in biquads.c */
289     x[1] =   1 - cos(w0);
290     x[2] =  (1 - cos(w0))/2;
291     x[3] =  (1 + cos(w0))/2;           /* Cf. filter_HPF in biquads.c */
292     x[4] = -(1 + cos(w0));
293     x[5] =  (1 + cos(w0))/2;
294     x[6] =   1 + alpha;
295     x[7] =  -2*cos(w0);
296     x[8] =   1 - alpha;
297 
298     for (norm = x[6], i = 0; i < 9; ++i)
299         x[i] /= norm;
300 
301     square_quadratic(x    , p->coefs);
302     square_quadratic(x + 3, p->coefs + 5);
303     square_quadratic(x + 6, p->coefs + 10);
304 
305     p->previous = av_calloc(outlink->ch_layout.nb_channels, sizeof(*p->previous));
306     if (!p->previous)
307         return AVERROR(ENOMEM);
308 
309     return 0;
310 }
311 
config_output(AVFilterLink * outlink)312 static int config_output(AVFilterLink *outlink)
313 {
314     AVFilterContext *ctx  = outlink->src;
315     MCompandContext *s    = ctx->priv;
316     int ret, ch, i, k, new_nb_items, nb_bands;
317     char *p = s->args, *saveptr = NULL;
318     int max_delay_size = 0;
319 
320     count_items(s->args, &nb_bands, '|');
321     s->nb_bands = FFMAX(1, nb_bands);
322 
323     s->bands = av_calloc(nb_bands, sizeof(*s->bands));
324     if (!s->bands)
325         return AVERROR(ENOMEM);
326 
327     for (i = 0, new_nb_items = 0; i < nb_bands; i++) {
328         int nb_points, nb_attacks, nb_items = 0;
329         char *tstr2, *tstr = av_strtok(p, "|", &saveptr);
330         char *p2, *p3, *saveptr2 = NULL, *saveptr3 = NULL;
331         double radius;
332 
333         if (!tstr)
334             return AVERROR(EINVAL);
335         p = NULL;
336 
337         p2 = tstr;
338         count_items(tstr, &nb_items, ' ');
339         tstr2 = av_strtok(p2, " ", &saveptr2);
340         if (!tstr2) {
341             av_log(ctx, AV_LOG_ERROR, "at least one attacks/decays rate is mandatory\n");
342             return AVERROR(EINVAL);
343         }
344         p2 = NULL;
345         p3 = tstr2;
346 
347         count_items(tstr2, &nb_attacks, ',');
348         if (!nb_attacks || nb_attacks & 1) {
349             av_log(ctx, AV_LOG_ERROR, "number of attacks rate plus decays rate must be even\n");
350             return AVERROR(EINVAL);
351         }
352 
353         s->bands[i].attack_rate = av_calloc(outlink->ch_layout.nb_channels, sizeof(double));
354         s->bands[i].decay_rate = av_calloc(outlink->ch_layout.nb_channels, sizeof(double));
355         s->bands[i].volume = av_calloc(outlink->ch_layout.nb_channels, sizeof(double));
356         if (!s->bands[i].attack_rate || !s->bands[i].decay_rate || !s->bands[i].volume)
357             return AVERROR(ENOMEM);
358 
359         for (k = 0; k < FFMIN(nb_attacks / 2, outlink->ch_layout.nb_channels); k++) {
360             char *tstr3 = av_strtok(p3, ",", &saveptr3);
361 
362             p3 = NULL;
363             sscanf(tstr3, "%lf", &s->bands[i].attack_rate[k]);
364             tstr3 = av_strtok(p3, ",", &saveptr3);
365             sscanf(tstr3, "%lf", &s->bands[i].decay_rate[k]);
366 
367             if (s->bands[i].attack_rate[k] > 1.0 / outlink->sample_rate) {
368                 s->bands[i].attack_rate[k] = 1.0 - exp(-1.0 / (outlink->sample_rate * s->bands[i].attack_rate[k]));
369             } else {
370                 s->bands[i].attack_rate[k] = 1.0;
371             }
372 
373             if (s->bands[i].decay_rate[k] > 1.0 / outlink->sample_rate) {
374                 s->bands[i].decay_rate[k] = 1.0 - exp(-1.0 / (outlink->sample_rate * s->bands[i].decay_rate[k]));
375             } else {
376                 s->bands[i].decay_rate[k] = 1.0;
377             }
378         }
379 
380         for (ch = k; ch < outlink->ch_layout.nb_channels; ch++) {
381             s->bands[i].attack_rate[ch] = s->bands[i].attack_rate[k - 1];
382             s->bands[i].decay_rate[ch]  = s->bands[i].decay_rate[k - 1];
383         }
384 
385         tstr2 = av_strtok(p2, " ", &saveptr2);
386         if (!tstr2) {
387             av_log(ctx, AV_LOG_ERROR, "transfer function curve in dB must be set\n");
388             return AVERROR(EINVAL);
389         }
390         sscanf(tstr2, "%lf", &s->bands[i].transfer_fn.curve_dB);
391 
392         radius = s->bands[i].transfer_fn.curve_dB * M_LN10 / 20.0;
393 
394         tstr2 = av_strtok(p2, " ", &saveptr2);
395         if (!tstr2) {
396             av_log(ctx, AV_LOG_ERROR, "transfer points missing\n");
397             return AVERROR(EINVAL);
398         }
399 
400         count_items(tstr2, &nb_points, ',');
401         s->bands[i].transfer_fn.nb_segments = (nb_points + 4) * 2;
402         s->bands[i].transfer_fn.segments = av_calloc(s->bands[i].transfer_fn.nb_segments,
403                                                      sizeof(CompandSegment));
404         if (!s->bands[i].transfer_fn.segments)
405             return AVERROR(ENOMEM);
406 
407         ret = parse_points(tstr2, nb_points, radius, &s->bands[i].transfer_fn, ctx);
408         if (ret < 0) {
409             av_log(ctx, AV_LOG_ERROR, "transfer points parsing failed\n");
410             return ret;
411         }
412 
413         tstr2 = av_strtok(p2, " ", &saveptr2);
414         if (!tstr2) {
415             av_log(ctx, AV_LOG_ERROR, "crossover_frequency is missing\n");
416             return AVERROR(EINVAL);
417         }
418 
419         new_nb_items += sscanf(tstr2, "%lf", &s->bands[i].topfreq) == 1;
420         if (s->bands[i].topfreq < 0 || s->bands[i].topfreq >= outlink->sample_rate / 2) {
421             av_log(ctx, AV_LOG_ERROR, "crossover_frequency: %f, should be >=0 and lower than half of sample rate: %d.\n", s->bands[i].topfreq, outlink->sample_rate / 2);
422             return AVERROR(EINVAL);
423         }
424 
425         if (s->bands[i].topfreq != 0) {
426             ret = crossover_setup(outlink, &s->bands[i].filter, s->bands[i].topfreq);
427             if (ret < 0)
428                 return ret;
429         }
430 
431         tstr2 = av_strtok(p2, " ", &saveptr2);
432         if (tstr2) {
433             sscanf(tstr2, "%lf", &s->bands[i].delay);
434             max_delay_size = FFMAX(max_delay_size, s->bands[i].delay * outlink->sample_rate);
435 
436             tstr2 = av_strtok(p2, " ", &saveptr2);
437             if (tstr2) {
438                 double initial_volume;
439 
440                 sscanf(tstr2, "%lf", &initial_volume);
441                 initial_volume = pow(10.0, initial_volume / 20);
442 
443                 for (k = 0; k < outlink->ch_layout.nb_channels; k++) {
444                     s->bands[i].volume[k] = initial_volume;
445                 }
446 
447                 tstr2 = av_strtok(p2, " ", &saveptr2);
448                 if (tstr2) {
449                     sscanf(tstr2, "%lf", &s->bands[i].transfer_fn.gain_dB);
450                 }
451             }
452         }
453     }
454     s->nb_bands = new_nb_items;
455 
456     for (i = 0; max_delay_size > 0 && i < s->nb_bands; i++) {
457         s->bands[i].delay_buf = ff_get_audio_buffer(outlink, max_delay_size);
458         if (!s->bands[i].delay_buf)
459             return AVERROR(ENOMEM);
460     }
461     s->delay_buf_size = max_delay_size;
462 
463     return 0;
464 }
465 
466 #define CONVOLVE _ _ _ _
467 
crossover(int ch,Crossover * p,double * ibuf,double * obuf_low,double * obuf_high,size_t len)468 static void crossover(int ch, Crossover *p,
469                       double *ibuf, double *obuf_low,
470                       double *obuf_high, size_t len)
471 {
472     double out_low, out_high;
473 
474     while (len--) {
475         p->pos = p->pos ? p->pos - 1 : N - 1;
476 #define _ out_low += p->coefs[j] * p->previous[ch][p->pos + j].in \
477             - p->coefs[2*N+2 + j] * p->previous[ch][p->pos + j].out_low, j++;
478         {
479             int j = 1;
480             out_low = p->coefs[0] * *ibuf;
481             CONVOLVE
482             *obuf_low++ = out_low;
483         }
484 #undef _
485 #define _ out_high += p->coefs[j+N+1] * p->previous[ch][p->pos + j].in \
486             - p->coefs[2*N+2 + j] * p->previous[ch][p->pos + j].out_high, j++;
487         {
488             int j = 1;
489             out_high = p->coefs[N+1] * *ibuf;
490             CONVOLVE
491             *obuf_high++ = out_high;
492         }
493         p->previous[ch][p->pos + N].in = p->previous[ch][p->pos].in = *ibuf++;
494         p->previous[ch][p->pos + N].out_low = p->previous[ch][p->pos].out_low = out_low;
495         p->previous[ch][p->pos + N].out_high = p->previous[ch][p->pos].out_high = out_high;
496     }
497 }
498 
mcompand_channel(MCompandContext * c,CompBand * l,double * ibuf,double * obuf,int len,int ch)499 static int mcompand_channel(MCompandContext *c, CompBand *l, double *ibuf, double *obuf, int len, int ch)
500 {
501     int i;
502 
503     for (i = 0; i < len; i++) {
504         double level_in_lin, level_out_lin, checkbuf;
505         /* Maintain the volume fields by simulating a leaky pump circuit */
506         update_volume(l, fabs(ibuf[i]), ch);
507 
508         /* Volume memory is updated: perform compand */
509         level_in_lin = l->volume[ch];
510         level_out_lin = get_volume(&l->transfer_fn, level_in_lin);
511 
512         if (c->delay_buf_size <= 0) {
513             checkbuf = ibuf[i] * level_out_lin;
514             obuf[i] = checkbuf;
515         } else {
516             double *delay_buf = (double *)l->delay_buf->extended_data[ch];
517 
518             /* FIXME: note that this lookahead algorithm is really lame:
519                the response to a peak is released before the peak
520                arrives. */
521 
522             /* because volume application delays differ band to band, but
523                total delay doesn't, the volume is applied in an iteration
524                preceding that in which the sample goes to obuf, except in
525                the band(s) with the longest vol app delay.
526 
527                the offset between delay_buf_ptr and the sample to apply
528                vol to, is a constant equal to the difference between this
529                band's delay and the longest delay of all the bands. */
530 
531             if (l->delay_buf_cnt >= l->delay_size) {
532                 checkbuf =
533                     delay_buf[(l->delay_buf_ptr +
534                                c->delay_buf_size -
535                                l->delay_size) % c->delay_buf_size] * level_out_lin;
536                 delay_buf[(l->delay_buf_ptr + c->delay_buf_size -
537                            l->delay_size) % c->delay_buf_size] = checkbuf;
538             }
539             if (l->delay_buf_cnt >= c->delay_buf_size) {
540                 obuf[i] = delay_buf[l->delay_buf_ptr];
541             } else {
542                 l->delay_buf_cnt++;
543             }
544             delay_buf[l->delay_buf_ptr++] = ibuf[i];
545             l->delay_buf_ptr %= c->delay_buf_size;
546         }
547     }
548 
549     return 0;
550 }
551 
filter_frame(AVFilterLink * inlink,AVFrame * in)552 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
553 {
554     AVFilterContext  *ctx = inlink->dst;
555     AVFilterLink *outlink = ctx->outputs[0];
556     MCompandContext *s    = ctx->priv;
557     AVFrame *out, *abuf, *bbuf, *cbuf;
558     int ch, band, i;
559 
560     out = ff_get_audio_buffer(outlink, in->nb_samples);
561     if (!out) {
562         av_frame_free(&in);
563         return AVERROR(ENOMEM);
564     }
565 
566     if (s->band_samples < in->nb_samples) {
567         av_frame_free(&s->band_buf1);
568         av_frame_free(&s->band_buf2);
569         av_frame_free(&s->band_buf3);
570 
571         s->band_buf1 = ff_get_audio_buffer(outlink, in->nb_samples);
572         s->band_buf2 = ff_get_audio_buffer(outlink, in->nb_samples);
573         s->band_buf3 = ff_get_audio_buffer(outlink, in->nb_samples);
574         s->band_samples = in->nb_samples;
575     }
576 
577     for (ch = 0; ch < outlink->ch_layout.nb_channels; ch++) {
578         double *a, *dst = (double *)out->extended_data[ch];
579 
580         for (band = 0, abuf = in, bbuf = s->band_buf2, cbuf = s->band_buf1; band < s->nb_bands; band++) {
581             CompBand *b = &s->bands[band];
582 
583             if (b->topfreq) {
584                 crossover(ch, &b->filter, (double *)abuf->extended_data[ch],
585                           (double *)bbuf->extended_data[ch], (double *)cbuf->extended_data[ch], in->nb_samples);
586             } else {
587                 bbuf = abuf;
588                 abuf = cbuf;
589             }
590 
591             if (abuf == in)
592                 abuf = s->band_buf3;
593             mcompand_channel(s, b, (double *)bbuf->extended_data[ch], (double *)abuf->extended_data[ch], out->nb_samples, ch);
594             a = (double *)abuf->extended_data[ch];
595             for (i = 0; i < out->nb_samples; i++) {
596                 dst[i] += a[i];
597             }
598 
599             FFSWAP(AVFrame *, abuf, cbuf);
600         }
601     }
602 
603     out->pts = in->pts;
604     av_frame_free(&in);
605     return ff_filter_frame(outlink, out);
606 }
607 
request_frame(AVFilterLink * outlink)608 static int request_frame(AVFilterLink *outlink)
609 {
610     AVFilterContext *ctx = outlink->src;
611     int ret;
612 
613     ret = ff_request_frame(ctx->inputs[0]);
614 
615     return ret;
616 }
617 
618 static const AVFilterPad mcompand_inputs[] = {
619     {
620         .name           = "default",
621         .type           = AVMEDIA_TYPE_AUDIO,
622         .filter_frame   = filter_frame,
623     },
624 };
625 
626 static const AVFilterPad mcompand_outputs[] = {
627     {
628         .name          = "default",
629         .type          = AVMEDIA_TYPE_AUDIO,
630         .request_frame = request_frame,
631         .config_props  = config_output,
632     },
633 };
634 
635 
636 const AVFilter ff_af_mcompand = {
637     .name           = "mcompand",
638     .description    = NULL_IF_CONFIG_SMALL(
639             "Multiband Compress or expand audio dynamic range."),
640     .priv_size      = sizeof(MCompandContext),
641     .priv_class     = &mcompand_class,
642     .uninit         = uninit,
643     FILTER_INPUTS(mcompand_inputs),
644     FILTER_OUTPUTS(mcompand_outputs),
645     FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP),
646 };
647