Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2012-12-16 13:03:27 +0400
committerHendrik Leppkes <h.leppkes@gmail.com>2017-08-04 20:12:11 +0300
commit8d82b6a793f6c1f316ef27cd0b6bc672f69fbb0b (patch)
treec8849489446fc9c4c5bba33eab4252f24258c6ef /libavresample
parentebb94701619fc84e9ec1bad127a19970d1a33186 (diff)
avresample: 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.
Diffstat (limited to 'libavresample')
-rw-r--r--libavresample/audio_mix.c20
-rw-r--r--libavresample/internal.h2
-rw-r--r--libavresample/options.c1
3 files changed, 23 insertions, 0 deletions
diff --git a/libavresample/audio_mix.c b/libavresample/audio_mix.c
index 7ae0aeb74d..ae1a09b892 100644
--- a/libavresample/audio_mix.c
+++ b/libavresample/audio_mix.c
@@ -56,6 +56,9 @@ struct AudioMix {
int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
void **matrix;
+
+ int clip_protection;
+ float clip_max;
};
void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
@@ -362,6 +365,8 @@ AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
am->out_layout = avr->out_channel_layout;
am->in_channels = avr->in_channels;
am->out_channels = avr->out_channels;
+ am->clip_protection = avr->internal_sample_fmt == AV_SAMPLE_FMT_FLTP && avr->clip_protection;
+ am->clip_max = 1.0f;
/* build matrix if the user did not already set one */
if (avr->mix_matrix) {
@@ -477,6 +482,21 @@ int ff_audio_mix(AudioMix *am, AudioData *src)
ff_audio_data_set_channels(src, am->out_channels);
+ /* clip protection is only enabled when the internal sample format is fltp, so we don't need to check here */
+ if (am->clip_protection) {
+ for(i = 0; i < src->nb_samples; i++) {
+ for (j = 0; j < src->channels; j++) {
+ const float sample = fabs(((float **)src->data)[j][i]);
+ if (sample > am->clip_max) {
+ am->clip_max = sample;
+ av_log(am->avr, AV_LOG_INFO, "Clipping protection at %.3f\n", sample);
+ }
+ if (am->clip_max > 1.0f)
+ ((float **)src->data)[j][i] /= am->clip_max;
+ }
+ }
+ }
+
return 0;
}
diff --git a/libavresample/internal.h b/libavresample/internal.h
index 2fc3f6da67..815be824a8 100644
--- a/libavresample/internal.h
+++ b/libavresample/internal.h
@@ -105,6 +105,8 @@ struct AVAudioResampleContext {
int use_channel_map;
enum RemapPoint remap_point;
ChannelMapInfo ch_map_info;
+
+ int clip_protection;
};
diff --git a/libavresample/options.c b/libavresample/options.c
index 5f08cd7e52..23575238f1 100644
--- a/libavresample/options.c
+++ b/libavresample/options.c
@@ -83,6 +83,7 @@ static const AVOption avresample_options[] = {
{"triangular", "Triangular Dither", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_TRIANGULAR }, INT_MIN, INT_MAX, PARAM, "dither_method"},
{"triangular_hp", "Triangular Dither With High Pass", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_TRIANGULAR_HP }, INT_MIN, INT_MAX, PARAM, "dither_method"},
{"triangular_ns", "Triangular Dither With Noise Shaping", 0, AV_OPT_TYPE_CONST, { .i64 = AV_RESAMPLE_DITHER_TRIANGULAR_NS }, INT_MIN, INT_MAX, PARAM, "dither_method"},
+ { "clip_protection", "Clipping Protection", OFFSET(clip_protection), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, PARAM },
{ NULL },
};