import numpy as np import soundfile as sf SAMPLE_RATE = 44100 DURATION = 1.2 def piano_key_frequency(n): return 2 ** ((n - 49) / 12) * 440.0 def generate_tone(n, frequency): samples = int(SAMPLE_RATE * DURATION) t = np.linspace(0, DURATION, samples, False) tone = np.zeros(samples) # Two slightly detuned strings per note (chorus) for detune in [-0.3, 0.3]: f = frequency * (1 + detune / 1200) # Rich harmonics with bright, metallic decay for h in range(1, 16): amp = 1.0 / (h ** 1.2) # bright: harmonics stay loud decay = 5.0 + h * 1.5 # faster overall decay tone += amp * np.exp(-decay * t) * np.sin(2 * np.pi * f * h * t) # Sharp pluck-like attack (2 ms) tone *= np.minimum(t / 0.002, 1.0) # Fast exponential decay -- plucked string feel tone *= np.exp(-4.0 * t) # Pluck transient: bright click at the start (5 ms) click = np.random.randn(samples) * np.exp(-t / 0.003) tone += 0.08 * click peak = np.max(np.abs(tone)) if peak > 0: tone *= 0.4 / peak return tone for n in range(1, 89): f = piano_key_frequency(n) sf.write(f"piano_key_{n}.wav", generate_tone(n, f), SAMPLE_RATE) print(f"piano_key_{n}.wav ({f:.1f} Hz)") print("Done.")