You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

449 lines
16KB

  1. /*
  2. * Copyright (c) 2005 Boðaç Topaktaþ
  3. * Copyright (c) 2020 Paul B Mahol
  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. #include "libavutil/channel_layout.h"
  22. #include "libavutil/ffmath.h"
  23. #include "libavutil/opt.h"
  24. #include "avfilter.h"
  25. #include "audio.h"
  26. #include "formats.h"
  27. typedef struct BiquadCoeffs {
  28. double a1, a2;
  29. double b0, b1, b2;
  30. } BiquadCoeffs;
  31. typedef struct ASuperCutContext {
  32. const AVClass *class;
  33. double cutoff;
  34. double level;
  35. double qfactor;
  36. int order;
  37. int filter_count;
  38. int bypass;
  39. BiquadCoeffs coeffs[10];
  40. AVFrame *w;
  41. int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
  42. } ASuperCutContext;
  43. static int query_formats(AVFilterContext *ctx)
  44. {
  45. AVFilterFormats *formats = NULL;
  46. AVFilterChannelLayouts *layouts = NULL;
  47. static const enum AVSampleFormat sample_fmts[] = {
  48. AV_SAMPLE_FMT_FLTP,
  49. AV_SAMPLE_FMT_DBLP,
  50. AV_SAMPLE_FMT_NONE
  51. };
  52. int ret;
  53. formats = ff_make_format_list(sample_fmts);
  54. if (!formats)
  55. return AVERROR(ENOMEM);
  56. ret = ff_set_common_formats(ctx, formats);
  57. if (ret < 0)
  58. return ret;
  59. layouts = ff_all_channel_counts();
  60. if (!layouts)
  61. return AVERROR(ENOMEM);
  62. ret = ff_set_common_channel_layouts(ctx, layouts);
  63. if (ret < 0)
  64. return ret;
  65. formats = ff_all_samplerates();
  66. return ff_set_common_samplerates(ctx, formats);
  67. }
  68. static void calc_q_factors(int n, double *q)
  69. {
  70. for (int i = 0; i < n / 2; i++)
  71. q[i] = 1. / (-2. * cos(M_PI * (2. * (i + 1) + n - 1.) / (2. * n)));
  72. }
  73. static int get_coeffs(AVFilterContext *ctx)
  74. {
  75. ASuperCutContext *s = ctx->priv;
  76. AVFilterLink *inlink = ctx->inputs[0];
  77. double w0 = s->cutoff / inlink->sample_rate;
  78. double K = tan(M_PI * w0);
  79. double q[10];
  80. s->bypass = w0 >= 0.5;
  81. if (s->bypass)
  82. return 0;
  83. if (!strcmp(ctx->filter->name, "asubcut")) {
  84. s->filter_count = s->order / 2 + (s->order & 1);
  85. calc_q_factors(s->order, q);
  86. if (s->order & 1) {
  87. BiquadCoeffs *coeffs = &s->coeffs[0];
  88. double omega = 2. * tan(M_PI * w0);
  89. coeffs->b0 = 2. / (2. + omega);
  90. coeffs->b1 = -coeffs->b0;
  91. coeffs->b2 = 0.;
  92. coeffs->a1 = -(omega - 2.) / (2. + omega);
  93. coeffs->a2 = 0.;
  94. }
  95. for (int b = (s->order & 1); b < s->filter_count; b++) {
  96. BiquadCoeffs *coeffs = &s->coeffs[b];
  97. const int idx = b - (s->order & 1);
  98. double norm = 1.0 / (1.0 + K / q[idx] + K * K);
  99. coeffs->b0 = norm;
  100. coeffs->b1 = -2.0 * coeffs->b0;
  101. coeffs->b2 = coeffs->b0;
  102. coeffs->a1 = -2.0 * (K * K - 1.0) * norm;
  103. coeffs->a2 = -(1.0 - K / q[idx] + K * K) * norm;
  104. }
  105. } else if (!strcmp(ctx->filter->name, "asupercut")) {
  106. s->filter_count = s->order / 2 + (s->order & 1);
  107. calc_q_factors(s->order, q);
  108. if (s->order & 1) {
  109. BiquadCoeffs *coeffs = &s->coeffs[0];
  110. double omega = 2. * tan(M_PI * w0);
  111. coeffs->b0 = omega / (2. + omega);
  112. coeffs->b1 = coeffs->b0;
  113. coeffs->b2 = 0.;
  114. coeffs->a1 = -(omega - 2.) / (2. + omega);
  115. coeffs->a2 = 0.;
  116. }
  117. for (int b = (s->order & 1); b < s->filter_count; b++) {
  118. BiquadCoeffs *coeffs = &s->coeffs[b];
  119. const int idx = b - (s->order & 1);
  120. double norm = 1.0 / (1.0 + K / q[idx] + K * K);
  121. coeffs->b0 = K * K * norm;
  122. coeffs->b1 = 2.0 * coeffs->b0;
  123. coeffs->b2 = coeffs->b0;
  124. coeffs->a1 = -2.0 * (K * K - 1.0) * norm;
  125. coeffs->a2 = -(1.0 - K / q[idx] + K * K) * norm;
  126. }
  127. } else if (!strcmp(ctx->filter->name, "asuperpass")) {
  128. double alpha, beta, gamma, theta;
  129. double theta_0 = 2. * M_PI * (s->cutoff / inlink->sample_rate);
  130. double d_E;
  131. s->filter_count = s->order / 2;
  132. d_E = (2. * tan(theta_0 / (2. * s->qfactor))) / sin(theta_0);
  133. for (int b = 0; b < s->filter_count; b += 2) {
  134. double D = 2. * sin(((b + 1) * M_PI) / (2. * s->filter_count));
  135. double A = (1. + pow((d_E / 2.), 2)) / (D * d_E / 2.);
  136. double d = sqrt((d_E * D) / (A + sqrt(A * A - 1.)));
  137. double B = D * (d_E / 2.) / d;
  138. double W = B + sqrt(B * B - 1.);
  139. for (int j = 0; j < 2; j++) {
  140. BiquadCoeffs *coeffs = &s->coeffs[b + j];
  141. if (j == 1)
  142. theta = 2. * atan(tan(theta_0 / 2.) / W);
  143. else
  144. theta = 2. * atan(W * tan(theta_0 / 2.));
  145. beta = 0.5 * ((1. - (d / 2.) * sin(theta)) / (1. + (d / 2.) * sin(theta)));
  146. gamma = (0.5 + beta) * cos(theta);
  147. alpha = 0.5 * (0.5 - beta) * sqrt(1. + pow((W - (1. / W)) / d, 2.));
  148. coeffs->a1 = 2. * gamma;
  149. coeffs->a2 = -2. * beta;
  150. coeffs->b0 = 2. * alpha;
  151. coeffs->b1 = 0.;
  152. coeffs->b2 = -2. * alpha;
  153. }
  154. }
  155. } else if (!strcmp(ctx->filter->name, "asuperstop")) {
  156. double alpha, beta, gamma, theta;
  157. double theta_0 = 2. * M_PI * (s->cutoff / inlink->sample_rate);
  158. double d_E;
  159. s->filter_count = s->order / 2;
  160. d_E = (2. * tan(theta_0 / (2. * s->qfactor))) / sin(theta_0);
  161. for (int b = 0; b < s->filter_count; b += 2) {
  162. double D = 2. * sin(((b + 1) * M_PI) / (2. * s->filter_count));
  163. double A = (1. + pow((d_E / 2.), 2)) / (D * d_E / 2.);
  164. double d = sqrt((d_E * D) / (A + sqrt(A * A - 1.)));
  165. double B = D * (d_E / 2.) / d;
  166. double W = B + sqrt(B * B - 1.);
  167. for (int j = 0; j < 2; j++) {
  168. BiquadCoeffs *coeffs = &s->coeffs[b + j];
  169. if (j == 1)
  170. theta = 2. * atan(tan(theta_0 / 2.) / W);
  171. else
  172. theta = 2. * atan(W * tan(theta_0 / 2.));
  173. beta = 0.5 * ((1. - (d / 2.) * sin(theta)) / (1. + (d / 2.) * sin(theta)));
  174. gamma = (0.5 + beta) * cos(theta);
  175. alpha = 0.5 * (0.5 + beta) * ((1. - cos(theta)) / (1. - cos(theta_0)));
  176. coeffs->a1 = 2. * gamma;
  177. coeffs->a2 = -2. * beta;
  178. coeffs->b0 = 2. * alpha;
  179. coeffs->b1 = -4. * alpha * cos(theta_0);
  180. coeffs->b2 = 2. * alpha;
  181. }
  182. }
  183. }
  184. return 0;
  185. }
  186. typedef struct ThreadData {
  187. AVFrame *in, *out;
  188. } ThreadData;
  189. #define FILTER(name, type) \
  190. static int filter_channels_## name(AVFilterContext *ctx, void *arg, \
  191. int jobnr, int nb_jobs) \
  192. { \
  193. ASuperCutContext *s = ctx->priv; \
  194. ThreadData *td = arg; \
  195. AVFrame *out = td->out; \
  196. AVFrame *in = td->in; \
  197. const int start = (in->channels * jobnr) / nb_jobs; \
  198. const int end = (in->channels * (jobnr+1)) / nb_jobs; \
  199. const double level = s->level; \
  200. \
  201. for (int ch = start; ch < end; ch++) { \
  202. const type *src = (const type *)in->extended_data[ch]; \
  203. type *dst = (type *)out->extended_data[ch]; \
  204. \
  205. for (int b = 0; b < s->filter_count; b++) { \
  206. BiquadCoeffs *coeffs = &s->coeffs[b]; \
  207. const type a1 = coeffs->a1; \
  208. const type a2 = coeffs->a2; \
  209. const type b0 = coeffs->b0; \
  210. const type b1 = coeffs->b1; \
  211. const type b2 = coeffs->b2; \
  212. type *w = ((type *)s->w->extended_data[ch]) + b * 2; \
  213. \
  214. for (int n = 0; n < in->nb_samples; n++) { \
  215. type sin = b ? dst[n] : src[n] * level; \
  216. type sout = sin * b0 + w[0]; \
  217. \
  218. w[0] = b1 * sin + w[1] + a1 * sout; \
  219. w[1] = b2 * sin + a2 * sout; \
  220. \
  221. dst[n] = sout; \
  222. } \
  223. } \
  224. } \
  225. \
  226. return 0; \
  227. }
  228. FILTER(fltp, float)
  229. FILTER(dblp, double)
  230. static int config_input(AVFilterLink *inlink)
  231. {
  232. AVFilterContext *ctx = inlink->dst;
  233. ASuperCutContext *s = ctx->priv;
  234. switch (inlink->format) {
  235. case AV_SAMPLE_FMT_FLTP: s->filter_channels = filter_channels_fltp; break;
  236. case AV_SAMPLE_FMT_DBLP: s->filter_channels = filter_channels_dblp; break;
  237. }
  238. s->w = ff_get_audio_buffer(inlink, 2 * 10);
  239. if (!s->w)
  240. return AVERROR(ENOMEM);
  241. return get_coeffs(ctx);
  242. }
  243. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  244. {
  245. AVFilterContext *ctx = inlink->dst;
  246. ASuperCutContext *s = ctx->priv;
  247. AVFilterLink *outlink = ctx->outputs[0];
  248. ThreadData td;
  249. AVFrame *out;
  250. if (s->bypass)
  251. return ff_filter_frame(outlink, in);
  252. if (av_frame_is_writable(in)) {
  253. out = in;
  254. } else {
  255. out = ff_get_audio_buffer(outlink, in->nb_samples);
  256. if (!out) {
  257. av_frame_free(&in);
  258. return AVERROR(ENOMEM);
  259. }
  260. av_frame_copy_props(out, in);
  261. }
  262. td.in = in; td.out = out;
  263. ctx->internal->execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels,
  264. ff_filter_get_nb_threads(ctx)));
  265. if (out != in)
  266. av_frame_free(&in);
  267. return ff_filter_frame(outlink, out);
  268. }
  269. static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
  270. char *res, int res_len, int flags)
  271. {
  272. int ret;
  273. ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
  274. if (ret < 0)
  275. return ret;
  276. return get_coeffs(ctx);
  277. }
  278. static av_cold void uninit(AVFilterContext *ctx)
  279. {
  280. ASuperCutContext *s = ctx->priv;
  281. av_frame_free(&s->w);
  282. }
  283. #define OFFSET(x) offsetof(ASuperCutContext, x)
  284. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
  285. static const AVOption asupercut_options[] = {
  286. { "cutoff", "set cutoff frequency", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=20000}, 20000, 192000, FLAGS },
  287. { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=10}, 3, 20, FLAGS },
  288. { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 1., FLAGS },
  289. { NULL }
  290. };
  291. AVFILTER_DEFINE_CLASS(asupercut);
  292. static const AVFilterPad inputs[] = {
  293. {
  294. .name = "default",
  295. .type = AVMEDIA_TYPE_AUDIO,
  296. .filter_frame = filter_frame,
  297. .config_props = config_input,
  298. },
  299. { NULL }
  300. };
  301. static const AVFilterPad outputs[] = {
  302. {
  303. .name = "default",
  304. .type = AVMEDIA_TYPE_AUDIO,
  305. },
  306. { NULL }
  307. };
  308. AVFilter ff_af_asupercut = {
  309. .name = "asupercut",
  310. .description = NULL_IF_CONFIG_SMALL("Cut super frequencies."),
  311. .query_formats = query_formats,
  312. .priv_size = sizeof(ASuperCutContext),
  313. .priv_class = &asupercut_class,
  314. .uninit = uninit,
  315. .inputs = inputs,
  316. .outputs = outputs,
  317. .process_command = process_command,
  318. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
  319. AVFILTER_FLAG_SLICE_THREADS,
  320. };
  321. static const AVOption asubcut_options[] = {
  322. { "cutoff", "set cutoff frequency", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 2, 200, FLAGS },
  323. { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=10}, 3, 20, FLAGS },
  324. { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 1., FLAGS },
  325. { NULL }
  326. };
  327. AVFILTER_DEFINE_CLASS(asubcut);
  328. AVFilter ff_af_asubcut = {
  329. .name = "asubcut",
  330. .description = NULL_IF_CONFIG_SMALL("Cut subwoofer frequencies."),
  331. .query_formats = query_formats,
  332. .priv_size = sizeof(ASuperCutContext),
  333. .priv_class = &asubcut_class,
  334. .uninit = uninit,
  335. .inputs = inputs,
  336. .outputs = outputs,
  337. .process_command = process_command,
  338. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
  339. AVFILTER_FLAG_SLICE_THREADS,
  340. };
  341. static const AVOption asuperpass_asuperstop_options[] = {
  342. { "centerf","set center frequency", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 2, 999999, FLAGS },
  343. { "order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=4}, 4, 20, FLAGS },
  344. { "qfactor","set Q-factor", OFFSET(qfactor),AV_OPT_TYPE_DOUBLE, {.dbl=1.},0.01, 100., FLAGS },
  345. { "level", "set input level", OFFSET(level), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0., 2., FLAGS },
  346. { NULL }
  347. };
  348. #define asuperpass_options asuperpass_asuperstop_options
  349. AVFILTER_DEFINE_CLASS(asuperpass);
  350. AVFilter ff_af_asuperpass = {
  351. .name = "asuperpass",
  352. .description = NULL_IF_CONFIG_SMALL("Apply high order Butterworth band-pass filter."),
  353. .query_formats = query_formats,
  354. .priv_size = sizeof(ASuperCutContext),
  355. .priv_class = &asuperpass_class,
  356. .uninit = uninit,
  357. .inputs = inputs,
  358. .outputs = outputs,
  359. .process_command = process_command,
  360. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
  361. AVFILTER_FLAG_SLICE_THREADS,
  362. };
  363. #define asuperstop_options asuperpass_asuperstop_options
  364. AVFILTER_DEFINE_CLASS(asuperstop);
  365. AVFilter ff_af_asuperstop = {
  366. .name = "asuperstop",
  367. .description = NULL_IF_CONFIG_SMALL("Apply high order Butterworth band-stop filter."),
  368. .query_formats = query_formats,
  369. .priv_size = sizeof(ASuperCutContext),
  370. .priv_class = &asuperstop_class,
  371. .uninit = uninit,
  372. .inputs = inputs,
  373. .outputs = outputs,
  374. .process_command = process_command,
  375. .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC |
  376. AVFILTER_FLAG_SLICE_THREADS,
  377. };