Fix tabla ge_bend synth — wider sweep, longer sustain, actually audible

- Sweep range: 50→450Hz (was 60→240Hz)
- Slower sweep rate: exp(-1.5t) so ear can track it (was -4t)
- Longer sustain: decay rate 2.5 (was 6) — bend lives long enough to hear
- Removed static sub and metal that masked the sweep
- Added 2nd harmonic for richness
- Louder body (1.2 gain)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 01:48:20 -04:00
parent 150c57ed3d
commit 95b7bd830c
+19 -20
View File
@@ -3335,36 +3335,35 @@ def _synth_tabla_ge_bend(n_samples):
"""Tabla Ge with upward pitch bend — palm pressing into bayan head.
The player strikes the bayan and then presses their palm into the
head, raising the pitch dramatically. The signature bayan sound
in Bollywood and fusion music.
head, raising the pitch dramatically. The signature "woooo" bayan
sound in Bollywood and fusion music. Zakir Hussain's calling card.
"""
t = numpy.arange(n_samples, dtype=numpy.float32) / SAMPLE_RATE
# Membrane thud
thump_len = min(int(SAMPLE_RATE * 0.07), n_samples)
# Initial strike — membrane thud
thump_len = min(int(SAMPLE_RATE * 0.05), n_samples)
thump_raw = _noise(thump_len)
if thump_len > 20:
bl, al = scipy.signal.butter(2, [40, 250], btype='band', fs=SAMPLE_RATE)
bl, al = scipy.signal.butter(2, [30, 200], btype='band', fs=SAMPLE_RATE)
thump = scipy.signal.lfilter(bl, al, numpy.pad(thump_raw, (0, max(0, n_samples - thump_len))))[:thump_len]
else:
thump = thump_raw
thump *= _exp_decay(thump_len, 20) * 0.8
# Pitch sweep UP — 60 Hz rising to 200+ Hz as palm presses
# Gets quieter as pitch rises (palm mutes the head as it presses)
freq = 60 + 180 * (1 - numpy.exp(-4 * t))
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)
freq = 50 + 400 * (1 - numpy.exp(-1.5 * t))
phase = 2 * numpy.pi * numpy.cumsum(freq) / SAMPLE_RATE
body = numpy.sin(phase) * _exp_decay(n_samples, 6) * 0.9
# Metal shell resonance
metal_len = min(int(SAMPLE_RATE * 0.1), n_samples)
metal = numpy.sin(2 * numpy.pi * 150 * t[:metal_len]) * _exp_decay(metal_len, 8) * 0.3
# Sub
sub = _sine_f32(50, n_samples) * _exp_decay(n_samples, 5) * 0.4
click_len = min(250, n_samples)
click = _noise(click_len) * _exp_decay(click_len, 35) * 0.3
result = body + sub
# 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
# Second harmonic for richness (follows the sweep)
body += numpy.sin(phase * 2) * _exp_decay(n_samples, 3.5) * 0.3
# Click for attack definition
click_len = min(300, n_samples)
click = _noise(click_len) * _exp_decay(click_len, 40) * 0.25
result = body
result[:thump_len] += thump
result[:metal_len] += metal
result[:click_len] += click
return numpy.tanh(result * 1.3).astype(numpy.float32)
return numpy.tanh(result * 1.2).astype(numpy.float32)
def _synth_djembe_bass(n_samples):