Boxy cajón: box resonance modes, plywood character, hollow mids

Bass has 180/320Hz box resonance modes. Slap has wood panel
resonance under the wire buzz. Tap has hollow finger-on-plywood.
Everything sounds like hitting a wooden box now.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 16:48:55 -04:00
parent 248594fb21
commit 2e5b18de2e
2 changed files with 41 additions and 34 deletions
BIN
View File
Binary file not shown.
+41 -34
View File
@@ -2794,60 +2794,67 @@ def _synth_doumbek_ka(n_samples):
def _synth_cajon_bass(n_samples):
"""Cajón bass — palm strike on center of the face.
Deep woody thump. The box resonates like a bass drum but with
a warmer, more wooden character.
You're hitting a wooden box. The front panel flexes, the air
inside resonates, and the whole thing booms with a hollow,
boxy midrange character.
"""
t = numpy.arange(n_samples, dtype=numpy.float32) / SAMPLE_RATE
# Wooden box thump
thump_len = min(int(SAMPLE_RATE * 0.06), n_samples)
# Box body resonance — hollow wooden chamber tone
body = numpy.sin(2 * numpy.pi * 80 * t) * _exp_decay(n_samples, 6) * 0.7
# Box resonance modes — the boxy character
box1 = numpy.sin(2 * numpy.pi * 180 * t) * _exp_decay(n_samples, 12) * 0.4
box2 = numpy.sin(2 * numpy.pi * 320 * t) * _exp_decay(n_samples, 18) * 0.2
# Palm thump on plywood
thump_len = min(int(SAMPLE_RATE * 0.08), n_samples)
thump_raw = _noise(thump_len)
import scipy.signal as _sig
if thump_len > 20:
bl, al = _sig.butter(2, [40, 200], btype='band', fs=SAMPLE_RATE)
thump = _sig.lfilter(bl, al, numpy.pad(thump_raw, (0, max(0, n_samples - thump_len))))[:thump_len].astype(numpy.float32)
bl, al = scipy.signal.butter(2, [60, 400], btype='band', fs=SAMPLE_RATE)
thump = scipy.signal.lfilter(bl, al, numpy.pad(thump_raw, (0, max(0, n_samples - thump_len))))[:thump_len].astype(numpy.float32)
else:
thump = thump_raw
thump *= _exp_decay(thump_len, 18) * 0.8
body = numpy.sin(2 * numpy.pi * 70 * t) * _exp_decay(n_samples, 7) * 0.8
sub = _sine_f32(45, n_samples) * _exp_decay(n_samples, 9) * 0.4
click_len = min(200, n_samples)
click = _noise(click_len) * _exp_decay(click_len, 45) * 0.3
result = body + sub
thump *= _exp_decay(thump_len, 14) * 0.7
# Panel flex — low thud
sub = _sine_f32(50, n_samples) * _exp_decay(n_samples, 8) * 0.4
result = body + box1 + box2 + sub
result[:thump_len] += thump
result[:click_len] += click
return numpy.tanh(result * 1.3).astype(numpy.float32)
return numpy.tanh(result * 1.4).astype(numpy.float32)
def _synth_cajon_slap(n_samples):
"""Cajón slap — fingers near the top edge, snare wires buzz.
Bright crack with a buzzy rattle from the internal snare wires.
The signature cajón sound — like a snare but woodier.
Bright crack on the plywood edge with snare wire rattle
and the box resonance underneath. Wood + wire.
"""
t = numpy.arange(n_samples, dtype=numpy.float32) / SAMPLE_RATE
# Snare wire buzz
wire = _noise(n_samples) * _exp_decay(n_samples, 18) * 0.6
import scipy.signal as _sig
bl, al = _sig.butter(2, [1500, 6000], btype='band', fs=SAMPLE_RATE)
wire = _sig.lfilter(bl, al, wire).astype(numpy.float32) * 1.2
# Wood body
body = numpy.sin(2 * numpy.pi * 200 * t) * _exp_decay(n_samples, 22) * 0.4
# Sharp slap
slap_len = min(int(SAMPLE_RATE * 0.008), n_samples)
slap = _noise(slap_len) * _exp_decay(slap_len, 200) * 0.8
result = body + wire
wire_len = min(int(SAMPLE_RATE * 0.06), n_samples)
wire = _noise(wire_len) * _exp_decay(wire_len, 20) * 0.5
if wire_len > 20:
bl, al = scipy.signal.butter(2, [1500, 5000], btype='band', fs=SAMPLE_RATE)
wire = scipy.signal.lfilter(bl, al, numpy.pad(wire, (0, max(0, n_samples - wire_len))))[:wire_len].astype(numpy.float32)
# Wood panel resonance — boxy mid
body = numpy.sin(2 * numpy.pi * 220 * t) * _exp_decay(n_samples, 25) * 0.35
box = numpy.sin(2 * numpy.pi * 380 * t) * _exp_decay(n_samples, 35) * 0.15
# Sharp edge slap — hand on plywood
slap_len = min(int(SAMPLE_RATE * 0.005), n_samples)
slap = _noise(slap_len) * _exp_decay(slap_len, 250) * 0.9
result = body + box
result[:wire_len] += wire
result[:slap_len] += slap
return numpy.tanh(result * 1.5).astype(numpy.float32)
return numpy.tanh(result * 1.6).astype(numpy.float32)
def _synth_cajon_tap(n_samples):
"""Cajón tap — light fingertip on the face. Ghost note."""
n = min(n_samples, int(SAMPLE_RATE * 0.04))
"""Cajón tap — light fingertip on the plywood face. Ghost note."""
n = min(n_samples, int(SAMPLE_RATE * 0.05))
t = numpy.arange(n, dtype=numpy.float32) / SAMPLE_RATE
tap = numpy.sin(2 * numpy.pi * 300 * t) * _exp_decay(n, 35) * 0.3
pop = _noise(min(50, n)) * _exp_decay(min(50, n), 250) * 0.5
result = tap
result[:min(50, n)] += pop
# Finger on wood — hollow tap
tap = numpy.sin(2 * numpy.pi * 280 * t) * _exp_decay(n, 40) * 0.3
box = numpy.sin(2 * numpy.pi * 450 * t) * _exp_decay(n, 55) * 0.12
pop = _noise(min(60, n)) * _exp_decay(min(60, n), 200) * 0.4
result = tap + box
result[:min(60, n)] += pop
out = numpy.zeros(n_samples, dtype=numpy.float32)
out[:n] = numpy.tanh(result * 1.5)
return out