af_acrusher.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright (c) Markus Schmidt and Christian Holschuh
  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
  8. * License 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 GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include "libavutil/opt.h"
  21. #include "avfilter.h"
  22. #include "internal.h"
  23. #include "audio.h"
  24. typedef struct LFOContext {
  25. double freq;
  26. double offset;
  27. int srate;
  28. double amount;
  29. double pwidth;
  30. double phase;
  31. } LFOContext;
  32. typedef struct SRContext {
  33. double target;
  34. double real;
  35. double samples;
  36. double last;
  37. } SRContext;
  38. typedef struct ACrusherContext {
  39. const AVClass *class;
  40. double level_in;
  41. double level_out;
  42. double bits;
  43. double mix;
  44. int mode;
  45. double dc;
  46. double idc;
  47. double aa;
  48. double samples;
  49. int is_lfo;
  50. double lforange;
  51. double lforate;
  52. double sqr;
  53. double aa1;
  54. double coeff;
  55. int round;
  56. double sov;
  57. double smin;
  58. double sdiff;
  59. LFOContext lfo;
  60. SRContext *sr;
  61. } ACrusherContext;
  62. #define OFFSET(x) offsetof(ACrusherContext, x)
  63. #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
  64. static const AVOption acrusher_options[] = {
  65. { "level_in", "set level in", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A },
  66. { "level_out","set level out", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A },
  67. { "bits", "set bit reduction", OFFSET(bits), AV_OPT_TYPE_DOUBLE, {.dbl=8}, 1, 64, A },
  68. { "mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=.5}, 0, 1, A },
  69. { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A, "mode" },
  70. { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A, "mode" },
  71. { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A, "mode" },
  72. { "dc", "set DC", OFFSET(dc), AV_OPT_TYPE_DOUBLE, {.dbl=1}, .25, 4, A },
  73. { "aa", "set anti-aliasing", OFFSET(aa), AV_OPT_TYPE_DOUBLE, {.dbl=.5}, 0, 1, A },
  74. { "samples", "set sample reduction", OFFSET(samples), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 250, A },
  75. { "lfo", "enable LFO", OFFSET(is_lfo), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A },
  76. { "lforange", "set LFO depth", OFFSET(lforange), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 250, A },
  77. { "lforate", "set LFO rate", OFFSET(lforate), AV_OPT_TYPE_DOUBLE, {.dbl=.3}, .01, 200, A },
  78. { NULL }
  79. };
  80. AVFILTER_DEFINE_CLASS(acrusher);
  81. static double samplereduction(ACrusherContext *s, SRContext *sr, double in)
  82. {
  83. sr->samples++;
  84. if (sr->samples >= s->round) {
  85. sr->target += s->samples;
  86. sr->real += s->round;
  87. if (sr->target + s->samples >= sr->real + 1) {
  88. sr->last = in;
  89. sr->target = 0;
  90. sr->real = 0;
  91. }
  92. sr->samples = 0;
  93. }
  94. return sr->last;
  95. }
  96. static double add_dc(double s, double dc, double idc)
  97. {
  98. return s > 0 ? s * dc : s * idc;
  99. }
  100. static double remove_dc(double s, double dc, double idc)
  101. {
  102. return s > 0 ? s * idc : s * dc;
  103. }
  104. static inline double factor(double y, double k, double aa1, double aa)
  105. {
  106. return 0.5 * (sin(M_PI * (fabs(y - k) - aa1) / aa - M_PI_2) + 1);
  107. }
  108. static double bitreduction(ACrusherContext *s, double in)
  109. {
  110. const double sqr = s->sqr;
  111. const double coeff = s->coeff;
  112. const double aa = s->aa;
  113. const double aa1 = s->aa1;
  114. double y, k;
  115. // add dc
  116. in = add_dc(in, s->dc, s->idc);
  117. // main rounding calculation depending on mode
  118. // the idea for anti-aliasing:
  119. // you need a function f which brings you to the scale, where
  120. // you want to round and the function f_b (with f(f_b)=id) which
  121. // brings you back to your original scale.
  122. //
  123. // then you can use the logic below in the following way:
  124. // y = f(in) and k = roundf(y)
  125. // if (y > k + aa1)
  126. // k = f_b(k) + ( f_b(k+1) - f_b(k) ) * 0.5 * (sin(x - PI/2) + 1)
  127. // if (y < k + aa1)
  128. // k = f_b(k) - ( f_b(k+1) - f_b(k) ) * 0.5 * (sin(x - PI/2) + 1)
  129. //
  130. // whereas x = (fabs(f(in) - k) - aa1) * PI / aa
  131. // for both cases.
  132. switch (s->mode) {
  133. case 0:
  134. default:
  135. // linear
  136. y = in * coeff;
  137. k = roundf(y);
  138. if (k - aa1 <= y && y <= k + aa1) {
  139. k /= coeff;
  140. } else if (y > k + aa1) {
  141. k = k / coeff + ((k + 1) / coeff - k / coeff) *
  142. factor(y, k, aa1, aa);
  143. } else {
  144. k = k / coeff - (k / coeff - (k - 1) / coeff) *
  145. factor(y, k, aa1, aa);
  146. }
  147. break;
  148. case 1:
  149. // logarithmic
  150. y = sqr * log(fabs(in)) + sqr * sqr;
  151. k = roundf(y);
  152. if(!in) {
  153. k = 0;
  154. } else if (k - aa1 <= y && y <= k + aa1) {
  155. k = in / fabs(in) * exp(k / sqr - sqr);
  156. } else if (y > k + aa1) {
  157. double x = exp(k / sqr - sqr);
  158. k = FFSIGN(in) * (x + (exp((k + 1) / sqr - sqr) - x) *
  159. factor(y, k, aa1, aa));
  160. } else {
  161. double x = exp(k / sqr - sqr);
  162. k = in / fabs(in) * (x - (x - exp((k - 1) / sqr - sqr)) *
  163. factor(y, k, aa1, aa));
  164. }
  165. break;
  166. }
  167. // mix between dry and wet signal
  168. k += (in - k) * s->mix;
  169. // remove dc
  170. k = remove_dc(k, s->dc, s->idc);
  171. return k;
  172. }
  173. static double lfo_get(LFOContext *lfo)
  174. {
  175. double phs = FFMIN(100., lfo->phase / FFMIN(1.99, FFMAX(0.01, lfo->pwidth)) + lfo->offset);
  176. double val;
  177. if (phs > 1)
  178. phs = fmod(phs, 1.);
  179. val = sin((phs * 360.) * M_PI / 180);
  180. return val * lfo->amount;
  181. }
  182. static void lfo_advance(LFOContext *lfo, unsigned count)
  183. {
  184. lfo->phase = fabs(lfo->phase + count * lfo->freq * (1. / lfo->srate));
  185. if (lfo->phase >= 1.)
  186. lfo->phase = fmod(lfo->phase, 1.);
  187. }
  188. static int filter_frame(AVFilterLink *inlink, AVFrame *in)
  189. {
  190. AVFilterContext *ctx = inlink->dst;
  191. ACrusherContext *s = ctx->priv;
  192. AVFilterLink *outlink = ctx->outputs[0];
  193. AVFrame *out;
  194. const double *src = (const double *)in->data[0];
  195. double *dst;
  196. const double level_in = s->level_in;
  197. const double level_out = s->level_out;
  198. const double mix = s->mix;
  199. int n, c;
  200. if (av_frame_is_writable(in)) {
  201. out = in;
  202. } else {
  203. out = ff_get_audio_buffer(inlink, in->nb_samples);
  204. if (!out) {
  205. av_frame_free(&in);
  206. return AVERROR(ENOMEM);
  207. }
  208. av_frame_copy_props(out, in);
  209. }
  210. dst = (double *)out->data[0];
  211. for (n = 0; n < in->nb_samples; n++) {
  212. if (s->is_lfo) {
  213. s->samples = s->smin + s->sdiff * (lfo_get(&s->lfo) + 0.5);
  214. s->round = round(s->samples);
  215. }
  216. for (c = 0; c < inlink->channels; c++) {
  217. double sample = src[c] * level_in;
  218. sample = mix * samplereduction(s, &s->sr[c], sample) + src[c] * (1. - mix) * level_in;
  219. dst[c] = bitreduction(s, sample) * level_out;
  220. }
  221. src += c;
  222. dst += c;
  223. if (s->is_lfo)
  224. lfo_advance(&s->lfo, 1);
  225. }
  226. if (in != out)
  227. av_frame_free(&in);
  228. return ff_filter_frame(outlink, out);
  229. }
  230. static int query_formats(AVFilterContext *ctx)
  231. {
  232. AVFilterFormats *formats;
  233. AVFilterChannelLayouts *layouts;
  234. static const enum AVSampleFormat sample_fmts[] = {
  235. AV_SAMPLE_FMT_DBL,
  236. AV_SAMPLE_FMT_NONE
  237. };
  238. int ret;
  239. layouts = ff_all_channel_counts();
  240. if (!layouts)
  241. return AVERROR(ENOMEM);
  242. ret = ff_set_common_channel_layouts(ctx, layouts);
  243. if (ret < 0)
  244. return ret;
  245. formats = ff_make_format_list(sample_fmts);
  246. if (!formats)
  247. return AVERROR(ENOMEM);
  248. ret = ff_set_common_formats(ctx, formats);
  249. if (ret < 0)
  250. return ret;
  251. formats = ff_all_samplerates();
  252. if (!formats)
  253. return AVERROR(ENOMEM);
  254. return ff_set_common_samplerates(ctx, formats);
  255. }
  256. static av_cold void uninit(AVFilterContext *ctx)
  257. {
  258. ACrusherContext *s = ctx->priv;
  259. av_freep(&s->sr);
  260. }
  261. static int config_input(AVFilterLink *inlink)
  262. {
  263. AVFilterContext *ctx = inlink->dst;
  264. ACrusherContext *s = ctx->priv;
  265. double rad, sunder, smax, sover;
  266. s->idc = 1. / s->dc;
  267. s->coeff = exp2(s->bits) - 1;
  268. s->sqr = sqrt(s->coeff / 2);
  269. s->aa1 = (1. - s->aa) / 2.;
  270. s->round = round(s->samples);
  271. rad = s->lforange / 2.;
  272. s->smin = FFMAX(s->samples - rad, 1.);
  273. sunder = s->samples - rad - s->smin;
  274. smax = FFMIN(s->samples + rad, 250.);
  275. sover = s->samples + rad - smax;
  276. smax -= sunder;
  277. s->smin -= sover;
  278. s->sdiff = smax - s->smin;
  279. s->lfo.freq = s->lforate;
  280. s->lfo.pwidth = 1.;
  281. s->lfo.srate = inlink->sample_rate;
  282. s->lfo.amount = .5;
  283. s->sr = av_calloc(inlink->channels, sizeof(*s->sr));
  284. if (!s->sr)
  285. return AVERROR(ENOMEM);
  286. return 0;
  287. }
  288. static const AVFilterPad avfilter_af_acrusher_inputs[] = {
  289. {
  290. .name = "default",
  291. .type = AVMEDIA_TYPE_AUDIO,
  292. .config_props = config_input,
  293. .filter_frame = filter_frame,
  294. },
  295. { NULL }
  296. };
  297. static const AVFilterPad avfilter_af_acrusher_outputs[] = {
  298. {
  299. .name = "default",
  300. .type = AVMEDIA_TYPE_AUDIO,
  301. },
  302. { NULL }
  303. };
  304. AVFilter ff_af_acrusher = {
  305. .name = "acrusher",
  306. .description = NULL_IF_CONFIG_SMALL("Reduce audio bit resolution."),
  307. .priv_size = sizeof(ACrusherContext),
  308. .priv_class = &acrusher_class,
  309. .uninit = uninit,
  310. .query_formats = query_formats,
  311. .inputs = avfilter_af_acrusher_inputs,
  312. .outputs = avfilter_af_acrusher_outputs,
  313. };