mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
avfilter/af_crystalizer: implement inverse filtering
This commit is contained in:
parent
28aedc7f54
commit
204a906437
@ -3690,8 +3690,9 @@ The filter accepts the following options:
|
||||
|
||||
@table @option
|
||||
@item i
|
||||
Sets the intensity of effect (default: 2.0). Must be in range between 0.0
|
||||
Sets the intensity of effect (default: 2.0). Must be in range between -10.0 to 0
|
||||
(unchanged sound) to 10.0 (maximum effect).
|
||||
To inverse filtering use negative value.
|
||||
|
||||
@item c
|
||||
Enable clipping. By default is enabled.
|
||||
|
@ -36,7 +36,7 @@ typedef struct CrystalizerContext {
|
||||
#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
|
||||
|
||||
static const AVOption crystalizer_options[] = {
|
||||
{ "i", "set intensity", OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0}, 0, 10, A },
|
||||
{ "i", "set intensity", OFFSET(mult), AV_OPT_TYPE_FLOAT, {.dbl=2.0},-10, 10, A },
|
||||
{ "c", "enable clipping", OFFSET(clip), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, A },
|
||||
{ NULL }
|
||||
};
|
||||
@ -91,7 +91,7 @@ static int filter_flt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
const void **s = td->s;
|
||||
const int nb_samples = td->nb_samples;
|
||||
const int channels = td->channels;
|
||||
float mult = td->mult;
|
||||
const float mult = td->mult;
|
||||
const int clip = td->clip;
|
||||
const int start = (channels * jobnr) / nb_jobs;
|
||||
const int end = (channels * (jobnr+1)) / nb_jobs;
|
||||
@ -195,7 +195,7 @@ static int filter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
const void **s = td->s;
|
||||
const int nb_samples = td->nb_samples;
|
||||
const int channels = td->channels;
|
||||
double mult = td->mult;
|
||||
const double mult = td->mult;
|
||||
const int clip = td->clip;
|
||||
const int start = (channels * jobnr) / nb_jobs;
|
||||
const int end = (channels * (jobnr+1)) / nb_jobs;
|
||||
@ -220,16 +220,157 @@ static int filter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ifilter_flt(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
{
|
||||
ThreadData *td = arg;
|
||||
void **d = td->d;
|
||||
void **p = td->p;
|
||||
const void **s = td->s;
|
||||
const int nb_samples = td->nb_samples;
|
||||
const int channels = td->channels;
|
||||
const float mult = -td->mult;
|
||||
const float div = -td->mult + 1.f;
|
||||
const int clip = td->clip;
|
||||
const int start = (channels * jobnr) / nb_jobs;
|
||||
const int end = (channels * (jobnr+1)) / nb_jobs;
|
||||
float *prv = p[0];
|
||||
int n, c;
|
||||
|
||||
for (c = start; c < end; c++) {
|
||||
const float *src = s[0];
|
||||
float *dst = d[0];
|
||||
|
||||
for (n = 0; n < nb_samples; n++) {
|
||||
float current = src[c];
|
||||
dst[c] = (current + prv[c] * mult) / div;
|
||||
prv[c] = dst[c];
|
||||
if (clip) {
|
||||
dst[c] = av_clipf(dst[c], -1, 1);
|
||||
}
|
||||
|
||||
dst += channels;
|
||||
src += channels;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ifilter_dbl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
{
|
||||
ThreadData *td = arg;
|
||||
void **d = td->d;
|
||||
void **p = td->p;
|
||||
const void **s = td->s;
|
||||
const int nb_samples = td->nb_samples;
|
||||
const int channels = td->channels;
|
||||
const double mult = -td->mult;
|
||||
const double div = -td->mult + 1.f;
|
||||
const int clip = td->clip;
|
||||
const int start = (channels * jobnr) / nb_jobs;
|
||||
const int end = (channels * (jobnr+1)) / nb_jobs;
|
||||
double *prv = p[0];
|
||||
int n, c;
|
||||
|
||||
for (c = start; c < end; c++) {
|
||||
const double *src = s[0];
|
||||
double *dst = d[0];
|
||||
|
||||
for (n = 0; n < nb_samples; n++) {
|
||||
double current = src[c];
|
||||
|
||||
dst[c] = (current + prv[c] * mult) / div;
|
||||
prv[c] = dst[c];
|
||||
if (clip) {
|
||||
dst[c] = av_clipd(dst[c], -1, 1);
|
||||
}
|
||||
|
||||
dst += channels;
|
||||
src += channels;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ifilter_fltp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
{
|
||||
ThreadData *td = arg;
|
||||
void **d = td->d;
|
||||
void **p = td->p;
|
||||
const void **s = td->s;
|
||||
const int nb_samples = td->nb_samples;
|
||||
const int channels = td->channels;
|
||||
const float mult = -td->mult;
|
||||
const float div = -td->mult + 1.f;
|
||||
const int clip = td->clip;
|
||||
const int start = (channels * jobnr) / nb_jobs;
|
||||
const int end = (channels * (jobnr+1)) / nb_jobs;
|
||||
int n, c;
|
||||
|
||||
for (c = start; c < end; c++) {
|
||||
const float *src = s[c];
|
||||
float *dst = d[c];
|
||||
float *prv = p[c];
|
||||
|
||||
for (n = 0; n < nb_samples; n++) {
|
||||
float current = src[n];
|
||||
|
||||
dst[n] = (current + prv[0] * mult) / div;
|
||||
prv[0] = dst[n];
|
||||
if (clip) {
|
||||
dst[n] = av_clipf(dst[n], -1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ifilter_dblp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
|
||||
{
|
||||
ThreadData *td = arg;
|
||||
void **d = td->d;
|
||||
void **p = td->p;
|
||||
const void **s = td->s;
|
||||
const int nb_samples = td->nb_samples;
|
||||
const int channels = td->channels;
|
||||
const double mult = -td->mult;
|
||||
const double div = -td->mult + 1.f;
|
||||
const int clip = td->clip;
|
||||
const int start = (channels * jobnr) / nb_jobs;
|
||||
const int end = (channels * (jobnr+1)) / nb_jobs;
|
||||
int n, c;
|
||||
|
||||
for (c = start; c < end; c++) {
|
||||
const double *src = s[c];
|
||||
double *dst = d[c];
|
||||
double *prv = p[c];
|
||||
|
||||
for (n = 0; n < nb_samples; n++) {
|
||||
double current = src[n];
|
||||
|
||||
dst[n] = (current + prv[0] * mult) / div;
|
||||
prv[0] = dst[n];
|
||||
if (clip) {
|
||||
dst[n] = av_clipd(dst[n], -1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_input(AVFilterLink *inlink)
|
||||
{
|
||||
AVFilterContext *ctx = inlink->dst;
|
||||
CrystalizerContext *s = ctx->priv;
|
||||
|
||||
switch (inlink->format) {
|
||||
case AV_SAMPLE_FMT_FLT: s->filter = filter_flt; break;
|
||||
case AV_SAMPLE_FMT_DBL: s->filter = filter_dbl; break;
|
||||
case AV_SAMPLE_FMT_FLTP: s->filter = filter_fltp; break;
|
||||
case AV_SAMPLE_FMT_DBLP: s->filter = filter_dblp; break;
|
||||
case AV_SAMPLE_FMT_FLT: s->filter = s->mult >= 0.f ? filter_flt : ifilter_flt; break;
|
||||
case AV_SAMPLE_FMT_DBL: s->filter = s->mult >= 0.f ? filter_dbl : ifilter_dbl; break;
|
||||
case AV_SAMPLE_FMT_FLTP: s->filter = s->mult >= 0.f ? filter_fltp : ifilter_fltp; break;
|
||||
case AV_SAMPLE_FMT_DBLP: s->filter = s->mult >= 0.f ? filter_dblp : ifilter_dblp; break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -285,6 +426,18 @@ static av_cold void uninit(AVFilterContext *ctx)
|
||||
av_frame_free(&s->prev);
|
||||
}
|
||||
|
||||
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
|
||||
char *res, int res_len, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return config_input(ctx->inputs[0]);
|
||||
}
|
||||
|
||||
static const AVFilterPad inputs[] = {
|
||||
{
|
||||
.name = "default",
|
||||
@ -312,7 +465,7 @@ AVFilter ff_af_crystalizer = {
|
||||
.uninit = uninit,
|
||||
.inputs = inputs,
|
||||
.outputs = outputs,
|
||||
.process_command = ff_filter_process_command,
|
||||
.process_command = process_command,
|
||||
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL |
|
||||
AVFILTER_FLAG_SLICE_THREADS,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user