From 44ca71fedb800ddef183feccdb9c1a69492aa89e Mon Sep 17 00:00:00 2001 From: Johns Date: Thu, 19 Apr 2012 16:01:20 +0200 Subject: [PATCH] Adds audio normalize support. --- README.txt | 31 +++++++++-------- audio.c | 90 ++++++++++++++++++++++++++++++++++++++++++------ softhddevice.cpp | 4 +-- video.c | 2 ++ 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/README.txt b/README.txt index 82e6f53..8ac6d08 100644 --- a/README.txt +++ b/README.txt @@ -157,27 +157,28 @@ Setup: /etc/vdr/setup.conf 0 = none, 1 = downmix downmix AC-3 to stero. - softhddevice.AudioSoftvol - FIXME: + softhddevice.AudioSoftvol = 0 + 0 = off, use hardware volume control + 1 = on, use software volume control - softhddevice.AudioNormalize - FIXME: + softhddevice.AudioNormalize = 0 + 0 = off, 1 = enable audio normalize - softhddevice.AudioMaxNormalize - FIXME: + softhddevice.AudioMaxNormalize = 0 + maximal volume factor/1000 of the normalize filter - softhddevice.AudioCompression - FIXME: + softhddevice.AudioCompression = 0 + 0 = off, 1 = enable audio compression - softhddevice.AudioMaxCompression - FIXME: + softhddevice.AudioMaxCompression = 0 + maximal volume factor/1000 of the compression filter - softhddevice.AudioStereoDescent - FIXME: - - softhddevice.AudioBufferTime - FIXME: + softhddevice.AudioStereoDescent = 0 + reduce volume level (/1000) for stereo sources + softhddevice.AudioBufferTime = 0 + 0 = default (336 ms) + 1 - 1000 = size of the buffer in ms softhddevice.AutoCrop.Interval = 0 0 disables auto-crop diff --git a/audio.c b/audio.c index 9342585..a025752 100644 --- a/audio.c +++ b/audio.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #define _(str) gettext(str) ///< gettext shortcut @@ -163,6 +164,8 @@ static char AudioNormalize; ///< flag use volume normalize static char AudioCompression; ///< flag use compress volume static char AudioMute; ///< flag muted static int AudioAmplifier; ///< software volume factor +static int AudioNormalizeFactor; ///< current normalize factor +static const int AudioMinNormalize = 100; ///< min. normalize factor static int AudioMaxNormalize; ///< max. normalize factor static int AudioCompressionFactor; ///< current compression factor static int AudioMaxCompression; ///< max. compression factor @@ -205,12 +208,13 @@ static const unsigned AudioRatesTable[AudioRatesMax] = { // filter //---------------------------------------------------------------------------- -static const int AudioNormSamples = 32768; ///< number of samples +static const int AudioNormSamples = 4096; ///< number of samples -#define AudioNormIndexes 128 ///< number of average values +#define AudioNormMaxIndex 128 ///< number of average values /// average of n last sample blocks -static uint32_t AudioNormAverage[AudioNormIndexes]; +static uint32_t AudioNormAverage[AudioNormMaxIndex]; static int AudioNormIndex; ///< index into average table +static int AudioNormReady; ///< index counter static int AudioNormCounter; ///< sample counter /** @@ -222,21 +226,77 @@ static int AudioNormCounter; ///< sample counter static void AudioNormalizer(int16_t * samples, int count) { int i; + int l; int n; uint32_t avg; + int factor; + int16_t *data; // average samples - avg = 0; - n = count / AudioBytesProSample; - for (i = 0; i < n; ++i) { + l = count / AudioBytesProSample; + data = samples; + do { + n = l; + if (AudioNormCounter + n > AudioNormSamples) { + n = AudioNormSamples - AudioNormCounter; + } + avg = AudioNormAverage[AudioNormIndex]; + for (i = 0; i < n; ++i) { + int t; + + t = data[i]; + avg += (t * t) / AudioNormSamples; + } + AudioNormAverage[AudioNormIndex] = avg; + AudioNormCounter += n; + if (AudioNormCounter >= AudioNormSamples) { + if (AudioNormReady < AudioNormMaxIndex) { + AudioNormReady++; + } else { + avg = 0; + for (i = 0; i < AudioNormMaxIndex; ++i) { + avg += AudioNormAverage[i] / AudioNormMaxIndex; + } + + // calculate normalize factor + if (avg > 0) { + factor = ((INT16_MAX / 8) * 1000U) / (uint32_t) sqrt(avg); + // smooth normalize + AudioNormalizeFactor = + (AudioNormalizeFactor * 500 + factor * 500) / 1000; + if (AudioNormalizeFactor < AudioMinNormalize) { + AudioNormalizeFactor = AudioMinNormalize; + } + if (AudioNormalizeFactor > AudioMaxNormalize) { + AudioNormalizeFactor = AudioMaxNormalize; + } + } else { + factor = 1000; + } + Debug(4, "audio/noramlize: avg %8d, fac=%6.3f, norm=%6.3f\n", + avg, factor / 1000.0, AudioNormalizeFactor / 1000.0); + } + + AudioNormIndex = (AudioNormIndex + 1) % AudioNormMaxIndex; + AudioNormCounter = 0; + AudioNormAverage[AudioNormIndex] = 0U; + } + data += n; + l -= n; + } while (l > 0); + + // apply normalize factor + for (i = 0; i < count / AudioBytesProSample; ++i) { int t; - t = samples[i]; - avg += t * t; - avg /= 2; + t = (samples[i] * AudioNormalizeFactor) / 1000; + if (t < INT16_MIN) { + t = INT16_MIN; + } else if (t > INT16_MAX) { + t = INT16_MAX; + } + samples[i] = t; } - - // FIXME: more todo } /** @@ -244,6 +304,14 @@ static void AudioNormalizer(int16_t * samples, int count) */ static void AudioResetNormalizer(void) { + int i; + + AudioNormCounter = 0; + AudioNormReady = 0; + for (i = 0; i < AudioNormMaxIndex; ++i) { + AudioNormAverage[i] = 0U; + } + AudioNormalizeFactor = 1000; } /** diff --git a/softhddevice.cpp b/softhddevice.cpp index bddc267..21a4996 100644 --- a/softhddevice.cpp +++ b/softhddevice.cpp @@ -690,9 +690,9 @@ void cMenuSetupSoft::Create(void) Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol, tr("Hardware"), tr("Software"))); Add(new cMenuEditBoolItem(tr("Enable normalize volume"), - &AudioMaxNormalize, trVDR("no"), trVDR("yes"))); + &AudioNormalize, trVDR("no"), trVDR("yes"))); Add(new cMenuEditIntItem(tr(" Max normalize factor (/1000)"), - &AudioMaxNormalize, 0, 5000)); + &AudioMaxNormalize, 0, 10000)); Add(new cMenuEditBoolItem(tr("Enable volume compression"), &AudioCompression, trVDR("no"), trVDR("yes"))); Add(new cMenuEditIntItem(tr(" Max compression factor (/1000)"), diff --git a/video.c b/video.c index 911272a..47d72db 100644 --- a/video.c +++ b/video.c @@ -1857,6 +1857,7 @@ static void VaapiCleanup(VaapiDecoder * decoder) decoder->SurfaceWrite = 0; decoder->SurfaceField = 0; + decoder->SyncCounter = 0; decoder->FrameCounter = 0; decoder->FramesDisplayed = 0; decoder->Closing = 0; @@ -5736,6 +5737,7 @@ static void VdpauCleanup(VdpauDecoder * decoder) decoder->SurfaceWrite = 0; decoder->SurfaceField = 0; + decoder->SyncCounter = 0; decoder->FrameCounter = 0; decoder->FramesDisplayed = 0; decoder->Closing = 0;