| @@ -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 3 | 33 | #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 | |
| | 521 | static 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 | |
| 517 | static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame) | 526 | static 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], ¤t_amplification_factor); | 692 | cqueue_dequeue(s->gain_history_smoothed[c], ¤t_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); |