Adds audio normalize support.

This commit is contained in:
Johns 2012-04-19 16:01:20 +02:00
parent 8039e8ae04
commit 44ca71fedb
4 changed files with 99 additions and 28 deletions

View File

@ -157,27 +157,28 @@ Setup: /etc/vdr/setup.conf
0 = none, 1 = downmix 0 = none, 1 = downmix
downmix AC-3 to stero. downmix AC-3 to stero.
softhddevice.AudioSoftvol softhddevice.AudioSoftvol = 0
FIXME: 0 = off, use hardware volume control
1 = on, use software volume control
softhddevice.AudioNormalize softhddevice.AudioNormalize = 0
FIXME: 0 = off, 1 = enable audio normalize
softhddevice.AudioMaxNormalize softhddevice.AudioMaxNormalize = 0
FIXME: maximal volume factor/1000 of the normalize filter
softhddevice.AudioCompression softhddevice.AudioCompression = 0
FIXME: 0 = off, 1 = enable audio compression
softhddevice.AudioMaxCompression softhddevice.AudioMaxCompression = 0
FIXME: maximal volume factor/1000 of the compression filter
softhddevice.AudioStereoDescent softhddevice.AudioStereoDescent = 0
FIXME: reduce volume level (/1000) for stereo sources
softhddevice.AudioBufferTime
FIXME:
softhddevice.AudioBufferTime = 0
0 = default (336 ms)
1 - 1000 = size of the buffer in ms
softhddevice.AutoCrop.Interval = 0 softhddevice.AutoCrop.Interval = 0
0 disables auto-crop 0 disables auto-crop

90
audio.c
View File

@ -48,6 +48,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <libintl.h> #include <libintl.h>
#define _(str) gettext(str) ///< gettext shortcut #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 AudioCompression; ///< flag use compress volume
static char AudioMute; ///< flag muted static char AudioMute; ///< flag muted
static int AudioAmplifier; ///< software volume factor 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 AudioMaxNormalize; ///< max. normalize factor
static int AudioCompressionFactor; ///< current compression factor static int AudioCompressionFactor; ///< current compression factor
static int AudioMaxCompression; ///< max. compression factor static int AudioMaxCompression; ///< max. compression factor
@ -205,12 +208,13 @@ static const unsigned AudioRatesTable[AudioRatesMax] = {
// filter // 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 /// 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 AudioNormIndex; ///< index into average table
static int AudioNormReady; ///< index counter
static int AudioNormCounter; ///< sample counter static int AudioNormCounter; ///< sample counter
/** /**
@ -222,21 +226,77 @@ static int AudioNormCounter; ///< sample counter
static void AudioNormalizer(int16_t * samples, int count) static void AudioNormalizer(int16_t * samples, int count)
{ {
int i; int i;
int l;
int n; int n;
uint32_t avg; uint32_t avg;
int factor;
int16_t *data;
// average samples // average samples
avg = 0; l = count / AudioBytesProSample;
n = count / AudioBytesProSample; data = samples;
for (i = 0; i < n; ++i) { 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; int t;
t = samples[i]; t = (samples[i] * AudioNormalizeFactor) / 1000;
avg += t * t; if (t < INT16_MIN) {
avg /= 2; 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) static void AudioResetNormalizer(void)
{ {
int i;
AudioNormCounter = 0;
AudioNormReady = 0;
for (i = 0; i < AudioNormMaxIndex; ++i) {
AudioNormAverage[i] = 0U;
}
AudioNormalizeFactor = 1000;
} }
/** /**

View File

@ -690,9 +690,9 @@ void cMenuSetupSoft::Create(void)
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol, Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
tr("Hardware"), tr("Software"))); tr("Hardware"), tr("Software")));
Add(new cMenuEditBoolItem(tr("Enable normalize volume"), 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)"), Add(new cMenuEditIntItem(tr(" Max normalize factor (/1000)"),
&AudioMaxNormalize, 0, 5000)); &AudioMaxNormalize, 0, 10000));
Add(new cMenuEditBoolItem(tr("Enable volume compression"), Add(new cMenuEditBoolItem(tr("Enable volume compression"),
&AudioCompression, trVDR("no"), trVDR("yes"))); &AudioCompression, trVDR("no"), trVDR("yes")));
Add(new cMenuEditIntItem(tr(" Max compression factor (/1000)"), Add(new cMenuEditIntItem(tr(" Max compression factor (/1000)"),

View File

@ -1857,6 +1857,7 @@ static void VaapiCleanup(VaapiDecoder * decoder)
decoder->SurfaceWrite = 0; decoder->SurfaceWrite = 0;
decoder->SurfaceField = 0; decoder->SurfaceField = 0;
decoder->SyncCounter = 0;
decoder->FrameCounter = 0; decoder->FrameCounter = 0;
decoder->FramesDisplayed = 0; decoder->FramesDisplayed = 0;
decoder->Closing = 0; decoder->Closing = 0;
@ -5736,6 +5737,7 @@ static void VdpauCleanup(VdpauDecoder * decoder)
decoder->SurfaceWrite = 0; decoder->SurfaceWrite = 0;
decoder->SurfaceField = 0; decoder->SurfaceField = 0;
decoder->SyncCounter = 0;
decoder->FrameCounter = 0; decoder->FrameCounter = 0;
decoder->FramesDisplayed = 0; decoder->FramesDisplayed = 0;
decoder->Closing = 0; decoder->Closing = 0;