Signed-off-by: Paul B Mahol <one...@gmail.com> --- doc/filters.texi | 78 +++++++++++++ libavfilter/Makefile | 1 + libavfilter/af_apulsator.c | 224 +++++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + 4 files changed, 304 insertions(+)
diff --git a/doc/filters.texi b/doc/filters.texi index d19fd346ae..a8987a56c7 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2141,6 +2141,84 @@ atrim=end=5,areverse @end example @end itemize +@section aringmodulator +Apply ring modulator to input audio stream. + +Ring Modulator distorts the original signal with a LFO-generated signal - +the so called "modulator". The modulator can be altered in frequency even +by another LFO which adds some kind of modulating distortion to the signal. +A third LFO is used to modulate different aspects of the ring modulator to +create even more strange effects. + +This filter accepts the following options: +@table @option +@item level_in +Set the input gain before signal is processed. + +@item level_out +Set the output gain after signal is processed. + +@item mod_mode +Set waveform of the modulator. + +@item mod_freq +Set frequency of the modulator. + +@item mod_amount +Set amount by how much original signal is modulated. + +@item mod_phase +Shift the phase of the right channels modulator against the left channel. + +@item mod_detune +Detune the modulators frequency between left and right channel. + +@item mod_listen +Only output modulator signal. By default is disabled. + +@item lfo1_mode +Set waveform of the LFO1 modulator. + +@item lfo1_freq +Set frequency of the LFO1 modulator. + +@item lfo1_mod_freq_lo +Set the minimal modulators frequency to reach at lowest point. + +@item lfo1_mod_freq_hi +Set the maximal modulators frequency to reach at highest point. + +@item lfo1_mod_freq +Enable modulating modulators frequency by LFO1. By defauls is disabled. + +@item lfo1_mod_detune_lo +Set the minimal modulators frequency to reach at lowest point. + +@item lfo1_mod_detune_hi +Set the maximal modulators frequency to reach at highest point. + +@item lfo1_mod_detune +Enable modulating modulators frequency by LFO1. By default is disabled. + +@item lfo2_mode +Set waveform of the LFO2 modulator. + +@item lfo2_freq +Set frequency of the LFO2 modulator. + +@item lfo2_lfo1_freq +Enable modulating LFO1's frequency by LFO2. By defauls is disabled. + +@item lfo2_mod_amount +Enable modulating modulators amount by LFO2. By defauls is disabled. + +@item lfo2_mod_amount_lo +Set the minimal modulators amount to reach at LFO2 lowest point. + +@item lfo2_mod_amount_hi +Set the maximal modulators amount to reach at LFO2 highest point. +@end table + @section arnndn Reduce noise from speech using Recurrent Neural Networks. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index f982afe15f..dc512fe4b2 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -72,6 +72,7 @@ OBJS-$(CONFIG_APULSATOR_FILTER) += af_apulsator.o OBJS-$(CONFIG_AREALTIME_FILTER) += f_realtime.o OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o OBJS-$(CONFIG_AREVERSE_FILTER) += f_reverse.o +OBJS-$(CONFIG_ARINGMODULATOR_FILTER) += af_apulsator.o OBJS-$(CONFIG_ARNNDN_FILTER) += af_arnndn.o OBJS-$(CONFIG_ASELECT_FILTER) += f_select.o OBJS-$(CONFIG_ASENDCMD_FILTER) += f_sendcmd.o diff --git a/libavfilter/af_apulsator.c b/libavfilter/af_apulsator.c index 67711a28ce..9ba1d48341 100644 --- a/libavfilter/af_apulsator.c +++ b/libavfilter/af_apulsator.c @@ -255,3 +255,227 @@ AVFilter ff_af_apulsator = { .inputs = inputs, .outputs = outputs, }; + +#if CONFIG_ARINGMODULATOR_FILTER +typedef struct AudioRingModulatorContext { + const AVClass *class; + double level_in; + double level_out; + int mod_mode; + double mod_freq; + double mod_amount; + double mod_phase; + double mod_detune; + int mod_listen; + int lfo1_mode; + double lfo1_freq; + double lfo1_mod_freq_lo; + double lfo1_mod_freq_hi; + int lfo1_mod_freq_active; + int lfo2_lfo1_freq_active; + int lfo1_mod_detune_active; + double lfo1_mod_detune_lo; + double lfo1_mod_detune_hi; + int lfo2_mode; + double lfo2_freq; + double lfo2_lfo1_freq_lo; + double lfo2_lfo1_freq_hi; + int lfo2_mod_amount_active; + double lfo2_mod_amount_lo; + double lfo2_mod_amount_hi; + + SimpleLFO lfo1, lfo2, modL, modR; +} AudioRingModulatorContext; + +static int ringmodulator_config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioRingModulatorContext *s = ctx->priv; + + s->modL.freq = s->mod_freq * pow(pow(2, 1.0 / 1200.0), s->mod_detune / 2); + s->modR.freq = s->mod_freq * pow(pow(2, 1.0 / 1200.0), s->mod_detune / 2); + s->modL.mode = s->mod_mode; + s->modR.mode = s->mod_mode; + s->modL.offset = 0; + s->modR.offset = s->mod_phase; + s->modL.srate = inlink->sample_rate; + s->modR.srate = inlink->sample_rate; + s->modL.amount = s->mod_amount; + s->modR.amount = s->mod_amount; + s->modL.pwidth = 1; + s->modR.pwidth = 1; + s->lfo1.freq = s->lfo1_freq; + s->lfo2.freq = s->lfo2_freq; + s->lfo1.mode = s->lfo1_mode; + s->lfo2.mode = s->lfo2_mode; + s->lfo1.srate = inlink->sample_rate; + s->lfo2.srate = inlink->sample_rate; + s->lfo1.amount = 1; + s->lfo2.amount = 1; + s->lfo1.pwidth = 1; + s->lfo2.pwidth = 1; + + return 0; +} + +static int ringmodulator_filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioRingModulatorContext *s = ctx->priv; + const double *src = (const double *)in->data[0]; + const int nb_samples = in->nb_samples; + const double level_out = s->level_out; + const double level_in = s->level_in; + AVFrame *out; + double *dst; + int n; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(inlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + dst = (double *)out->data[0]; + + for (n = 0; n < nb_samples; n++) { + double mod_amount = s->mod_amount; + double freq = 0.; + double outL = 0.; + double outR = 0.; + double inL = src[0] * level_in; + double inR = src[1] * level_in; + double procL; + double procR; + double modulL; + double modulR; + + if (s->lfo1_mod_freq_active) { + freq = (s->lfo1_mod_freq_hi - s->lfo1_mod_freq_lo) * + ((lfo_get_value(&s->lfo1) + 1) / 2.) + + s->lfo1_mod_freq_lo; + s->modL.freq = freq; + s->modR.freq = freq; + } + + if (s->lfo1_mod_detune_active) { + double detune = (s->lfo1_mod_detune_hi - s->lfo1_mod_detune_lo) * + ((lfo_get_value(&s->lfo1) + 1) / 2.) + s->lfo1_mod_detune_lo; + + s->modL.freq = freq ? freq : s->mod_freq * pow(pow(2, 1.0 / 1200.0), detune / 2); + s->modR.freq = freq ? freq : s->mod_freq * pow(pow(2, 1.0 / 1200.0), detune / -2); + } + + if (s->lfo2_lfo1_freq_active) { + s->lfo1.freq = (s->lfo2_lfo1_freq_hi - s->lfo2_lfo1_freq_lo) * + ((lfo_get_value(&s->lfo2) + 1) / 2.) + + s->lfo2_lfo1_freq_lo; + } + + if (s->lfo2_mod_amount_active) { + mod_amount = (s->lfo2_mod_amount_hi - s->lfo2_mod_amount_lo) * + ((lfo_get_value(&s->lfo2) + 1) / 2.) + + s->lfo2_mod_amount_lo; + } + + modulL = lfo_get_value(&s->modL) * mod_amount; + modulR = lfo_get_value(&s->modR) * mod_amount; + + procL = inL * modulL; + procR = inR * modulR; + + outL = s->mod_listen ? modulL : procL + inL * (1 - mod_amount); + outR = s->mod_listen ? modulR : procR + inR * (1 - mod_amount); + + outL *= level_out; + outR *= level_out; + + dst[0] = outL; + dst[1] = outR; + + lfo_advance(&s->lfo1, 1); + lfo_advance(&s->lfo2, 1); + lfo_advance(&s->modL, 1); + lfo_advance(&s->modR, 1); + + dst += 2; + src += 2; + } + + if (in != out) + av_frame_free(&in); + + return ff_filter_frame(outlink, out); +} + +#undef OFFSET +#undef FLAGS +#define OFFSET(x) offsetof(AudioRingModulatorContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption aringmodulator_options[] = { + { "level_in", "set input gain", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, FLAGS, }, + { "level_out", "set output gain", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, FLAGS, }, + { "mod_mode", "set modulation mode", OFFSET(mod_mode), AV_OPT_TYPE_INT, {.i64=SINE}, SINE, NB_MODES-1, FLAGS, "mode" }, + { "sine", NULL, 0, AV_OPT_TYPE_CONST, {.i64=SINE}, 0, 0, FLAGS, "mode" }, + { "triangle", NULL, 0, AV_OPT_TYPE_CONST, {.i64=TRIANGLE}, 0, 0, FLAGS, "mode" }, + { "square", NULL, 0, AV_OPT_TYPE_CONST, {.i64=SQUARE}, 0, 0, FLAGS, "mode" }, + { "sawup", NULL, 0, AV_OPT_TYPE_CONST, {.i64=SAWUP}, 0, 0, FLAGS, "mode" }, + { "sawdown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=SAWDOWN}, 0, 0, FLAGS, "mode" }, + { "mod_freq", NULL, OFFSET(mod_freq), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 1, 20000, FLAGS }, + { "mod_amount", NULL, OFFSET(mod_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, FLAGS }, + { "mod_phase", NULL, OFFSET(mod_phase), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, FLAGS }, + { "mod_detune", NULL, OFFSET(mod_detune), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -200, 200, FLAGS }, + { "mod_listen", NULL, OFFSET(mod_listen), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "lfo1_mode", NULL, OFFSET(lfo1_mode), AV_OPT_TYPE_INT, {.i64=SINE}, SINE, NB_MODES-1, FLAGS, "mode" }, + { "lfo1_freq", NULL, OFFSET(lfo1_freq), AV_OPT_TYPE_DOUBLE, {.dbl=0.1}, 0.01, 10, FLAGS }, + { "lfo1_mod_freq_lo", NULL, OFFSET(lfo1_mod_freq_lo), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 1,20000, FLAGS }, + { "lfo1_mod_freq_hi", NULL, OFFSET(lfo1_mod_freq_hi), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 1,20000, FLAGS }, + { "lfo1_mod_freq", NULL, OFFSET(lfo1_mod_freq_active), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "lfo1_mod_detune_lo", NULL, OFFSET(lfo1_mod_detune_lo), AV_OPT_TYPE_DOUBLE, {.dbl=-100}, -200, 200, FLAGS }, + { "lfo1_mod_detune_hi", NULL, OFFSET(lfo1_mod_detune_hi), AV_OPT_TYPE_DOUBLE, {.dbl=100}, -200, 200, FLAGS }, + { "lfo1_mod_detune", NULL, OFFSET(lfo1_mod_detune_active), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "lfo2_mode", NULL, OFFSET(lfo2_mode), AV_OPT_TYPE_INT, {.i64=SINE}, SINE, NB_MODES-1, FLAGS, "mode" }, + { "lfo2_freq", NULL, OFFSET(lfo2_freq), AV_OPT_TYPE_DOUBLE, {.dbl=0.2}, 0.01, 10, FLAGS }, + { "lfo2_lfo1_freq", NULL, OFFSET(lfo2_lfo1_freq_active), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "lfo2_mod_amount", NULL, OFFSET(lfo2_mod_amount_active), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { "lfo2_mod_amount_lo", NULL, OFFSET(lfo2_mod_amount_lo), AV_OPT_TYPE_DOUBLE, {.dbl=0.3}, 0, 1, FLAGS }, + { "lfo2_mod_amount_hi", NULL, OFFSET(lfo2_mod_amount_hi), AV_OPT_TYPE_DOUBLE, {.dbl=0.6}, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(aringmodulator); + +static const AVFilterPad ringmodulator_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = ringmodulator_config_input, + .filter_frame = ringmodulator_filter_frame, + }, + { NULL } +}; + +static const AVFilterPad ringmodulator_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, + { NULL } +}; + +AVFilter ff_af_aringmodulator = { + .name = "aringmodulator", + .description = NULL_IF_CONFIG_SMALL("Audio Ring Modulator."), + .priv_size = sizeof(AudioRingModulatorContext), + .priv_class = åmodulator_class, + .query_formats = query_formats, + .inputs = ringmodulator_inputs, + .outputs = ringmodulator_outputs, +}; +#endif /* CONFIG_ARINGMODULATOR_FILTER */ diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 1b94501da0..6ec92181f3 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -65,6 +65,7 @@ extern AVFilter ff_af_apulsator; extern AVFilter ff_af_arealtime; extern AVFilter ff_af_aresample; extern AVFilter ff_af_areverse; +extern AVFilter ff_af_aringmodulator; extern AVFilter ff_af_arnndn; extern AVFilter ff_af_aselect; extern AVFilter ff_af_asendcmd; -- 2.17.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".