From 6cb3b0e30321d6d514406fc2eb29f78a729c8642 Mon Sep 17 00:00:00 2001 From: Hendrik Leppkes Date: Sun, 16 Dec 2012 10:03:27 +0100 Subject: [PATCH] swresample: add a "clipping protection" mode when mixing This mode normalizes audio down to stay below 1.0 after mixing, so no clipping occurs when converting to integer formats. --- libswresample/options.c | 1 + libswresample/rematrix.c | 20 +++++++++++++++++++- libswresample/swresample_internal.h | 3 +++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libswresample/options.c b/libswresample/options.c index a3284a4896..1684048831 100644 --- a/libswresample/options.c +++ b/libswresample/options.c @@ -122,6 +122,7 @@ static const AVOption options[]={ { "kaiser_beta" , "set swr Kaiser window beta" , OFFSET(kaiser_beta) , AV_OPT_TYPE_DOUBLE , {.dbl=9 }, 2 , 16 , PARAM }, { "output_sample_bits" , "set swr number of output sample bits", OFFSET(dither.output_sample_bits), AV_OPT_TYPE_INT , {.i64=0 }, 0 , 64 , PARAM }, +{ "clip_protection" , "Clipping Protection" , OFFSET(clip_protection), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, PARAM }, {0} }; diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index fb4d9aecf0..b095e2d34f 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -452,6 +452,7 @@ av_cold int swri_rematrix_init(SwrContext *s){ int nb_out = s->out.ch_count; s->mix_any_f = NULL; + s->clip_max = 1.0f; if (!s->rematrix_custom) { int r = auto_matrix(s); @@ -566,7 +567,7 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus if(s->mix_any_f) { s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len); - return 0; + goto clip_protection; } if(s->mix_2_1_simd || s->mix_1_1_simd){ @@ -637,5 +638,22 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus } } } + +clip_protection: + if (s->clip_protection && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) + { + for(j = 0; j < out->ch_count; j++) { + for(i = 0; i < len; i++) { + const float sample = fabsf(((float *)out->ch[j])[i]); + if (sample > s->clip_max) { + s->clip_max = sample; + av_log(s, AV_LOG_INFO, "Clipping protection at %.3f\n", sample); + } + if (s->clip_max > 1.0f) + ((float *)out->ch[j])[i] /= s->clip_max; + } + } + } + return 0; } diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index 7e46b16fb2..814b3ab888 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -183,6 +183,9 @@ struct SwrContext { mix_any_func_type *mix_any_f; /* TODO: callbacks for ASM optimizations */ + + int clip_protection; + float clip_max; }; av_warn_unused_result