History

avfilter/af_afftdn: rewrite noise floor tracking

Paul B Mahol committed 4 years ago

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

Showing the changes to libavfilter (1 of 1 file). Show all

Unified · Split

libavfilter/af_afftdn.c+61−179
@@ -92,11 +92,6 @@ typedef struct DeNoiseChannel { · 91 unmodified lines
92 double noise_band_avi[NB_PROFILE_BANDS];92 double noise_band_avi[NB_PROFILE_BANDS];
93 double noise_band_var[NB_PROFILE_BANDS];93 double noise_band_var[NB_PROFILE_BANDS];
94 94
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;
100 double noise_reduction;95 double noise_reduction;
101 double last_noise_reduction;96 double last_noise_reduction;
102 double noise_floor;97 double noise_floor;
@@ -155,7 +150,6 @@ typedef struct AudioFFTDeNoiseContext { · 52 unmodified lines
155 double window_weight;150 double window_weight;
156 double floor;151 double floor;
157 double sample_floor;152 double sample_floor;
158 double auto_floor;
159 153
160 int noise_band_edge[NB_PROFILE_BANDS + 2];154 int noise_band_edge[NB_PROFILE_BANDS + 2];
161 int noise_band_count;155 int noise_band_count;
@@ -301,42 +295,6 @@ static double process_get_band_noise(AudioFFTDeNoiseContext *s, · 139 unmodified lines
301 return sum;295 return sum;
302}296}
303 297
304static 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
340static double limit_gain(double a, double b)298static double limit_gain(double a, double b)
341{299{
342 if (a > 1.0)300 if (a > 1.0)
@@ -346,116 +304,88 @@ static double limit_gain(double a, double b) · 3 unmodified lines
346 return 1.0;304 return 1.0;
347}305}
348 306
307static 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
333static void set_parameters(AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, int update_var, int update_auto_var);
334
335static 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
349static void process_frame(AVFilterContext *ctx,348static void process_frame(AVFilterContext *ctx,
350 AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch,349 AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch,
351 AVComplexFloat *fft_data,350 AVComplexFloat *fft_data,
352 double *prior, double *prior_band_excit, int track_noise)351 double *prior, double *prior_band_excit, int track_noise)
353{352{
354 AVFilterLink *outlink = ctx->outputs[0];353 AVFilterLink *outlink = ctx->outputs[0];
355 const double sample_floor = s->sample_floor;
356 const double *abs_var = dnch->abs_var;354 const double *abs_var = dnch->abs_var;
357 const double ratio = outlink->frame_count_out ? s->ratio : 1.0;355 const double ratio = outlink->frame_count_out ? s->ratio : 1.0;
358 const double rratio = 1. - ratio;356 const double rratio = 1. - ratio;
359 const int *bin2band = s->bin2band;357 const int *bin2band = s->bin2band;
358 double *noisy_data = dnch->noisy_data;
360 double *band_excit = dnch->band_excit;359 double *band_excit = dnch->band_excit;
361 double *band_amt = dnch->band_amt;360 double *band_amt = dnch->band_amt;
362 double *gain = dnch->gain;361 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;
367 362
368 mag = fft_data[i].re * fft_data[i].re + fft_data[i].im * fft_data[i].im;363 for (int i = 0; i < s->bin_count; i++) {
369 if (mag > sample_floor)364 double sqr_new_gain, new_gain, power, mag, mag_abs_var, new_mag_abs_var;
370 n = i;
371 365
372 dnch->noisy_data[i] = mag;366 noisy_data[i] = mag = hypot(fft_data[i].re, fft_data[i].im);
373 mag_abs_var = mag / abs_var[i];367 power = mag * mag;
368 mag_abs_var = power / abs_var[i];
374 new_mag_abs_var = ratio * prior[i] + rratio * fmax(mag_abs_var - 1.0, 0.0);369 new_mag_abs_var = ratio * prior[i] + rratio * fmax(mag_abs_var - 1.0, 0.0);
375 new_gain = new_mag_abs_var / (1.0 + new_mag_abs_var);370 new_gain = new_mag_abs_var / (1.0 + new_mag_abs_var);
376 sqr_new_gain = new_gain * new_gain;371 sqr_new_gain = new_gain * new_gain;
377 prior[i] = mag_abs_var * sqr_new_gain;372 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;
379 gain[i] = new_gain;374 gain[i] = new_gain;
380 }375 }
381 376
382 if (n > s->fft_length2 - 2) {377 if (track_noise) {
383 n = s->bin_count;378 double flatness, num, den;
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 }
417 379
418 i = i1 - k - 1;380 spectral_flatness(s, noisy_data, s->floor, s->bin_count, &num, &den);
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 }
429 381
430 if (s->track_residual) {382 flatness = num / den;
431 if (dnch->last_noise_floor > dnch->last_residual_floor + 9) {383 if (flatness > 0.8) {
432 min *= 0.5;384 const double offset = floor_offset(noisy_data, s->bin_count, den);
433 max *= 0.75;385 const double new_floor = av_clipd(10.0 * log10(den) - 100.0 + offset, -90., -20.);
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 }
451 386
452 sum = av_clipd(sum, -min, max);387 dnch->noise_floor = 0.1 * new_floor + dnch->noise_floor * 0.9;
453 sum = exp(sum);388 set_parameters(s, dnch, 1, 0);
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;
459 }389 }
460 }390 }
461 391
@@ -495,7 +425,7 @@ static void process_frame(AVFilterContext *ctx, · 33 unmodified lines
495 }425 }
496 }426 }
497 427
498 for (int i = 0; i < s->fft_length2; i++) {428 for (int i = 0; i < s->bin_count; i++) {
499 const double new_gain = gain[i];429 const double new_gain = gain[i];
500 430
501 fft_data[i].re *= new_gain;431 fft_data[i].re *= new_gain;
@@ -556,7 +486,6 @@ static void set_band_parameters(AudioFFTDeNoiseContext *s, · 54 unmodified lines
556 d4 = (m - i) / d2;486 d4 = (m - i) / d2;
557 dnch->rel_var[m] = exp((d5 * d3 + band_noise * d4) * C);487 dnch->rel_var[m] = exp((d5 * d3 + band_noise * d4) * C);
558 }488 }
559 dnch->rel_var[s->fft_length2] = exp(band_noise * C);
560 489
561 for (i = 0; i < NB_PROFILE_BANDS; i++)490 for (i = 0; i < NB_PROFILE_BANDS; i++)
562 dnch->noise_band_auto_var[i] = dnch->max_var * exp((process_get_band_noise(s, dnch, i) - 2.0) * C);491 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
667 s->fft_length2 = 1 << (32 - ff_clz(s->window_length));596 s->fft_length2 = 1 << (32 - ff_clz(s->window_length));
668 s->fft_length = s->fft_length2;597 s->fft_length = s->fft_length2;
669 s->buffer_length = s->fft_length * 2;598 s->buffer_length = s->fft_length * 2;
670 s->bin_count = s->fft_length2 + 1;599 s->bin_count = s->fft_length2 / 2 + 1;
671 600
672 s->band_centre[0] = 80;601 s->band_centre[0] = 80;
673 for (i = 1; i < NB_PROFILE_BANDS; i++) {602 for (i = 1; i < NB_PROFILE_BANDS; i++) {
@@ -712,7 +641,7 @@ static int config_input(AVFilterLink *inlink) · 38 unmodified lines
712 for (i = 0; i < s->bin_count; i++)641 for (i = 0; i < s->bin_count; i++)
713 s->bin2band[i] = lrint(sdiv * freq2bark((0.5 * i * s->sample_rate) / s->fft_length2));642 s->bin2band[i] = lrint(sdiv * freq2bark((0.5 * i * s->sample_rate) / s->fft_length2));
714 643
715 s->number_of_bands = s->bin2band[s->fft_length2] + 1;644 s->number_of_bands = s->bin2band[s->bin_count - 1] + 1;
716 645
717 s->band_alpha = av_calloc(s->number_of_bands, sizeof(*s->band_alpha));646 s->band_alpha = av_calloc(s->number_of_bands, sizeof(*s->band_alpha));
718 s->band_beta = av_calloc(s->number_of_bands, sizeof(*s->band_beta));647 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
745 674
746 reduce_mean(dnch->band_noise);675 reduce_mean(dnch->band_noise);
747 676
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
761 dnch->amt = av_calloc(s->bin_count, sizeof(*dnch->amt));677 dnch->amt = av_calloc(s->bin_count, sizeof(*dnch->amt));
762 dnch->band_amt = av_calloc(s->number_of_bands, sizeof(*dnch->band_amt));678 dnch->band_amt = av_calloc(s->number_of_bands, sizeof(*dnch->band_amt));
763 dnch->band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->band_excit));679 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
884 s->window_weight = 0.5 * sum;800 s->window_weight = 0.5 * sum;
885 s->floor = (1LL << 48) * exp(-23.025558369790467) * s->window_weight;801 s->floor = (1LL << 48) * exp(-23.025558369790467) * s->window_weight;
886 s->sample_floor = s->floor * exp(4.144600506562284);802 s->sample_floor = s->floor * exp(4.144600506562284);
887 s->auto_floor = s->floor * exp(6.907667510937141);
888 803
889 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {804 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {
890 DeNoiseChannel *dnch = &s->dnch[ch];805 DeNoiseChannel *dnch = &s->dnch[ch];
@@ -965,7 +880,6 @@ static void sample_noise_block(AudioFFTDeNoiseContext *s, · 74 unmodified lines
965 880
966 mag2 = fmax(mag2, s->sample_floor);881 mag2 = fmax(mag2, s->sample_floor);
967 882
968 dnch->noisy_data[i] = mag2;
969 var += mag2;883 var += mag2;
970 n++;884 n++;
971 }885 }
@@ -1034,7 +948,7 @@ static void set_noise_profile(AudioFFTDeNoiseContext *s, · 62 unmodified lines
1034 for (int m = 0; m < NB_PROFILE_BANDS; m++)948 for (int m = 0; m < NB_PROFILE_BANDS; m++)
1035 temp[m] -= d1;949 temp[m] -= d1;
1036 950
1037 new_noise_floor = round(d1) + 2.5;951 new_noise_floor = d1;
1038 952
1039 if (new_profile) {953 if (new_profile) {
1040 av_log(s, AV_LOG_INFO, "bn=");954 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
1066 double *dst = dnch->out_samples;980 double *dst = dnch->out_samples;
1067 float *fft_in = dnch->fft_in;981 float *fft_in = dnch->fft_in;
1068 982
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
1079 for (int m = 0; m < window_length; m++)983 for (int m = 0; m < window_length; m++)
1080 fft_in[m] = window[m] * src[m] * (1LL << 23);984 fft_in[m] = window[m] * src[m] * (1LL << 23);
1081 985
@@ -1098,25 +1002,6 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job · 16 unmodified lines
1098 return 0;1002 return 0;
1099}1003}
1100 1004
1101static 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
1120static int output_frame(AVFilterLink *inlink, AVFrame *in)1005static int output_frame(AVFilterLink *inlink, AVFrame *in)
1121{1006{
1122 AVFilterContext *ctx = inlink->dst;1007 AVFilterContext *ctx = inlink->dst;
@@ -1139,10 +1024,7 @@ static int output_frame(AVFilterLink *inlink, AVFrame *in) · 16 unmodified lines
1139 1024
1140 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {1025 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {
1141 DeNoiseChannel *dnch = &s->dnch[ch];1026 DeNoiseChannel *dnch = &s->dnch[ch];
1142 double levels[NB_PROFILE_BANDS];
1143 1027
1144 get_auto_noise_levels(s, dnch, levels);
1145 set_noise_profile(s, dnch, levels, 0);
1146 average += dnch->noise_floor;1028 average += dnch->noise_floor;
1147 max = fmax(max, dnch->noise_floor);1029 max = fmax(max, dnch->noise_floor);
1148 min = fmin(min, dnch->noise_floor);1030 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