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.

331 lines
12KB

  1. /*
  2. * Copyright (c) 2020 Paul B Mahol
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public License
  8. * as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "libavutil/eval.h"
  21. #include "libavutil/opt.h"
  22. #include "libavutil/tx.h"
  23. #include "audio.h"
  24. #include "avfilter.h"
  25. #include "internal.h"
  26. #include "window_func.h"
  27. typedef struct AudioFIRSourceContext {
  28. const AVClass *class;
  29. char *freq_points_str;
  30. char *magnitude_str;
  31. char *phase_str;
  32. int nb_taps;
  33. int sample_rate;
  34. int nb_samples;
  35. int win_func;
  36. AVComplexFloat *complexf;
  37. float *freq;
  38. float *magnitude;
  39. float *phase;
  40. int freq_size;
  41. int magnitude_size;
  42. int phase_size;
  43. int nb_freq;
  44. int nb_magnitude;
  45. int nb_phase;
  46. float *taps;
  47. float *win;
  48. int64_t pts;
  49. AVTXContext *tx_ctx;
  50. av_tx_fn tx_fn;
  51. } AudioFIRSourceContext;
  52. #define OFFSET(x) offsetof(AudioFIRSourceContext, x)
  53. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  54. static const AVOption afirsrc_options[] = {
  55. { "taps", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS },
  56. { "t", "set number of taps", OFFSET(nb_taps), AV_OPT_TYPE_INT, {.i64=1025}, 9, UINT16_MAX, FLAGS },
  57. { "frequency", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS },
  58. { "f", "set frequency points", OFFSET(freq_points_str), AV_OPT_TYPE_STRING, {.str="0 1"}, 0, 0, FLAGS },
  59. { "magnitude", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS },
  60. { "m", "set magnitude values", OFFSET(magnitude_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, FLAGS },
  61. { "phase", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS },
  62. { "p", "set phase values", OFFSET(phase_str), AV_OPT_TYPE_STRING, {.str="0 0"}, 0, 0, FLAGS },
  63. { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
  64. { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100}, 1, INT_MAX, FLAGS },
  65. { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
  66. { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
  67. { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_BLACKMAN}, 0, NB_WFUNC-1, FLAGS, "win_func" },
  68. { "w", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_BLACKMAN}, 0, NB_WFUNC-1, FLAGS, "win_func" },
  69. { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" },
  70. { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" },
  71. { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, FLAGS, "win_func" },
  72. { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, FLAGS, "win_func" },
  73. { "blackman", "Blackman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BLACKMAN}, 0, 0, FLAGS, "win_func" },
  74. { "welch", "Welch", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_WELCH}, 0, 0, FLAGS, "win_func" },
  75. { "flattop", "Flat-top", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_FLATTOP}, 0, 0, FLAGS, "win_func" },
  76. { "bharris", "Blackman-Harris", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHARRIS}, 0, 0, FLAGS, "win_func" },
  77. { "bnuttall", "Blackman-Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BNUTTALL}, 0, 0, FLAGS, "win_func" },
  78. { "bhann", "Bartlett-Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHANN}, 0, 0, FLAGS, "win_func" },
  79. { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, FLAGS, "win_func" },
  80. { "nuttall", "Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_NUTTALL}, 0, 0, FLAGS, "win_func" },
  81. { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_LANCZOS}, 0, 0, FLAGS, "win_func" },
  82. { "gauss", "Gauss", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_GAUSS}, 0, 0, FLAGS, "win_func" },
  83. { "tukey", "Tukey", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_TUKEY}, 0, 0, FLAGS, "win_func" },
  84. { "dolph", "Dolph-Chebyshev", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_DOLPH}, 0, 0, FLAGS, "win_func" },
  85. { "cauchy", "Cauchy", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_CAUCHY}, 0, 0, FLAGS, "win_func" },
  86. { "parzen", "Parzen", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_PARZEN}, 0, 0, FLAGS, "win_func" },
  87. { "poisson", "Poisson", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_POISSON}, 0, 0, FLAGS, "win_func" },
  88. { "bohman" , "Bohman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BOHMAN}, 0, 0, FLAGS, "win_func" },
  89. {NULL}
  90. };
  91. AVFILTER_DEFINE_CLASS(afirsrc);
  92. static av_cold int init(AVFilterContext *ctx)
  93. {
  94. AudioFIRSourceContext *s = ctx->priv;
  95. if (!(s->nb_taps & 1)) {
  96. av_log(s, AV_LOG_WARNING, "Number of taps %d must be odd length.\n", s->nb_taps);
  97. s->nb_taps |= 1;
  98. }
  99. return 0;
  100. }
  101. static av_cold void uninit(AVFilterContext *ctx)
  102. {
  103. AudioFIRSourceContext *s = ctx->priv;
  104. av_freep(&s->win);
  105. av_freep(&s->taps);
  106. av_freep(&s->freq);
  107. av_freep(&s->magnitude);
  108. av_freep(&s->phase);
  109. av_freep(&s->complexf);
  110. av_tx_uninit(&s->tx_ctx);
  111. }
  112. static av_cold int query_formats(AVFilterContext *ctx)
  113. {
  114. AudioFIRSourceContext *s = ctx->priv;
  115. static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 };
  116. int sample_rates[] = { s->sample_rate, -1 };
  117. static const enum AVSampleFormat sample_fmts[] = {
  118. AV_SAMPLE_FMT_FLT,
  119. AV_SAMPLE_FMT_NONE
  120. };
  121. AVFilterFormats *formats;
  122. AVFilterChannelLayouts *layouts;
  123. int ret;
  124. formats = ff_make_format_list(sample_fmts);
  125. if (!formats)
  126. return AVERROR(ENOMEM);
  127. ret = ff_set_common_formats (ctx, formats);
  128. if (ret < 0)
  129. return ret;
  130. layouts = ff_make_format64_list(chlayouts);
  131. if (!layouts)
  132. return AVERROR(ENOMEM);
  133. ret = ff_set_common_channel_layouts(ctx, layouts);
  134. if (ret < 0)
  135. return ret;
  136. formats = ff_make_format_list(sample_rates);
  137. if (!formats)
  138. return AVERROR(ENOMEM);
  139. return ff_set_common_samplerates(ctx, formats);
  140. }
  141. static int parse_string(char *str, float **items, int *nb_items, int *items_size)
  142. {
  143. float *new_items;
  144. char *tail;
  145. new_items = av_fast_realloc(NULL, items_size, 1 * sizeof(float));
  146. if (!new_items)
  147. return AVERROR(ENOMEM);
  148. *items = new_items;
  149. tail = str;
  150. if (!tail)
  151. return AVERROR(EINVAL);
  152. do {
  153. (*items)[(*nb_items)++] = av_strtod(tail, &tail);
  154. new_items = av_fast_realloc(*items, items_size, (*nb_items + 1) * sizeof(float));
  155. if (!new_items)
  156. return AVERROR(ENOMEM);
  157. *items = new_items;
  158. if (tail && *tail)
  159. tail++;
  160. } while (tail && *tail);
  161. return 0;
  162. }
  163. static void lininterp(AVComplexFloat *complexf,
  164. const float *freq,
  165. const float *magnitude,
  166. const float *phase,
  167. int m, int minterp)
  168. {
  169. for (int i = 0; i < minterp; i++) {
  170. for (int j = 1; j < m; j++) {
  171. const float x = i / (float)minterp;
  172. if (x <= freq[j]) {
  173. const float mg = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (magnitude[j] - magnitude[j-1]) + magnitude[j-1];
  174. const float ph = (x - freq[j-1]) / (freq[j] - freq[j-1]) * (phase[j] - phase[j-1]) + phase[j-1];
  175. complexf[i].re = mg * cosf(ph);
  176. complexf[i].im = mg * sinf(ph);
  177. break;
  178. }
  179. }
  180. }
  181. }
  182. static av_cold int config_output(AVFilterLink *outlink)
  183. {
  184. AVFilterContext *ctx = outlink->src;
  185. AudioFIRSourceContext *s = ctx->priv;
  186. float overlap, scale = 1.f, compensation;
  187. int fft_size, middle, ret;
  188. s->nb_freq = s->nb_magnitude = s->nb_phase = 0;
  189. ret = parse_string(s->freq_points_str, &s->freq, &s->nb_freq, &s->freq_size);
  190. if (ret < 0)
  191. return ret;
  192. ret = parse_string(s->magnitude_str, &s->magnitude, &s->nb_magnitude, &s->magnitude_size);
  193. if (ret < 0)
  194. return ret;
  195. ret = parse_string(s->phase_str, &s->phase, &s->nb_phase, &s->phase_size);
  196. if (ret < 0)
  197. return ret;
  198. if (s->nb_freq != s->nb_magnitude && s->nb_freq != s->nb_phase && s->nb_freq >= 2) {
  199. av_log(ctx, AV_LOG_ERROR, "Number of frequencies, magnitudes and phases must be same and >= 2.\n");
  200. return AVERROR(EINVAL);
  201. }
  202. for (int i = 0; i < s->nb_freq; i++) {
  203. if (i == 0 && s->freq[i] != 0.f) {
  204. av_log(ctx, AV_LOG_ERROR, "First frequency must be 0.\n");
  205. return AVERROR(EINVAL);
  206. }
  207. if (i == s->nb_freq - 1 && s->freq[i] != 1.f) {
  208. av_log(ctx, AV_LOG_ERROR, "Last frequency must be 1.\n");
  209. return AVERROR(EINVAL);
  210. }
  211. if (i && s->freq[i] < s->freq[i-1]) {
  212. av_log(ctx, AV_LOG_ERROR, "Frequencies must be in increasing order.\n");
  213. return AVERROR(EINVAL);
  214. }
  215. }
  216. fft_size = 1 << (av_log2(s->nb_taps) + 1);
  217. s->complexf = av_calloc(fft_size * 2, sizeof(*s->complexf));
  218. if (!s->complexf)
  219. return AVERROR(ENOMEM);
  220. ret = av_tx_init(&s->tx_ctx, &s->tx_fn, AV_TX_FLOAT_FFT, 1, fft_size, &scale, 0);
  221. if (ret < 0)
  222. return ret;
  223. s->taps = av_calloc(s->nb_taps, sizeof(*s->taps));
  224. if (!s->taps)
  225. return AVERROR(ENOMEM);
  226. s->win = av_calloc(s->nb_taps, sizeof(*s->win));
  227. if (!s->win)
  228. return AVERROR(ENOMEM);
  229. generate_window_func(s->win, s->nb_taps, s->win_func, &overlap);
  230. lininterp(s->complexf, s->freq, s->magnitude, s->phase, s->nb_freq, fft_size / 2);
  231. s->tx_fn(s->tx_ctx, s->complexf + fft_size, s->complexf, sizeof(float));
  232. compensation = 2.f / fft_size;
  233. middle = s->nb_taps / 2;
  234. for (int i = 0; i <= middle; i++) {
  235. s->taps[ i] = s->complexf[fft_size + middle - i].re * compensation * s->win[i];
  236. s->taps[middle + i] = s->complexf[fft_size + i].re * compensation * s->win[middle + i];
  237. }
  238. s->pts = 0;
  239. return 0;
  240. }
  241. static int request_frame(AVFilterLink *outlink)
  242. {
  243. AVFilterContext *ctx = outlink->src;
  244. AudioFIRSourceContext *s = ctx->priv;
  245. AVFrame *frame;
  246. int nb_samples;
  247. nb_samples = FFMIN(s->nb_samples, s->nb_taps - s->pts);
  248. if (!nb_samples)
  249. return AVERROR_EOF;
  250. if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
  251. return AVERROR(ENOMEM);
  252. memcpy(frame->data[0], s->taps + s->pts, nb_samples * sizeof(float));
  253. frame->pts = s->pts;
  254. s->pts += nb_samples;
  255. return ff_filter_frame(outlink, frame);
  256. }
  257. static const AVFilterPad afirsrc_outputs[] = {
  258. {
  259. .name = "default",
  260. .type = AVMEDIA_TYPE_AUDIO,
  261. .request_frame = request_frame,
  262. .config_props = config_output,
  263. },
  264. { NULL }
  265. };
  266. AVFilter ff_asrc_afirsrc = {
  267. .name = "afirsrc",
  268. .description = NULL_IF_CONFIG_SMALL("Generate a FIR coefficients audio stream."),
  269. .query_formats = query_formats,
  270. .init = init,
  271. .uninit = uninit,
  272. .priv_size = sizeof(AudioFIRSourceContext),
  273. .inputs = NULL,
  274. .outputs = afirsrc_outputs,
  275. .priv_class = &afirsrc_class,
  276. };