History

avfilter/af_dynaudnorm: allow to filter subset of channels

Paul B Mahol committed 4 years ago

Commit a9124a71 parent b9f91a72 files · +24 −4Browse files

Unified · Split

2 files
  1. doc/filters.texi +3 −0
  2. libavfilter/af_dynaudnorm.c +21 −4
doc/filters.texi+3−0
@@ -4389,6 +4389,9 @@ If input frame volume is above this value frame will be normalized. · 4388 unmodified lines
4389Otherwise frame may not be normalized at all. The default value is set4389Otherwise frame may not be normalized at all. The default value is set
4390to 0, which means all input frames will be normalized.4390to 0, which means all input frames will be normalized.
4391This option is mostly useful if digital noise is not wanted to be amplified.4391This option is mostly useful if digital noise is not wanted to be amplified.
4392
4393@item channels, h
4394Specify which channels to filter, by default all available channels are filtered.
4392@end table4395@end table
4393 4396
4394@subsection Commands4397@subsection Commands
libavfilter/af_dynaudnorm.c+21−4
@@ -27,6 +27,7 @@ · 26 unmodified lines
27#include <float.h>27#include <float.h>
28 28
29#include "libavutil/avassert.h"29#include "libavutil/avassert.h"
30#include "libavutil/channel_layout.h"
30#include "libavutil/opt.h"31#include "libavutil/opt.h"
31 32
32#define MIN_FILTER_SIZE 333#define MIN_FILTER_SIZE 3
@@ -76,6 +77,7 @@ typedef struct DynamicAudioNormalizerContext { · 43 unmodified lines
76 77
77 int channels;78 int channels;
78 int eof;79 int eof;
80 uint64_t channels_to_filter;
79 int64_t pts;81 int64_t pts;
80 82
81 cqueue **gain_history_original;83 cqueue **gain_history_original;
@@ -110,6 +112,8 @@ static const AVOption dynaudnorm_options[] = { · 28 unmodified lines
110 { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },112 { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS },
111 { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },113 { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
112 { "t", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },114 { "t", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS },
115 { "channels", "set channels to filter", OFFSET(channels_to_filter),AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS },
116 { "h", "set channels to filter", OFFSET(channels_to_filter),AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS },
113 { NULL }117 { NULL }
114};118};
115 119
@@ -514,6 +518,11 @@ static inline double update_value(double new, double old, double aggressiveness) · 398 unmodified lines
514 return aggressiveness * new + (1.0 - aggressiveness) * old;518 return aggressiveness * new + (1.0 - aggressiveness) * old;
515}519}
516 520
521static inline int bypass_channel(DynamicAudioNormalizerContext *s, AVFrame *frame, int ch)
522{
523 return !(av_channel_layout_extract_channel(frame->channel_layout, ch) & s->channels_to_filter);
524}
525
517static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame)526static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame)
518{527{
519 const double diff = 1.0 / frame->nb_samples;528 const double diff = 1.0 / frame->nb_samples;
@@ -521,6 +530,7 @@ static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *fra · 1 unmodified line
521 int c, i;530 int c, i;
522 531
523 for (c = 0; c < s->channels; c++) {532 for (c = 0; c < s->channels; c++) {
533 const int bypass = bypass_channel(s, frame, c);
524 double *dst_ptr = (double *)frame->extended_data[c];534 double *dst_ptr = (double *)frame->extended_data[c];
525 double current_average_value = 0.0;535 double current_average_value = 0.0;
526 double prev_value;536 double prev_value;
@@ -531,7 +541,7 @@ static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *fra · 4 unmodified lines
531 prev_value = is_first_frame ? current_average_value : s->dc_correction_value[c];541 prev_value = is_first_frame ? current_average_value : s->dc_correction_value[c];
532 s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1);542 s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1);
533 543
534 for (i = 0; i < frame->nb_samples; i++) {544 for (i = 0; i < frame->nb_samples && !bypass; i++) {
535 dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, frame->nb_samples);545 dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, frame->nb_samples);
536 }546 }
537 }547 }
@@ -604,6 +614,11 @@ static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame · 66 unmodified lines
604 614
605 for (c = 0; c < s->channels; c++) {615 for (c = 0; c < s->channels; c++) {
606 double *const dst_ptr = (double *)frame->extended_data[c];616 double *const dst_ptr = (double *)frame->extended_data[c];
617 const int bypass = bypass_channel(s, frame, c);
618
619 if (bypass)
620 continue;
621
607 for (i = 0; i < frame->nb_samples; i++) {622 for (i = 0; i < frame->nb_samples; i++) {
608 const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);623 const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);
609 dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);624 dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
@@ -611,19 +626,20 @@ static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame · 1 unmodified line
611 }626 }
612 } else {627 } else {
613 for (c = 0; c < s->channels; c++) {628 for (c = 0; c < s->channels; c++) {
629 const int bypass = bypass_channel(s, frame, c);
614 const double standard_deviation = compute_frame_std_dev(s, frame, c);630 const double standard_deviation = compute_frame_std_dev(s, frame, c);
615 const double current_threshold = setup_compress_thresh(FFMIN(1.0, s->compress_factor * standard_deviation));631 const double current_threshold = setup_compress_thresh(FFMIN(1.0, s->compress_factor * standard_deviation));
616
617 const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[c];632 const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[c];
618 double prev_actual_thresh, curr_actual_thresh;633 double prev_actual_thresh, curr_actual_thresh;
619 double *dst_ptr;634 double *dst_ptr;
635
620 s->compress_threshold[c] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[c], 1.0/3.0);636 s->compress_threshold[c] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[c], 1.0/3.0);
621 637
622 prev_actual_thresh = setup_compress_thresh(prev_value);638 prev_actual_thresh = setup_compress_thresh(prev_value);
623 curr_actual_thresh = setup_compress_thresh(s->compress_threshold[c]);639 curr_actual_thresh = setup_compress_thresh(s->compress_threshold[c]);
624 640
625 dst_ptr = (double *)frame->extended_data[c];641 dst_ptr = (double *)frame->extended_data[c];
626 for (i = 0; i < frame->nb_samples; i++) {642 for (i = 0; i < frame->nb_samples && !bypass; i++) {
627 const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);643 const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples);
628 dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);644 dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]);
629 }645 }
@@ -668,13 +684,14 @@ static void amplify_frame(DynamicAudioNormalizerContext *s, AVFrame *in, · 38 unmodified lines
668 int c, i;684 int c, i;
669 685
670 for (c = 0; c < s->channels; c++) {686 for (c = 0; c < s->channels; c++) {
687 const int bypass = bypass_channel(s, frame, c);
671 const double *src_ptr = (const double *)in->extended_data[c];688 const double *src_ptr = (const double *)in->extended_data[c];
672 double *dst_ptr = (double *)frame->extended_data[c];689 double *dst_ptr = (double *)frame->extended_data[c];
673 double current_amplification_factor;690 double current_amplification_factor;
674 691
675 cqueue_dequeue(s->gain_history_smoothed[c], &current_amplification_factor);692 cqueue_dequeue(s->gain_history_smoothed[c], &current_amplification_factor);
676 693
677 for (i = 0; i < frame->nb_samples && enabled; i++) {694 for (i = 0; i < frame->nb_samples && enabled && !bypass; i++) {
678 const double amplification_factor = fade(s->prev_amplification_factor[c],695 const double amplification_factor = fade(s->prev_amplification_factor[c],
679 current_amplification_factor, i,696 current_amplification_factor, i,
680 frame->nb_samples);697 frame->nb_samples);

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