• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Paul B Mahol
3  * Copyright (c) Laurent de Soras, 2005
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/channel_layout.h"
23 #include "libavutil/ffmath.h"
24 #include "libavutil/opt.h"
25 #include "avfilter.h"
26 #include "audio.h"
27 #include "formats.h"
28 
29 #define MAX_NB_COEFFS 16
30 
31 typedef struct AFreqShift {
32     const AVClass *class;
33 
34     double shift;
35     double level;
36     int nb_coeffs;
37     int old_nb_coeffs;
38 
39     double cd[MAX_NB_COEFFS * 2];
40     float cf[MAX_NB_COEFFS * 2];
41 
42     int64_t in_samples;
43 
44     AVFrame *i1, *o1;
45     AVFrame *i2, *o2;
46 
47     void (*filter_channel)(AVFilterContext *ctx,
48                            int channel,
49                            AVFrame *in, AVFrame *out);
50 } AFreqShift;
51 
52 static const enum AVSampleFormat sample_fmts[] = {
53     AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE
54 };
55 
56 #define PFILTER(name, type, sin, cos, cc)                     \
57 static void pfilter_channel_## name(AVFilterContext *ctx,     \
58                             int ch,                           \
59                             AVFrame *in, AVFrame *out)        \
60 {                                                             \
61     AFreqShift *s = ctx->priv;                                \
62     const int nb_samples = in->nb_samples;                    \
63     const type *src = (const type *)in->extended_data[ch];    \
64     type *dst = (type *)out->extended_data[ch];               \
65     type *i1 = (type *)s->i1->extended_data[ch];              \
66     type *o1 = (type *)s->o1->extended_data[ch];              \
67     type *i2 = (type *)s->i2->extended_data[ch];              \
68     type *o2 = (type *)s->o2->extended_data[ch];              \
69     const type *c = s->cc;                                    \
70     const type level = s->level;                              \
71     type shift = s->shift * M_PI;                             \
72     type cos_theta = cos(shift);                              \
73     type sin_theta = sin(shift);                              \
74                                                               \
75     for (int n = 0; n < nb_samples; n++) {                    \
76         type xn1 = src[n], xn2 = src[n];                      \
77         type I, Q;                                            \
78                                                               \
79         for (int j = 0; j < s->nb_coeffs; j++) {              \
80             I = c[j] * (xn1 + o2[j]) - i2[j];                 \
81             i2[j] = i1[j];                                    \
82             i1[j] = xn1;                                      \
83             o2[j] = o1[j];                                    \
84             o1[j] = I;                                        \
85             xn1 = I;                                          \
86         }                                                     \
87                                                               \
88         for (int j = s->nb_coeffs; j < s->nb_coeffs*2; j++) { \
89             Q = c[j] * (xn2 + o2[j]) - i2[j];                 \
90             i2[j] = i1[j];                                    \
91             i1[j] = xn2;                                      \
92             o2[j] = o1[j];                                    \
93             o1[j] = Q;                                        \
94             xn2 = Q;                                          \
95         }                                                     \
96         Q = o2[s->nb_coeffs * 2 - 1];                         \
97                                                               \
98         dst[n] = (I * cos_theta - Q * sin_theta) * level;     \
99     }                                                         \
100 }
101 
PFILTER(flt,float,sin,cos,cf)102 PFILTER(flt, float, sin, cos, cf)
103 PFILTER(dbl, double, sin, cos, cd)
104 
105 #define FFILTER(name, type, sin, cos, fmod, cc)               \
106 static void ffilter_channel_## name(AVFilterContext *ctx,     \
107                             int ch,                           \
108                             AVFrame *in, AVFrame *out)        \
109 {                                                             \
110     AFreqShift *s = ctx->priv;                                \
111     const int nb_samples = in->nb_samples;                    \
112     const type *src = (const type *)in->extended_data[ch];    \
113     type *dst = (type *)out->extended_data[ch];               \
114     type *i1 = (type *)s->i1->extended_data[ch];              \
115     type *o1 = (type *)s->o1->extended_data[ch];              \
116     type *i2 = (type *)s->i2->extended_data[ch];              \
117     type *o2 = (type *)s->o2->extended_data[ch];              \
118     const type *c = s->cc;                                    \
119     const type level = s->level;                              \
120     type ts = 1. / in->sample_rate;                           \
121     type shift = s->shift;                                    \
122     int64_t N = s->in_samples;                                \
123                                                               \
124     for (int n = 0; n < nb_samples; n++) {                    \
125         type xn1 = src[n], xn2 = src[n];                      \
126         type I, Q, theta;                                     \
127                                                               \
128         for (int j = 0; j < s->nb_coeffs; j++) {              \
129             I = c[j] * (xn1 + o2[j]) - i2[j];                 \
130             i2[j] = i1[j];                                    \
131             i1[j] = xn1;                                      \
132             o2[j] = o1[j];                                    \
133             o1[j] = I;                                        \
134             xn1 = I;                                          \
135         }                                                     \
136                                                               \
137         for (int j = s->nb_coeffs; j < s->nb_coeffs*2; j++) { \
138             Q = c[j] * (xn2 + o2[j]) - i2[j];                 \
139             i2[j] = i1[j];                                    \
140             i1[j] = xn2;                                      \
141             o2[j] = o1[j];                                    \
142             o1[j] = Q;                                        \
143             xn2 = Q;                                          \
144         }                                                     \
145         Q = o2[s->nb_coeffs * 2 - 1];                         \
146                                                               \
147         theta = 2. * M_PI * fmod(shift * (N + n) * ts, 1.);   \
148         dst[n] = (I * cos(theta) - Q * sin(theta)) * level;   \
149     }                                                         \
150 }
151 
152 FFILTER(flt, float, sinf, cosf, fmodf, cf)
153 FFILTER(dbl, double, sin, cos, fmod, cd)
154 
155 static void compute_transition_param(double *K, double *Q, double transition)
156 {
157     double kksqrt, e, e2, e4, k, q;
158 
159     k  = tan((1. - transition * 2.) * M_PI / 4.);
160     k *= k;
161     kksqrt = pow(1 - k * k, 0.25);
162     e = 0.5 * (1. - kksqrt) / (1. + kksqrt);
163     e2 = e * e;
164     e4 = e2 * e2;
165     q = e * (1. + e4 * (2. + e4 * (15. + 150. * e4)));
166 
167     *Q = q;
168     *K = k;
169 }
170 
ipowp(double x,int64_t n)171 static double ipowp(double x, int64_t n)
172 {
173     double z = 1.;
174 
175     while (n != 0) {
176         if (n & 1)
177             z *= x;
178         n >>= 1;
179         x *= x;
180     }
181 
182     return z;
183 }
184 
compute_acc_num(double q,int order,int c)185 static double compute_acc_num(double q, int order, int c)
186 {
187     int64_t i = 0;
188     int j = 1;
189     double acc = 0.;
190     double q_ii1;
191 
192     do {
193         q_ii1  = ipowp(q, i * (i + 1));
194         q_ii1 *= sin((i * 2 + 1) * c * M_PI / order) * j;
195         acc   += q_ii1;
196 
197         j = -j;
198         i++;
199     } while (fabs(q_ii1) > 1e-100);
200 
201     return acc;
202 }
203 
compute_acc_den(double q,int order,int c)204 static double compute_acc_den(double q, int order, int c)
205 {
206     int64_t i = 1;
207     int j = -1;
208     double acc = 0.;
209     double q_i2;
210 
211     do {
212         q_i2  = ipowp(q, i * i);
213         q_i2 *= cos(i * 2 * c * M_PI / order) * j;
214         acc  += q_i2;
215 
216         j = -j;
217         i++;
218     } while (fabs(q_i2) > 1e-100);
219 
220     return acc;
221 }
222 
compute_coef(int index,double k,double q,int order)223 static double compute_coef(int index, double k, double q, int order)
224 {
225     const int    c    = index + 1;
226     const double num  = compute_acc_num(q, order, c) * pow(q, 0.25);
227     const double den  = compute_acc_den(q, order, c) + 0.5;
228     const double ww   = num / den;
229     const double wwsq = ww * ww;
230 
231     const double x    = sqrt((1 - wwsq * k) * (1 - wwsq / k)) / (1 + wwsq);
232     const double coef = (1 - x) / (1 + x);
233 
234     return coef;
235 }
236 
compute_coefs(double * coef_arrd,float * coef_arrf,int nbr_coefs,double transition)237 static void compute_coefs(double *coef_arrd, float *coef_arrf, int nbr_coefs, double transition)
238 {
239     const int order = nbr_coefs * 2 + 1;
240     double k, q;
241 
242     compute_transition_param(&k, &q, transition);
243 
244     for (int n = 0; n < nbr_coefs; n++) {
245         const int idx = (n / 2) + (n & 1) * nbr_coefs / 2;
246 
247         coef_arrd[idx] = compute_coef(n, k, q, order);
248         coef_arrf[idx] = coef_arrd[idx];
249     }
250 }
251 
config_input(AVFilterLink * inlink)252 static int config_input(AVFilterLink *inlink)
253 {
254     AVFilterContext *ctx = inlink->dst;
255     AFreqShift *s = ctx->priv;
256 
257     if (s->old_nb_coeffs != s->nb_coeffs)
258         compute_coefs(s->cd, s->cf, s->nb_coeffs * 2, 2. * 20. / inlink->sample_rate);
259     s->old_nb_coeffs = s->nb_coeffs;
260 
261     s->i1 = ff_get_audio_buffer(inlink, MAX_NB_COEFFS * 2);
262     s->o1 = ff_get_audio_buffer(inlink, MAX_NB_COEFFS * 2);
263     s->i2 = ff_get_audio_buffer(inlink, MAX_NB_COEFFS * 2);
264     s->o2 = ff_get_audio_buffer(inlink, MAX_NB_COEFFS * 2);
265     if (!s->i1 || !s->o1 || !s->i2 || !s->o2)
266         return AVERROR(ENOMEM);
267 
268     if (inlink->format == AV_SAMPLE_FMT_DBLP) {
269         if (!strcmp(ctx->filter->name, "afreqshift"))
270             s->filter_channel = ffilter_channel_dbl;
271         else
272             s->filter_channel = pfilter_channel_dbl;
273     } else {
274         if (!strcmp(ctx->filter->name, "afreqshift"))
275             s->filter_channel = ffilter_channel_flt;
276         else
277             s->filter_channel = pfilter_channel_flt;
278     }
279 
280     return 0;
281 }
282 
283 typedef struct ThreadData {
284     AVFrame *in, *out;
285 } ThreadData;
286 
filter_channels(AVFilterContext * ctx,void * arg,int jobnr,int nb_jobs)287 static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
288 {
289     AFreqShift *s = ctx->priv;
290     ThreadData *td = arg;
291     AVFrame *out = td->out;
292     AVFrame *in = td->in;
293     const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
294     const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
295 
296     for (int ch = start; ch < end; ch++)
297         s->filter_channel(ctx, ch, in, out);
298 
299     return 0;
300 }
301 
filter_frame(AVFilterLink * inlink,AVFrame * in)302 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
303 {
304     AVFilterContext *ctx = inlink->dst;
305     AVFilterLink *outlink = ctx->outputs[0];
306     AFreqShift *s = ctx->priv;
307     AVFrame *out;
308     ThreadData td;
309 
310     if (s->old_nb_coeffs != s->nb_coeffs)
311         compute_coefs(s->cd, s->cf, s->nb_coeffs * 2, 2. * 20. / inlink->sample_rate);
312     s->old_nb_coeffs = s->nb_coeffs;
313 
314     if (av_frame_is_writable(in)) {
315         out = in;
316     } else {
317         out = ff_get_audio_buffer(outlink, in->nb_samples);
318         if (!out) {
319             av_frame_free(&in);
320             return AVERROR(ENOMEM);
321         }
322         av_frame_copy_props(out, in);
323     }
324 
325     td.in = in; td.out = out;
326     ff_filter_execute(ctx, filter_channels, &td, NULL,
327                       FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx)));
328 
329     s->in_samples += in->nb_samples;
330 
331     if (out != in)
332         av_frame_free(&in);
333     return ff_filter_frame(outlink, out);
334 }
335 
uninit(AVFilterContext * ctx)336 static av_cold void uninit(AVFilterContext *ctx)
337 {
338     AFreqShift *s = ctx->priv;
339 
340     av_frame_free(&s->i1);
341     av_frame_free(&s->o1);
342     av_frame_free(&s->i2);
343     av_frame_free(&s->o2);
344 }
345 
346 #define OFFSET(x) offsetof(AFreqShift, x)
347 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
348 
349 static const AVOption afreqshift_options[] = {
350     { "shift", "set frequency shift", OFFSET(shift), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -INT_MAX, INT_MAX, FLAGS },
351     { "level", "set output level",    OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1},      0.0,     1.0, FLAGS },
352     { "order", "set filter order",    OFFSET(nb_coeffs),AV_OPT_TYPE_INT, {.i64=8},  1, MAX_NB_COEFFS, FLAGS },
353     { NULL }
354 };
355 
356 AVFILTER_DEFINE_CLASS(afreqshift);
357 
358 static const AVFilterPad inputs[] = {
359     {
360         .name         = "default",
361         .type         = AVMEDIA_TYPE_AUDIO,
362         .filter_frame = filter_frame,
363         .config_props = config_input,
364     },
365 };
366 
367 static const AVFilterPad outputs[] = {
368     {
369         .name = "default",
370         .type = AVMEDIA_TYPE_AUDIO,
371     },
372 };
373 
374 const AVFilter ff_af_afreqshift = {
375     .name            = "afreqshift",
376     .description     = NULL_IF_CONFIG_SMALL("Apply frequency shifting to input audio."),
377     .priv_size       = sizeof(AFreqShift),
378     .priv_class      = &afreqshift_class,
379     .uninit          = uninit,
380     FILTER_INPUTS(inputs),
381     FILTER_OUTPUTS(outputs),
382     FILTER_SAMPLEFMTS_ARRAY(sample_fmts),
383     .process_command = ff_filter_process_command,
384     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
385                        AVFILTER_FLAG_SLICE_THREADS,
386 };
387 
388 static const AVOption aphaseshift_options[] = {
389     { "shift", "set phase shift", OFFSET(shift), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -1.0, 1.0, FLAGS },
390     { "level", "set output level",OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1},  0.0, 1.0, FLAGS },
391     { "order", "set filter order",OFFSET(nb_coeffs), AV_OPT_TYPE_INT,{.i64=8},    1, MAX_NB_COEFFS, FLAGS },
392     { NULL }
393 };
394 
395 AVFILTER_DEFINE_CLASS(aphaseshift);
396 
397 const AVFilter ff_af_aphaseshift = {
398     .name            = "aphaseshift",
399     .description     = NULL_IF_CONFIG_SMALL("Apply phase shifting to input audio."),
400     .priv_size       = sizeof(AFreqShift),
401     .priv_class      = &aphaseshift_class,
402     .uninit          = uninit,
403     FILTER_INPUTS(inputs),
404     FILTER_OUTPUTS(outputs),
405     FILTER_SAMPLEFMTS_ARRAY(sample_fmts),
406     .process_command = ff_filter_process_command,
407     .flags           = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
408                        AVFILTER_FLAG_SLICE_THREADS,
409 };
410