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.

254 lines
9.0KB

  1. /*
  2. * Copyright (c) 2015 Kyle Swanson <k@ylo.ph>.
  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/opt.h"
  21. #include "audio.h"
  22. #include "avfilter.h"
  23. #include "internal.h"
  24. #include "libavutil/lfg.h"
  25. #include "libavutil/random_seed.h"
  26. typedef struct ANoiseSrcContext {
  27. const AVClass *class;
  28. int sample_rate;
  29. double amplitude;
  30. int64_t duration;
  31. int color;
  32. int64_t seed;
  33. int nb_samples;
  34. int64_t pts;
  35. int infinite;
  36. double (*filter)(double white, double *buf, double half_amplitude);
  37. double buf[7];
  38. AVLFG c;
  39. } ANoiseSrcContext;
  40. enum NoiseMode {
  41. NM_WHITE,
  42. NM_PINK,
  43. NM_BROWN,
  44. NM_BLUE,
  45. NM_VIOLET,
  46. NM_VELVET,
  47. NM_NB
  48. };
  49. #define OFFSET(x) offsetof(ANoiseSrcContext, x)
  50. #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  51. static const AVOption anoisesrc_options[] = {
  52. { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 15, INT_MAX, FLAGS },
  53. { "r", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 15, INT_MAX, FLAGS },
  54. { "amplitude", "set amplitude", OFFSET(amplitude), AV_OPT_TYPE_DOUBLE, {.dbl = 1.}, 0., 1., FLAGS },
  55. { "a", "set amplitude", OFFSET(amplitude), AV_OPT_TYPE_DOUBLE, {.dbl = 1.}, 0., 1., FLAGS },
  56. { "duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS },
  57. { "d", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS },
  58. { "color", "set noise color", OFFSET(color), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NM_NB - 1, FLAGS, "color" },
  59. { "colour", "set noise color", OFFSET(color), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NM_NB - 1, FLAGS, "color" },
  60. { "c", "set noise color", OFFSET(color), AV_OPT_TYPE_INT, {.i64 = 0}, 0, NM_NB - 1, FLAGS, "color" },
  61. { "white", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_WHITE}, 0, 0, FLAGS, "color" },
  62. { "pink", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_PINK}, 0, 0, FLAGS, "color" },
  63. { "brown", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_BROWN}, 0, 0, FLAGS, "color" },
  64. { "blue", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_BLUE}, 0, 0, FLAGS, "color" },
  65. { "violet", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_VIOLET}, 0, 0, FLAGS, "color" },
  66. { "velvet", 0, 0, AV_OPT_TYPE_CONST, {.i64 = NM_VELVET}, 0, 0, FLAGS, "color" },
  67. { "seed", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT_MAX, FLAGS },
  68. { "s", "set random seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT_MAX, FLAGS },
  69. { "nb_samples", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
  70. { "n", "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, FLAGS },
  71. {NULL}
  72. };
  73. AVFILTER_DEFINE_CLASS(anoisesrc);
  74. static av_cold int query_formats(AVFilterContext *ctx)
  75. {
  76. ANoiseSrcContext *s = ctx->priv;
  77. static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 };
  78. int sample_rates[] = { s->sample_rate, -1 };
  79. static const enum AVSampleFormat sample_fmts[] = {
  80. AV_SAMPLE_FMT_DBL,
  81. AV_SAMPLE_FMT_NONE
  82. };
  83. AVFilterFormats *formats;
  84. AVFilterChannelLayouts *layouts;
  85. int ret;
  86. formats = ff_make_format_list(sample_fmts);
  87. if (!formats)
  88. return AVERROR(ENOMEM);
  89. ret = ff_set_common_formats (ctx, formats);
  90. if (ret < 0)
  91. return ret;
  92. layouts = avfilter_make_format64_list(chlayouts);
  93. if (!layouts)
  94. return AVERROR(ENOMEM);
  95. ret = ff_set_common_channel_layouts(ctx, layouts);
  96. if (ret < 0)
  97. return ret;
  98. formats = ff_make_format_list(sample_rates);
  99. if (!formats)
  100. return AVERROR(ENOMEM);
  101. return ff_set_common_samplerates(ctx, formats);
  102. }
  103. static double white_filter(double white, double *buf, double ha)
  104. {
  105. return white;
  106. }
  107. static double pink_filter(double white, double *buf, double ha)
  108. {
  109. double pink;
  110. /* http://www.musicdsp.org/files/pink.txt */
  111. buf[0] = 0.99886 * buf[0] + white * 0.0555179;
  112. buf[1] = 0.99332 * buf[1] + white * 0.0750759;
  113. buf[2] = 0.96900 * buf[2] + white * 0.1538520;
  114. buf[3] = 0.86650 * buf[3] + white * 0.3104856;
  115. buf[4] = 0.55000 * buf[4] + white * 0.5329522;
  116. buf[5] = -0.7616 * buf[5] - white * 0.0168980;
  117. pink = buf[0] + buf[1] + buf[2] + buf[3] + buf[4] + buf[5] + buf[6] + white * 0.5362;
  118. buf[6] = white * 0.115926;
  119. return pink * 0.11;
  120. }
  121. static double blue_filter(double white, double *buf, double ha)
  122. {
  123. double blue;
  124. /* Same as pink_filter but subtract the offsets rather than add */
  125. buf[0] = 0.0555179 * white - 0.99886 * buf[0];
  126. buf[1] = 0.0750759 * white - 0.99332 * buf[1];
  127. buf[2] = 0.1538520 * white - 0.96900 * buf[2];
  128. buf[3] = 0.3104856 * white - 0.86650 * buf[3];
  129. buf[4] = 0.5329522 * white - 0.55000 * buf[4];
  130. buf[5] = -0.016898 * white + 0.76160 * buf[5];
  131. blue = buf[0] + buf[1] + buf[2] + buf[3] + buf[4] + buf[5] + buf[6] + white * 0.5362;
  132. buf[6] = white * 0.115926;
  133. return blue * 0.11;
  134. }
  135. static double brown_filter(double white, double *buf, double ha)
  136. {
  137. double brown;
  138. brown = ((0.02 * white) + buf[0]) / 1.02;
  139. buf[0] = brown;
  140. return brown * 3.5;
  141. }
  142. static double violet_filter(double white, double *buf, double ha)
  143. {
  144. double violet;
  145. violet = ((0.02 * white) - buf[0]) / 1.02;
  146. buf[0] = violet;
  147. return violet * 3.5;
  148. }
  149. static double velvet_filter(double white, double *buf, double ha)
  150. {
  151. return 2. * ha * ((white > ha) - (white < -ha));
  152. }
  153. static av_cold int config_props(AVFilterLink *outlink)
  154. {
  155. AVFilterContext *ctx = outlink->src;
  156. ANoiseSrcContext *s = ctx->priv;
  157. if (s->seed == -1)
  158. s->seed = av_get_random_seed();
  159. av_lfg_init(&s->c, s->seed);
  160. if (s->duration == 0)
  161. s->infinite = 1;
  162. s->duration = av_rescale(s->duration, s->sample_rate, AV_TIME_BASE);
  163. switch (s->color) {
  164. case NM_WHITE: s->filter = white_filter; break;
  165. case NM_PINK: s->filter = pink_filter; break;
  166. case NM_BROWN: s->filter = brown_filter; break;
  167. case NM_BLUE: s->filter = blue_filter; break;
  168. case NM_VIOLET: s->filter = violet_filter; break;
  169. case NM_VELVET: s->filter = velvet_filter; break;
  170. }
  171. return 0;
  172. }
  173. static int request_frame(AVFilterLink *outlink)
  174. {
  175. AVFilterContext *ctx = outlink->src;
  176. ANoiseSrcContext *s = ctx->priv;
  177. AVFrame *frame;
  178. int nb_samples, i;
  179. double *dst;
  180. if (!s->infinite && s->duration <= 0) {
  181. return AVERROR_EOF;
  182. } else if (!s->infinite && s->duration < s->nb_samples) {
  183. nb_samples = s->duration;
  184. } else {
  185. nb_samples = s->nb_samples;
  186. }
  187. if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
  188. return AVERROR(ENOMEM);
  189. dst = (double *)frame->data[0];
  190. for (i = 0; i < nb_samples; i++) {
  191. double white;
  192. white = s->amplitude * ((2 * ((double) av_lfg_get(&s->c) / 0xffffffff)) - 1);
  193. dst[i] = s->filter(white, s->buf, s->amplitude * 0.5);
  194. }
  195. if (!s->infinite)
  196. s->duration -= nb_samples;
  197. frame->pts = s->pts;
  198. s->pts += nb_samples;
  199. return ff_filter_frame(outlink, frame);
  200. }
  201. static const AVFilterPad anoisesrc_outputs[] = {
  202. {
  203. .name = "default",
  204. .type = AVMEDIA_TYPE_AUDIO,
  205. .request_frame = request_frame,
  206. .config_props = config_props,
  207. },
  208. { NULL }
  209. };
  210. AVFilter ff_asrc_anoisesrc = {
  211. .name = "anoisesrc",
  212. .description = NULL_IF_CONFIG_SMALL("Generate a noise audio signal."),
  213. .query_formats = query_formats,
  214. .priv_size = sizeof(ANoiseSrcContext),
  215. .inputs = NULL,
  216. .outputs = anoisesrc_outputs,
  217. .priv_class = &anoisesrc_class,
  218. };