nodes/audio.pyΒΆ
Part of Tower Defence.
1"""Procedural audio: built on the engine's AudioSynth API.
2
3Replaces the upstream's bundled shot.wav (no licence grant) with a
4sound generated at load time. The sweep keeps a small amount of
5bespoke numpy because AudioSynth oscillators have constant frequency
6(same pattern as the other ports).
7"""
8
9from __future__ import annotations
10
11import math
12
13import numpy as np
14
15from simvx.core import AudioClip
16
17SAMPLE_RATE = 44100
18NCHANNELS = 2
19
20
21def make_shot() -> AudioClip:
22 """Turret shot: filtered noise crack over a fast downward thump."""
23 n = int(SAMPLE_RATE * 0.16)
24 rng = np.random.default_rng(3)
25 noise = rng.uniform(-1, 1, n).astype(np.float32) * 0.35
26 noise *= np.exp(np.linspace(0.0, -9.0, n, dtype=np.float32)) # sharp decay
27 freq = np.linspace(220, 70, n)
28 thump = np.sin(2 * math.pi * np.cumsum(freq) / SAMPLE_RATE).astype(np.float32) * 0.30
29 thump *= np.exp(np.linspace(0.0, -6.0, n, dtype=np.float32))
30 mono = noise + thump
31 out = np.empty(mono.size * NCHANNELS, dtype=np.float32)
32 out[0::NCHANNELS] = mono
33 out[1::NCHANNELS] = mono
34 return AudioClip.from_pcm(out, sample_rate=SAMPLE_RATE, channels=NCHANNELS, name="shot")
35
36
37__all__ = ["make_shot"]