History

avfilter/af_afftdn: rewrite noise floor tracking

Paul B Mahol committed 4 years ago

Commit ccb81ac1 parent 77d20a01 file · +61 −179Browse files

Unified · Split

libavfilter/af_afftdn.c+61−179
@@ -92,11 +92,6 @@ typedef struct DeNoiseChannel { · 91 unmodified lines
9292 double noise_band_avi[NB_PROFILE_BANDS];
9393 double noise_band_var[NB_PROFILE_BANDS];
9494
95− double sfm_threshold;
96− double sfm_alpha;
97− double sfm_results[3];
98− int sfm_fail_flags[SFM_FLAGS_SIZE];
99− int sfm_fail_total;
10095 double noise_reduction;
10196 double last_noise_reduction;
10297 double noise_floor;
@@ -155,7 +150,6 @@ typedef struct AudioFFTDeNoiseContext { · 52 unmodified lines
155150 double window_weight;
156151 double floor;
157152 double sample_floor;
158− double auto_floor;
159153
160154 int noise_band_edge[NB_PROFILE_BANDS + 2];
161155 int noise_band_count;
@@ -301,42 +295,6 @@ static double process_get_band_noise(AudioFFTDeNoiseContext *s, · 139 unmodified lines
301295 return sum;
302296 }
303297
304−static void calculate_sfm(AudioFFTDeNoiseContext *s,
305− DeNoiseChannel *dnch,
306− int start, int end)
307−{
308− double d1 = 0.0, d2 = 1.0;
309− int i = 0, j = 0;
310−
311− for (int k = start; k < end; k++) {
312− if (dnch->noisy_data[k] > s->sample_floor) {
313− j++;
314− d1 += dnch->noisy_data[k];
315− d2 *= dnch->noisy_data[k];
316− if (d2 > 1.0E100) {
317− d2 *= 1.0E-100;
318− i++;
319− } else if (d2 < 1.0E-100) {
320− d2 *= 1.0E100;
321− i--;
322− }
323− }
324− }
325− if (j > 1) {
326− d1 /= j;
327− dnch->sfm_results[0] = d1;
328− d2 = log(d2) + 230.2585 * i;
329− d2 /= j;
330− d1 = log(d1);
331− dnch->sfm_results[1] = d1;
332− dnch->sfm_results[2] = d1 - d2;
333− } else {
334− dnch->sfm_results[0] = s->auto_floor;
335− dnch->sfm_results[1] = dnch->sfm_threshold;
336− dnch->sfm_results[2] = dnch->sfm_threshold;
337− }
338−}
339−
340298 static double limit_gain(double a, double b)
341299 {
342300 if (a > 1.0)
@@ -346,116 +304,88 @@ static double limit_gain(double a, double b) · 3 unmodified lines
346304 return 1.0;
347305 }
348306
307+static void spectral_flatness(AudioFFTDeNoiseContext *s, const double *const spectral,
308+ double floor, int len, double *rnum, double *rden)
309+{
310+ double num = 0., den = 0.;
311+ int size = 0;
312+
313+ for (int n = 0; n < len; n++) {
314+ const double v = spectral[n];
315+ if (v > floor) {
316+ num += log(v);
317+ den += v;
318+ size++;
319+ }
320+ }
321+
322+ size = FFMAX(size, 1);
323+
324+ num /= size;
325+ den /= size;
326+
327+ num = exp(num);
328+
329+ *rnum = num;
330+ *rden = den;
331+}
332+
333+static void set_parameters(AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, int update_var, int update_auto_var);
334+
335+static double floor_offset(const double *S, int size, double mean)
336+{
337+ double offset = 0.0;
338+
339+ for (int n = 0; n < size; n++) {
340+ const double p = S[n] - mean;
341+
342+ offset = fmax(offset, fabs(p));
343+ }
344+
345+ return offset / mean;
346+}
347+
349348 static void process_frame(AVFilterContext *ctx,
350349 AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch,
351350 AVComplexFloat *fft_data,
352351 double *prior, double *prior_band_excit, int track_noise)
353352 {
354353 AVFilterLink *outlink = ctx->outputs[0];
355− const double sample_floor = s->sample_floor;
356354 const double *abs_var = dnch->abs_var;
357355 const double ratio = outlink->frame_count_out ? s->ratio : 1.0;
358356 const double rratio = 1. - ratio;
359357 const int *bin2band = s->bin2band;
358+ double *noisy_data = dnch->noisy_data;
360359 double *band_excit = dnch->band_excit;
361360 double *band_amt = dnch->band_amt;
362361 double *gain = dnch->gain;
363− int n = 0, i1;
364−
365− for (int i = 0; i < s->fft_length2; i++) {
366− double sqr_new_gain, new_gain, mag, mag_abs_var, new_mag_abs_var;
367362
368− mag = fft_data[i].re * fft_data[i].re + fft_data[i].im * fft_data[i].im;
369− if (mag > sample_floor)
370− n = i;
363+ for (int i = 0; i < s->bin_count; i++) {
364+ double sqr_new_gain, new_gain, power, mag, mag_abs_var, new_mag_abs_var;
371365
372− dnch->noisy_data[i] = mag;
373− mag_abs_var = mag / abs_var[i];
366+ noisy_data[i] = mag = hypot(fft_data[i].re, fft_data[i].im);
367+ power = mag * mag;
368+ mag_abs_var = power / abs_var[i];
374369 new_mag_abs_var = ratio * prior[i] + rratio * fmax(mag_abs_var - 1.0, 0.0);
375370 new_gain = new_mag_abs_var / (1.0 + new_mag_abs_var);
376371 sqr_new_gain = new_gain * new_gain;
377372 prior[i] = mag_abs_var * sqr_new_gain;
378− dnch->clean_data[i] = mag * sqr_new_gain;
373+ dnch->clean_data[i] = power * sqr_new_gain;
379374 gain[i] = new_gain;
380375 }
381376
382− if (n > s->fft_length2 - 2) {
383− n = s->bin_count;
384− i1 = s->noise_band_count;
385− } else {
386− i1 = 0;
387− for (int i = 0; i <= s->noise_band_count; i++) {
388− if (n > 1.1 * s->noise_band_edge[i]) {
389− i1 = i;
390− }
391− }
392− }
393−
394− if (track_noise && (i1 > s->noise_band_count / 2)) {
395− int j = FFMIN(n, s->noise_band_edge[i1]);
396− int m = 3, k;
397−
398− for (k = i1 - 1; k >= 0; k--) {
399− int i = s->noise_band_edge[k];
400− calculate_sfm(s, dnch, i, j);
401− dnch->noise_band_sample[k] = dnch->sfm_results[0];
402− if (dnch->sfm_results[2] + 0.013 * m * fmax(0.0, dnch->sfm_results[1] - 20.53) >= dnch->sfm_threshold) {
403− break;
404− }
405− j = i;
406− m++;
407− }
408−
409− if (k < i1 - 1) {
410− double sum = 0.0, min, max;
411− int i;
412−
413− for (i = i1 - 1; i > k; i--) {
414− min = log(dnch->noise_band_sample[i] / dnch->noise_band_auto_var[i]);
415− sum += min;
416− }
377+ if (track_noise) {
378+ double flatness, num, den;
417379
418− i = i1 - k - 1;
419− if (i < 5) {
420− min = 3.0E-4 * i * i;
421− } else {
422− min = 3.0E-4 * (8 * i - 16);
423− }
424− if (i < 3) {
425− max = 2.0E-4 * i * i;
426− } else {
427− max = 2.0E-4 * (4 * i - 4);
428− }
380+ spectral_flatness(s, noisy_data, s->floor, s->bin_count, &num, &den);
429381
430− if (s->track_residual) {
431− if (dnch->last_noise_floor > dnch->last_residual_floor + 9) {
432− min *= 0.5;
433− max *= 0.75;
434− } else if (dnch->last_noise_floor > dnch->last_residual_floor + 6) {
435− min *= 0.4;
436− max *= 1.0;
437− } else if (dnch->last_noise_floor > dnch->last_residual_floor + 4) {
438− min *= 0.3;
439− max *= 1.3;
440− } else if (dnch->last_noise_floor > dnch->last_residual_floor + 2) {
441− min *= 0.2;
442− max *= 1.6;
443− } else if (dnch->last_noise_floor > dnch->last_residual_floor) {
444− min *= 0.1;
445− max *= 2.0;
446− } else {
447− min = 0.0;
448− max *= 2.5;
449− }
450− }
382+ flatness = num / den;
383+ if (flatness > 0.8) {
384+ const double offset = floor_offset(noisy_data, s->bin_count, den);
385+ const double new_floor = av_clipd(10.0 * log10(den) - 100.0 + offset, -90., -20.);
451386
452− sum = av_clipd(sum, -min, max);
453− sum = exp(sum);
454− for (int i = 0; i < NB_PROFILE_BANDS; i++)
455− dnch->noise_band_auto_var[i] *= sum;
456− } else if (dnch->sfm_results[2] >= dnch->sfm_threshold) {
457− dnch->sfm_fail_flags[s->block_count & SFM_FLAGS_MASK] = 1;
458− dnch->sfm_fail_total += 1;
387+ dnch->noise_floor = 0.1 * new_floor + dnch->noise_floor * 0.9;
388+ set_parameters(s, dnch, 1, 0);
459389 }
460390 }
461391
@@ -495,7 +425,7 @@ static void process_frame(AVFilterContext *ctx, · 33 unmodified lines
495425 }
496426 }
497427
498− for (int i = 0; i < s->fft_length2; i++) {
428+ for (int i = 0; i < s->bin_count; i++) {
499429 const double new_gain = gain[i];
500430
501431 fft_data[i].re *= new_gain;
@@ -556,7 +486,6 @@ static void set_band_parameters(AudioFFTDeNoiseContext *s, · 54 unmodified lines
556486 d4 = (m - i) / d2;
557487 dnch->rel_var[m] = exp((d5 * d3 + band_noise * d4) * C);
558488 }
559− dnch->rel_var[s->fft_length2] = exp(band_noise * C);
560489
561490 for (i = 0; i < NB_PROFILE_BANDS; i++)
562491 dnch->noise_band_auto_var[i] = dnch->max_var * exp((process_get_band_noise(s, dnch, i) - 2.0) * C);
@@ -667,7 +596,7 @@ static int config_input(AVFilterLink *inlink) · 104 unmodified lines
667596 s->fft_length2 = 1 << (32 - ff_clz(s->window_length));
668597 s->fft_length = s->fft_length2;
669598 s->buffer_length = s->fft_length * 2;
670− s->bin_count = s->fft_length2 + 1;
599+ s->bin_count = s->fft_length2 / 2 + 1;
671600
672601 s->band_centre[0] = 80;
673602 for (i = 1; i < NB_PROFILE_BANDS; i++) {
@@ -712,7 +641,7 @@ static int config_input(AVFilterLink *inlink) · 38 unmodified lines
712641 for (i = 0; i < s->bin_count; i++)
713642 s->bin2band[i] = lrint(sdiv * freq2bark((0.5 * i * s->sample_rate) / s->fft_length2));
714643
715− s->number_of_bands = s->bin2band[s->fft_length2] + 1;
644+ s->number_of_bands = s->bin2band[s->bin_count - 1] + 1;
716645
717646 s->band_alpha = av_calloc(s->number_of_bands, sizeof(*s->band_alpha));
718647 s->band_beta = av_calloc(s->number_of_bands, sizeof(*s->band_beta));
@@ -745,19 +674,6 @@ static int config_input(AVFilterLink *inlink) · 26 unmodified lines
745674
746675 reduce_mean(dnch->band_noise);
747676
748− dnch->sfm_threshold = 0.8;
749− dnch->sfm_alpha = 0.05;
750− for (i = 0; i < SFM_FLAGS_SIZE; i++)
751− dnch->sfm_fail_flags[i] = 0;
752−
753− dnch->sfm_fail_total = 0;
754− j = FFMAX((int)(10.0 * (1.3 - dnch->sfm_threshold)), 1);
755−
756− for (i = 0; i < SFM_FLAGS_SIZE; i += j) {
757− dnch->sfm_fail_flags[i] = 1;
758− dnch->sfm_fail_total += 1;
759− }
760−
761677 dnch->amt = av_calloc(s->bin_count, sizeof(*dnch->amt));
762678 dnch->band_amt = av_calloc(s->number_of_bands, sizeof(*dnch->band_amt));
763679 dnch->band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->band_excit));
@@ -884,7 +800,6 @@ static int config_input(AVFilterLink *inlink) · 120 unmodified lines
884800 s->window_weight = 0.5 * sum;
885801 s->floor = (1LL << 48) * exp(-23.025558369790467) * s->window_weight;
886802 s->sample_floor = s->floor * exp(4.144600506562284);
887− s->auto_floor = s->floor * exp(6.907667510937141);
888803
889804 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {
890805 DeNoiseChannel *dnch = &s->dnch[ch];
@@ -965,7 +880,6 @@ static void sample_noise_block(AudioFFTDeNoiseContext *s, · 74 unmodified lines
965880
966881 mag2 = fmax(mag2, s->sample_floor);
967882
968− dnch->noisy_data[i] = mag2;
969883 var += mag2;
970884 n++;
971885 }
@@ -1034,7 +948,7 @@ static void set_noise_profile(AudioFFTDeNoiseContext *s, · 62 unmodified lines
1034948 for (int m = 0; m < NB_PROFILE_BANDS; m++)
1035949 temp[m] -= d1;
1036950
1037− new_noise_floor = round(d1) + 2.5;
951+ new_noise_floor = d1;
1038952
1039953 if (new_profile) {
1040954 av_log(s, AV_LOG_INFO, "bn=");
@@ -1066,16 +980,6 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 25 unmodified lines
1066980 double *dst = dnch->out_samples;
1067981 float *fft_in = dnch->fft_in;
1068982
1069− if (s->track_noise) {
1070− int i = s->block_count & SFM_FLAGS_MASK;
1071−
1072− if (dnch->sfm_fail_flags[i])
1073− dnch->sfm_fail_total--;
1074− dnch->sfm_fail_flags[i] = 0;
1075− dnch->sfm_threshold *= 1.0 - dnch->sfm_alpha;
1076− dnch->sfm_threshold += dnch->sfm_alpha * ((1.0 / SFM_FLAGS_SIZE) * dnch->sfm_fail_total);
1077− }
1078−
1079983 for (int m = 0; m < window_length; m++)
1080984 fft_in[m] = window[m] * src[m] * (1LL << 23);
1081985
@@ -1098,25 +1002,6 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 16 unmodified lines
10981002 return 0;
10991003 }
11001004
1101−static void get_auto_noise_levels(AudioFFTDeNoiseContext *s,
1102− DeNoiseChannel *dnch,
1103− double *levels)
1104−{
1105− if (s->noise_band_count > 0) {
1106− for (int i = 0; i < s->noise_band_count; i++) {
1107− levels[i] = 10.0 * log10(dnch->noise_band_auto_var[i] / s->floor) - 100.0;
1108− }
1109− if (s->noise_band_count < NB_PROFILE_BANDS) {
1110− for (int i = s->noise_band_count; i < NB_PROFILE_BANDS; i++)
1111− levels[i] = levels[i - 1];
1112− }
1113− } else {
1114− for (int i = 0; i < NB_PROFILE_BANDS; i++) {
1115− levels[i] = -100.0;
1116− }
1117− }
1118−}
1119−
11201005 static int output_frame(AVFilterLink *inlink, AVFrame *in)
11211006 {
11221007 AVFilterContext *ctx = inlink->dst;
@@ -1139,10 +1024,7 @@ static int output_frame(AVFilterLink *inlink, AVFrame *in) · 16 unmodified lines
11391024
11401025 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {
11411026 DeNoiseChannel *dnch = &s->dnch[ch];
1142− double levels[NB_PROFILE_BANDS];
11431027
1144− get_auto_noise_levels(s, dnch, levels);
1145− set_noise_profile(s, dnch, levels, 0);
11461028 average += dnch->noise_floor;
11471029 max = fmax(max, dnch->noise_floor);
11481030 min = fmin(min, dnch->noise_floor);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t