fix(mix): reduce waveform smoothing to 15 ms; turn off DEBUG flags

This commit is contained in:
daniel-c-harvey
2026-06-17 06:33:03 -04:00
parent d6df0de63a
commit ea74aaaf2e
3 changed files with 13 additions and 17 deletions
@@ -3,19 +3,20 @@ namespace DeepDrftContent.Processors;
/// <summary>
/// Loudness via root-mean-square amplitude per time bucket. Decodes signed PCM (8-bit unsigned,
/// 16/24/32-bit signed little-endian), averages channels to mono, partitions the frames into
/// equal time slices, takes the RMS of each slice, applies a ~50 ms envelope-follower smoothing
/// equal time slices, takes the RMS of each slice, applies a ~15 ms envelope-follower smoothing
/// so the contour reads as a smooth curve rather than a spikey polygon, then peak-normalizes so
/// the loudest bucket is 1. No external audio dependency — operates directly on the WAV data-chunk bytes.
/// </summary>
public class RmsLoudnessAlgorithm : ILoudnessAlgorithm
{
/// <summary>
/// Envelope-follower time constant, seconds. ~50 ms is the spec's smoothing target (Phase 10
/// tuning): long enough to round off the per-bucket RMS spikes into a smooth ribbon contour,
/// short enough that real loudness transients (kicks, drops) still read. Applied as a symmetric
/// (forward+backward) one-pole filter so the smoothing introduces no time lag.
/// Envelope-follower time constant, seconds. ~15 ms is the smoothing target (Phase 10
/// tuning, reduced from 50 ms which was over-smoothed): long enough to round off the
/// per-bucket RMS spikes into a smooth ribbon contour, short enough that real loudness
/// transients (kicks, drops) still read. Applied as a symmetric (forward+backward) one-pole
/// filter so the smoothing introduces no time lag.
/// </summary>
public const double SmoothingTimeConstantSeconds = 0.05;
public const double SmoothingTimeConstantSeconds = 0.015;
public double[] Compute(ReadOnlySpan<byte> pcmData, int channels, int sampleRate, int bitsPerSample, int bucketCount)
{
@@ -81,7 +82,7 @@ public class RmsLoudnessAlgorithm : ILoudnessAlgorithm
}
}
// Envelope smoothing (~50 ms): round the spikey per-bucket RMS into a smooth contour before
// Envelope smoothing (~15 ms): round the spikey per-bucket RMS into a smooth contour before
// peak-normalization, so the rendered ribbon reads as a continuous curve, not faceted polygons.
// Each bucket spans (totalSeconds / bucketCount) of audio; the filter coefficient is derived
// from that against the time constant so the smoothing is duration-aware, not a fixed window.
@@ -117,7 +118,7 @@ public class RmsLoudnessAlgorithm : ILoudnessAlgorithm
/// Symmetric one-pole envelope smoothing over the per-bucket loudness, in place. A forward pass
/// then a backward pass cancels the single-pole phase lag, so the smoothed contour stays aligned
/// with the audio (no rightward time shift). The coefficient <c>a = exp(bucketSeconds / τ)</c>
/// gives a ~<paramref name="bucketSeconds"/>-relative response targeting the ~50 ms time constant:
/// gives a ~<paramref name="bucketSeconds"/>-relative response targeting the ~15 ms time constant:
/// each bucket blends <c>(1 a)</c> of itself with <c>a</c> of the running envelope. A near-zero
/// or non-finite bucket duration leaves the data untouched (nothing to smooth meaningfully).
/// </summary>