Commit 964a9bad authored by Paul B Mahol's avatar Paul B Mahol

avfilter/af_tremolo: make it bit-exact with sox effect of same name

Signed-off-by: 's avatarPaul B Mahol <onemda@gmail.com>
parent 7179add4
...@@ -85,7 +85,7 @@ OBJS-$(CONFIG_SILENCEREMOVE_FILTER) += af_silenceremove.o ...@@ -85,7 +85,7 @@ OBJS-$(CONFIG_SILENCEREMOVE_FILTER) += af_silenceremove.o
OBJS-$(CONFIG_STEREOTOOLS_FILTER) += af_stereotools.o OBJS-$(CONFIG_STEREOTOOLS_FILTER) += af_stereotools.o
OBJS-$(CONFIG_STEREOWIDEN_FILTER) += af_stereowiden.o OBJS-$(CONFIG_STEREOWIDEN_FILTER) += af_stereowiden.o
OBJS-$(CONFIG_TREBLE_FILTER) += af_biquads.o OBJS-$(CONFIG_TREBLE_FILTER) += af_biquads.o
OBJS-$(CONFIG_TREMOLO_FILTER) += af_tremolo.o generate_wave_table.o OBJS-$(CONFIG_TREMOLO_FILTER) += af_tremolo.o
OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o
OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o
......
...@@ -22,15 +22,13 @@ ...@@ -22,15 +22,13 @@
#include "avfilter.h" #include "avfilter.h"
#include "internal.h" #include "internal.h"
#include "audio.h" #include "audio.h"
#include "generate_wave_table.h"
typedef struct TremoloContext { typedef struct TremoloContext {
const AVClass *class; const AVClass *class;
double freq; double freq;
double depth; double depth;
double *wave_table; double *table;
int wave_table_index; int index;
int sample_rate;
} TremoloContext; } TremoloContext;
#define OFFSET(x) offsetof(TremoloContext, x) #define OFFSET(x) offsetof(TremoloContext, x)
...@@ -44,20 +42,11 @@ static const AVOption tremolo_options[] = { ...@@ -44,20 +42,11 @@ static const AVOption tremolo_options[] = {
AVFILTER_DEFINE_CLASS(tremolo); AVFILTER_DEFINE_CLASS(tremolo);
static double trem_env(AVFilterContext *ctx)
{
TremoloContext *s = ctx->priv;
double env = s->wave_table[s->wave_table_index];
s->wave_table_index++;
if (s->wave_table_index >= s->sample_rate / s->freq)
s->wave_table_index = 0;
return 1.0 - (s->depth * env);
}
static int filter_frame(AVFilterLink *inlink, AVFrame *in) static int filter_frame(AVFilterLink *inlink, AVFrame *in)
{ {
AVFilterContext *ctx = inlink->dst; AVFilterContext *ctx = inlink->dst;
AVFilterLink *outlink = ctx->outputs[0]; AVFilterLink *outlink = ctx->outputs[0];
TremoloContext *s = ctx->priv;
const double *src = (const double *)in->data[0]; const double *src = (const double *)in->data[0];
const int channels = inlink->channels; const int channels = inlink->channels;
const int nb_samples = in->nb_samples; const int nb_samples = in->nb_samples;
...@@ -78,12 +67,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ...@@ -78,12 +67,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
dst = (double *)out->data[0]; dst = (double *)out->data[0];
for (n = 0; n < nb_samples; n++) { for (n = 0; n < nb_samples; n++) {
const double env = trem_env(ctx);
for (c = 0; c < channels; c++) for (c = 0; c < channels; c++)
dst[c] = src[c] * env; dst[c] = src[c] * s->table[s->index];
dst += channels; dst += channels;
src += channels; src += channels;
s->index++;
if (s->index >= inlink->sample_rate)
s->index = 0;
} }
if (in != out) if (in != out)
...@@ -125,21 +115,30 @@ static int query_formats(AVFilterContext *ctx) ...@@ -125,21 +115,30 @@ static int query_formats(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx)
{ {
TremoloContext *s = ctx->priv; TremoloContext *s = ctx->priv;
av_freep(&s->wave_table); av_freep(&s->table);
} }
static int config_input(AVFilterLink *inlink) static int config_input(AVFilterLink *inlink)
{ {
AVFilterContext *ctx = inlink->dst; AVFilterContext *ctx = inlink->dst;
TremoloContext *s = ctx->priv; TremoloContext *s = ctx->priv;
const double offset = 1. - s->depth / 2.;
int i;
s->sample_rate = inlink->sample_rate; s->table = av_malloc_array(inlink->sample_rate, sizeof(*s->table));
s->wave_table = av_malloc_array(s->sample_rate / s->freq, sizeof(*s->wave_table)); if (!s->table)
if (!s->wave_table)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
ff_generate_wave_table(WAVE_SIN, AV_SAMPLE_FMT_DBL, s->wave_table, s->sample_rate / s->freq, 0.0, 1.0, 0.0); for (i = 0; i < inlink->sample_rate; i++) {
s->wave_table_index = 0; double env = s->freq * i / inlink->sample_rate;
env = sin(2 * M_PI * fmod(env + 0.25, 1.0));
s->table[i] = env * (1 - fabs(offset)) + offset;
}
s->index = 0;
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment