"""Did the Ableton renders pass through a limiter / normaliser? This decides whether a Python linear crossfade can stand in for an Ableton render at a lower send level. If the chain is purely linear (sum of dry + reverb return, no dynamics), then 0.7*dry + 0.3*(dry+reverb) = dry + 0.3*reverb is EXACTLY an Ableton render at 30% send, and Python is equivalent. A limiter breaks that. It is level-dependent and non-linear, so a render at 30% send hits it differently than the 100% render did -- and crossfading afterwards cannot reproduce that. The tell is a hard ceiling: many files peaking at the same value rather than scattered. """ import wave from collections import Counter from pathlib import Path import numpy as np DATA = Path("/workspace/Demos/data/acoustic-space-ableton/audio") def peak_db(p): with wave.open(str(p), "rb") as w: n, ch, sw = w.getnframes(), w.getnchannels(), w.getsampwidth() raw = w.readframes(n) if sw == 3: # 24-bit a = np.frombuffer(raw, dtype=np.uint8).reshape(-1, 3).astype(np.int32) x = (a[:, 0] | (a[:, 1] << 8) | (a[:, 2] << 16)) x = np.where(x & 0x800000, x - 0x1000000, x).astype(float) / 8388608.0 else: x = np.frombuffer(raw, dtype=np.int16).astype(float) / 32768.0 if x.size == 0: return None return 20 * np.log10(np.abs(x).max() + 1e-12) for label in ("references", "targets"): peaks = [] for p in sorted((DATA / label).glob("*.wav")): d = peak_db(p) if d is not None: peaks.append(round(d, 2)) if not peaks: continue print(f"=== {label}: {len(peaks)} files ===") print(f" peak range: {min(peaks):.2f} .. {max(peaks):.2f} dBFS") common = Counter(peaks).most_common(5) print(" most common peak values:") for v, c in common: bar = "#" * min(c, 40) print(f" {v:>7.2f} dBFS x{c:<3} {bar}") ceiling = [p for p in peaks if p > -0.5] print(f" files peaking above -0.5 dBFS: {len(ceiling)} of {len(peaks)} " f"({100.0*len(ceiling)/len(peaks):.0f}%)") print() print("A tight cluster at one value just below 0 => a ceiling was applied") print("(limiter or normaliser), so the render chain is NOT purely linear and an") print("Ableton render at lower send will differ from a Python crossfade.") print("A broad scatter => linear sum, and Python is mathematically equivalent.")