"""Bazooka FX sounds, synthesised (Claude Opus 5.5, 2026-10-11). SL wants 44.1 kHz 16-bit mono wav. stretch.wav: rubbery creak rising in pitch as the arms pull back (~1.8 s) fire.wav: whoosh (band-swept noise) into a thump + crackle at impact (~1.4 s)""" import numpy as np, wave from pathlib import Path SR = 44100 rng = np.random.default_rng(7) here = Path(__file__).parent def save(name, x): x = x / (np.abs(x).max() + 1e-9) * 0.9 with wave.open(str(here / name), "wb") as w: w.setnchannels(1); w.setsampwidth(2); w.setframerate(SR) w.writeframes((x * 32767).astype(np.int16).tobytes()) def t_(secs): return np.arange(int(SR * secs)) / SR def bandpass(noise, centre, q=4.0): """time-varying 2-pole resonator; centre is an array of Hz per sample""" y = np.zeros_like(noise); y1 = y2 = 0.0 for i, (x, f) in enumerate(zip(noise, centre)): w = 2 * np.pi * f / SR r = np.exp(-w / (2 * q)) y0 = x + 2 * r * np.cos(w) * y1 - r * r * y2 y[i] = y0; y2, y1 = y1, y0 return y # stretch: a rubber band creak = a low sawtooth-ish tone with wobble, pitch gliding up, plus friction squeaks t = t_(1.8) f = 90 + 260 * (t / t[-1]) ** 1.6 + 6 * np.sin(2 * np.pi * 11 * t) ph = 2 * np.pi * np.cumsum(f) / SR tone = sum(np.sin(k * ph) / k for k in range(1, 7)) creak = (0.5 + 0.5 * np.sign(np.sin(2 * np.pi * (14 + 20 * t) * t))) * rng.normal(0, 1, t.size) creak = bandpass(creak, 1800 + 1500 * t / t[-1], q=6) env = np.minimum(1, t / 0.15) * np.minimum(1, (t[-1] - t) / 0.12) stretch = (tone * 0.6 + creak * 0.04) * env save("stretch.wav", stretch) # fire: 0.45 s whoosh rising, then thump at 0.45 s, then crackle tail t = t_(1.4) whoosh_env = np.where(t < 0.45, (t / 0.45) ** 2, np.exp(-(t - 0.45) / 0.12)) centre = np.where(t < 0.45, 300 + 2500 * (t / 0.45) ** 2, 2800 * np.exp(-(t - 0.45) / 0.3) + 200) whoosh = bandpass(rng.normal(0, 1, t.size), centre, q=2.5) * whoosh_env tt = np.clip(t - 0.45, 0, None) on = t >= 0.45 thump = on * np.sin(2 * np.pi * (45 + 110 * np.exp(-tt / 0.05)) * tt) * np.exp(-tt / 0.18) pop = on * rng.normal(0, 1, t.size) * np.exp(-tt / 0.02) crackle = on * (rng.random(t.size) < 0.004) * rng.normal(0, 1, t.size) * np.exp(-tt / 0.35) crackle = np.convolve(crackle, np.exp(-np.arange(60) / 8), "same") fire = whoosh / (np.abs(whoosh).max() + 1e-9) * 0.7 + thump * 1.0 + pop * 0.35 + crackle * 0.25 save("fire.wav", fire) print("ok")