Skip to content

Commit

Permalink
damc: compressor: adjust silence handling
Browse files Browse the repository at this point in the history
Silence appears in these cases:
 1. When audio is stopped to switch to something else (that might have
    a different volume)
 2. When audio is silence temporarily (eg: radio/broadcast stream
    without background music)
 3. During normal audio, when the audio signal crosses 0

In these cases, we want to:
 - Long term: tend to unity gain in case of switching to a high volume
   stream (handles 1.)
 - Short term: keep the current compression gain (handles 2. and 3.)

Use the release time as the constant time for this.
  • Loading branch information
amurzeau committed Sep 22, 2024
1 parent ab3bdb6 commit 23a27fc
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 13 deletions.
33 changes: 21 additions & 12 deletions src/damc/damc_audio_processing/CompressorFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ void CompressorFilter::reset() {

void CompressorFilter::processSamples(float** samples, size_t count) {
if(enablePeak || enableLoudness) {
bool samplesAreAllZeroes = true;
float staticGain = gainComputer(0) + makeUpGain;
for(size_t i = 0; i < count; i++) {
float levelPeak = 0;
Expand All @@ -77,9 +76,6 @@ void CompressorFilter::processSamples(float** samples, size_t count) {
}
}

if(levelPeak != 0)
samplesAreAllZeroes = false;

float dbGain = doCompression(levelPeak, levelLoudness);

// db to ratio
Expand All @@ -89,13 +85,6 @@ void CompressorFilter::processSamples(float** samples, size_t count) {
samples[channel][i] = compressionRatio * samples[channel][i];
}
}

if(samplesAreAllZeroes) {
// When no sound, avoid big amplification that would cause high volume sound when some sound is played
// Make the gain assume the volume is 0dBFS.

y1 = yL = gainComputer(0.f);
}
}
}

Expand All @@ -112,7 +101,12 @@ float CompressorFilter::doCompression(float levelPeak, float levelLoudness) {
dbSample = std::max(dbSample, lufsRealtimeLevel - lufsTarget.get());
}

levelDetectorSmoothing(gainComputer(dbSample));
if(dbSample != -INFINITY) {
levelDetectorSmoothing(gainComputer(dbSample));
} else {
// When a sample is 0, keep the current compression gain.
levelDetectorSilenceSmoothing(gainComputer(0));
}
return -yL;
}

Expand Down Expand Up @@ -153,6 +147,21 @@ void CompressorFilter::levelDetectorSmoothing(float dbCompression) {
yL = alphaA * yL + (1 - alphaA) * y1;
}

void CompressorFilter::levelDetectorSilenceSmoothing(float dbCompression) {
// Smooth out to unity gain when the input signal is silence (sample value is 0).
// Silence appears in these cases:
// 1. When audio is stopped to switch to something else (that might have a different volume)
// 2. When audio is silence temporarily (eg: radio/broadcast stream without background music)
// 3. During normal audio, when the audio signal crosses 0
//
// In these cases, we want to:
// - Long term: tend to unity gain in case of switching to a high volume stream (handles 1.)
// - Short term: keep the current compression gain (handles 2. and 3.)
// Use the release time as the constant time for this.
y1 = alphaR * y1 + (1 - alphaR) * dbCompression;
yL = alphaA * yL + (1 - alphaA) * y1;
}

void CompressorFilter::onFastTimer() {
if(enableLoudness) {
lufsMeter.set(lufsRealtimeLevel);
Expand Down
3 changes: 2 additions & 1 deletion src/damc/damc_audio_processing/CompressorFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class CompressorFilter : public OscContainer {
protected:
float doCompression(float levelPeak, float levelLoudness);
float gainComputer(float sample) const;
void levelDetectorSmoothing(float sample);
void levelDetectorSmoothing(float dbCompression);
void levelDetectorSilenceSmoothing(float dbCompression);
float levelToDbPeak(float sample);
float levelToDbLoudnessLUFS(float sample);
float levelDetectorPeak(float sample);
Expand Down

0 comments on commit 23a27fc

Please sign in to comment.