mirror of https://git.ffmpeg.org/ffmpeg.git
avfilter/af_afftdn: use better approach for gain smoothing
This commit is contained in:
parent
eae3b84189
commit
fe85afbf8c
|
@ -1392,10 +1392,11 @@ Default value is @code{none}.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@item gain_smooth, gs
|
@item gain_smooth, gs
|
||||||
Set gain smooth factor, used to lowpass gains applied to each frequency bin.
|
Set gain smooth spatial radius, used to smooth gains applied to each frequency bin.
|
||||||
Useful to reduce random music noise artefacts.
|
Useful to reduce random music noise artefacts.
|
||||||
Higher values reduce smoothing of gains.
|
Higher values increases smoothing of gains.
|
||||||
Default value is @code{1.0}.
|
Allowed range is from @code{0} to @code{50}.
|
||||||
|
Default value is @code{0}.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@subsection Commands
|
@subsection Commands
|
||||||
|
|
|
@ -71,6 +71,7 @@ typedef struct DeNoiseChannel {
|
||||||
double *band_amt;
|
double *band_amt;
|
||||||
double *band_excit;
|
double *band_excit;
|
||||||
double *gain;
|
double *gain;
|
||||||
|
double *smoothed_gain;
|
||||||
double *prior;
|
double *prior;
|
||||||
double *prior_band_excit;
|
double *prior_band_excit;
|
||||||
double *clean_data;
|
double *clean_data;
|
||||||
|
@ -114,7 +115,7 @@ typedef struct AudioFFTDeNoiseContext {
|
||||||
int output_mode;
|
int output_mode;
|
||||||
int noise_floor_link;
|
int noise_floor_link;
|
||||||
float ratio;
|
float ratio;
|
||||||
float gain_smooth;
|
int gain_smooth;
|
||||||
float band_multiplier;
|
float band_multiplier;
|
||||||
float floor_offset;
|
float floor_offset;
|
||||||
|
|
||||||
|
@ -208,8 +209,8 @@ static const AVOption afftdn_options[] = {
|
||||||
{ "begin", "start", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_START}, 0, 0, AFR, "sample" },
|
{ "begin", "start", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_START}, 0, 0, AFR, "sample" },
|
||||||
{ "stop", "stop", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_STOP}, 0, 0, AFR, "sample" },
|
{ "stop", "stop", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_STOP}, 0, 0, AFR, "sample" },
|
||||||
{ "end", "stop", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_STOP}, 0, 0, AFR, "sample" },
|
{ "end", "stop", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_STOP}, 0, 0, AFR, "sample" },
|
||||||
{ "gain_smooth", "set gain smooth factor",OFFSET(gain_smooth), AV_OPT_TYPE_FLOAT, {.dbl = 1.00}, 0.0001, 1, AFR },
|
{ "gain_smooth", "set gain smooth radius",OFFSET(gain_smooth), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 50, AFR },
|
||||||
{ "gs", "set gain smooth factor",OFFSET(gain_smooth), AV_OPT_TYPE_FLOAT, {.dbl = 1.00}, 0.0001, 1, AFR },
|
{ "gs", "set gain smooth radius",OFFSET(gain_smooth), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 50, AFR },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -357,6 +358,7 @@ static void process_frame(AVFilterContext *ctx,
|
||||||
double *noisy_data = dnch->noisy_data;
|
double *noisy_data = dnch->noisy_data;
|
||||||
double *band_excit = dnch->band_excit;
|
double *band_excit = dnch->band_excit;
|
||||||
double *band_amt = dnch->band_amt;
|
double *band_amt = dnch->band_amt;
|
||||||
|
double *smoothed_gain = dnch->smoothed_gain;
|
||||||
double *gain = dnch->gain;
|
double *gain = dnch->gain;
|
||||||
|
|
||||||
for (int i = 0; i < s->bin_count; i++) {
|
for (int i = 0; i < s->bin_count; i++) {
|
||||||
|
@ -424,16 +426,28 @@ static void process_frame(AVFilterContext *ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
memcpy(smoothed_gain, gain, s->bin_count * sizeof(*smoothed_gain));
|
||||||
const double f = s->gain_smooth;
|
if (s->gain_smooth > 0) {
|
||||||
const double F = 1. - f;
|
const int r = s->gain_smooth;
|
||||||
|
|
||||||
for (int i = 1; i < s->bin_count; i++)
|
for (int i = r; i < s->bin_count - r; i++) {
|
||||||
gain[i] = gain[i-1] * F + f * gain[i];
|
const double gc = gain[i];
|
||||||
|
double num = 0., den = 0.;
|
||||||
|
|
||||||
|
for (int j = -r; j <= r; j++) {
|
||||||
|
const double g = gain[i + j];
|
||||||
|
const double d = 1. - fabs(g - gc);
|
||||||
|
|
||||||
|
num += g * d;
|
||||||
|
den += d;
|
||||||
|
}
|
||||||
|
|
||||||
|
smoothed_gain[i] = num / den;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < s->bin_count; i++) {
|
for (int i = 0; i < s->bin_count; i++) {
|
||||||
const double new_gain = gain[i];
|
const double new_gain = smoothed_gain[i];
|
||||||
|
|
||||||
fft_data[i].re *= new_gain;
|
fft_data[i].re *= new_gain;
|
||||||
fft_data[i].im *= new_gain;
|
fft_data[i].im *= new_gain;
|
||||||
|
@ -685,6 +699,7 @@ static int config_input(AVFilterLink *inlink)
|
||||||
dnch->band_amt = av_calloc(s->number_of_bands, sizeof(*dnch->band_amt));
|
dnch->band_amt = av_calloc(s->number_of_bands, sizeof(*dnch->band_amt));
|
||||||
dnch->band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->band_excit));
|
dnch->band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->band_excit));
|
||||||
dnch->gain = av_calloc(s->bin_count, sizeof(*dnch->gain));
|
dnch->gain = av_calloc(s->bin_count, sizeof(*dnch->gain));
|
||||||
|
dnch->smoothed_gain = av_calloc(s->bin_count, sizeof(*dnch->smoothed_gain));
|
||||||
dnch->prior = av_calloc(s->bin_count, sizeof(*dnch->prior));
|
dnch->prior = av_calloc(s->bin_count, sizeof(*dnch->prior));
|
||||||
dnch->prior_band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->prior_band_excit));
|
dnch->prior_band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->prior_band_excit));
|
||||||
dnch->clean_data = av_calloc(s->bin_count, sizeof(*dnch->clean_data));
|
dnch->clean_data = av_calloc(s->bin_count, sizeof(*dnch->clean_data));
|
||||||
|
@ -708,6 +723,7 @@ static int config_input(AVFilterLink *inlink)
|
||||||
!dnch->band_amt ||
|
!dnch->band_amt ||
|
||||||
!dnch->band_excit ||
|
!dnch->band_excit ||
|
||||||
!dnch->gain ||
|
!dnch->gain ||
|
||||||
|
!dnch->smoothed_gain ||
|
||||||
!dnch->prior ||
|
!dnch->prior ||
|
||||||
!dnch->prior_band_excit ||
|
!dnch->prior_band_excit ||
|
||||||
!dnch->clean_data ||
|
!dnch->clean_data ||
|
||||||
|
@ -1161,6 +1177,7 @@ static av_cold void uninit(AVFilterContext *ctx)
|
||||||
av_freep(&dnch->band_amt);
|
av_freep(&dnch->band_amt);
|
||||||
av_freep(&dnch->band_excit);
|
av_freep(&dnch->band_excit);
|
||||||
av_freep(&dnch->gain);
|
av_freep(&dnch->gain);
|
||||||
|
av_freep(&dnch->smoothed_gain);
|
||||||
av_freep(&dnch->prior);
|
av_freep(&dnch->prior);
|
||||||
av_freep(&dnch->prior_band_excit);
|
av_freep(&dnch->prior_band_excit);
|
||||||
av_freep(&dnch->clean_data);
|
av_freep(&dnch->clean_data);
|
||||||
|
|
Loading…
Reference in New Issue