|
|
|
@@ -72,6 +72,35 @@ func NewBS412Limiter(thresholdDBr, pilotLevel, rdsInjection, chunkDurationSec fl |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// UpdateChunkDuration reconfigures the limiter for a new chunk size. |
|
|
|
// Call this from GenerateFrame when the actual chunk duration is known |
|
|
|
// (computed as samples/sampleRate) to avoid calibration errors if the |
|
|
|
// engine's chunk duration differs from the value passed to NewBS412Limiter. |
|
|
|
// Safe to call on every chunk; no-ops when duration has not changed. |
|
|
|
func (l *BS412Limiter) UpdateChunkDuration(chunkSec float64) { |
|
|
|
if chunkSec <= 0 { |
|
|
|
return |
|
|
|
} |
|
|
|
windowSec := 60.0 |
|
|
|
newBufLen := int(math.Ceil(windowSec / chunkSec)) |
|
|
|
if newBufLen < 10 { |
|
|
|
newBufLen = 10 |
|
|
|
} |
|
|
|
if newBufLen == len(l.powerBuf) { |
|
|
|
return // no change |
|
|
|
} |
|
|
|
// Resize buffer — drop history to avoid stale power readings from the |
|
|
|
// old window size distorting the rolling average. |
|
|
|
l.powerBuf = make([]float64, newBufLen) |
|
|
|
l.bufIdx = 0 |
|
|
|
l.bufFull = false |
|
|
|
l.powerSum = 0 |
|
|
|
attackTC := 2.0 / chunkSec |
|
|
|
releaseTC := 5.0 / chunkSec |
|
|
|
l.attackCoeff = 1.0 - math.Exp(-1.0/attackTC) |
|
|
|
l.releaseCoeff = 1.0 - math.Exp(-1.0/releaseTC) |
|
|
|
} |
|
|
|
|
|
|
|
// ProcessChunk measures the audio power of a chunk and returns the |
|
|
|
// gain factor to apply to the audio composite for BS.412 compliance. |
|
|
|
// Call once per chunk with the average audio power of that chunk. |
|
|
|
|