From 9e85a48d0e24687eaad2573521e30bafe6cd7be7 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 30 Mar 2026 01:50:49 -0400 Subject: [PATCH] =?UTF-8?q?Fix=20ge=5Fbend=20decay=20=E2=80=94=20envelope?= =?UTF-8?q?=20was=20killing=20the=20sweep=20before=20it=20was=20audible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced _exp_decay (which uses sample-count-based decay and was too fast) with a direct time-based exponential: exp(-0.8*t) giving ~1.2s of signal. The sweep from 50→450Hz is now actually hearable. Co-Authored-By: Claude Opus 4.6 (1M context) --- pytheory/play.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pytheory/play.py b/pytheory/play.py index 79feebe..8cd480e 100644 --- a/pytheory/play.py +++ b/pytheory/play.py @@ -3350,20 +3350,21 @@ def _synth_tabla_ge_bend(n_samples): thump *= _exp_decay(thump_len, 25) * 0.7 # THE SWEEP — this is the whole point. Palm presses into the head, # pitch rises from deep bass to a singing tone. - # Slow sweep (-1.5*t) so the ear can track it, wide range (50→450Hz) + # Slow sweep so the ear can track it, wide range (50→450Hz) freq = 50 + 400 * (1 - numpy.exp(-1.5 * t)) phase = 2 * numpy.pi * numpy.cumsum(freq) / SAMPLE_RATE - # Longer sustain so the sweep is heard — decay rate 2.5 not 6 - body = numpy.sin(phase) * _exp_decay(n_samples, 2.5) * 1.2 + # Very slow decay — the sweep MUST be audible for at least 1 second + env = numpy.exp(-0.8 * t) # -0.8 gives ~1.2s of usable signal + body = numpy.sin(phase) * env * 1.3 # Second harmonic for richness (follows the sweep) - body += numpy.sin(phase * 2) * _exp_decay(n_samples, 3.5) * 0.3 + body += numpy.sin(phase * 2) * env * 0.3 # Click for attack definition click_len = min(300, n_samples) - click = _noise(click_len) * _exp_decay(click_len, 40) * 0.25 + click = _noise(click_len) * _exp_decay(click_len, 40) * 0.2 result = body result[:thump_len] += thump result[:click_len] += click - return numpy.tanh(result * 1.2).astype(numpy.float32) + return numpy.tanh(result * 1.1).astype(numpy.float32) def _synth_djembe_bass(n_samples):