#!/usr/bin/env python3 """Generate the four tiny, gentle WAV effects used by Paw Play. The sounds are intentionally soft, short and free of sharp transients so they do not startle a cat. 16-bit mono / 44.1 kHz keeps the APK small. """ from __future__ import annotations import math import random import struct import wave from pathlib import Path RATE = 44100 ROOT = Path(__file__).resolve().parents[1] OUT = ROOT / "app" / "res" / "raw" def write_wav(name: str, samples: list[float], peak: float = 0.45) -> None: OUT.mkdir(parents=True, exist_ok=True) high = max(1e-9, max(abs(s) for s in samples)) scale = peak / high data = b"".join( struct.pack(" float: t = i / RATE total = n / RATE a = min(1.0, t / attack) if attack > 0 else 1.0 r = min(1.0, max(0.0, (total - t) / release)) if release > 0 else 1.0 return a * r def plop() -> list[float]: n = int(0.30 * RATE) out: list[float] = [] phase = 0.0 for i in range(n): t = i / RATE # Falling "bloop" with a tiny watery second partial. freq = 250 + 620 * math.exp(-t * 18) phase += 2 * math.pi * freq / RATE body = math.sin(phase) * math.exp(-t * 9) water = math.sin(phase * 2.01) * 0.16 * math.exp(-t * 13) out.append((body + water) * envelope(i, n, 0.006, 0.07)) return out def chime() -> list[float]: n = int(0.95 * RATE) notes = [(1046.50, 0.00), (1318.51, 0.075), (1567.98, 0.15)] out = [0.0] * n for freq, delay in notes: start = int(delay * RATE) for i in range(start, n): t = (i - start) / RATE env = math.exp(-t * 5.4) * min(1.0, t / 0.006) tone = ( math.sin(2 * math.pi * freq * t) + 0.28 * math.sin(2 * math.pi * freq * 2.0 * t) + 0.08 * math.sin(2 * math.pi * freq * 3.01 * t) ) out[i] += tone * env * 0.33 return [s * envelope(i, n, 0.003, 0.18) for i, s in enumerate(out)] def whoosh() -> list[float]: n = int(0.40 * RATE) rng = random.Random(7) out: list[float] = [] low = 0.0 band = 0.0 for i in range(n): t = i / RATE white = rng.uniform(-1.0, 1.0) low += (white - low) * 0.055 band += (white - band) * 0.025 # Airy noise that opens and closes quickly. env = math.sin(math.pi * min(1.0, t / 0.36)) ** 1.6 out.append((low - band * 0.55) * env * 0.9) return out def ping() -> list[float]: n = int(0.24 * RATE) out: list[float] = [] for i in range(n): t = i / RATE env = math.exp(-t * 22) * min(1.0, t / 0.003) tone = ( math.sin(2 * math.pi * 1700 * t) + 0.22 * math.sin(2 * math.pi * 2380 * t) ) out.append(tone * env * 0.5) return out def main() -> None: write_wav("plop.wav", plop(), peak=0.42) write_wav("chime.wav", chime(), peak=0.34) write_wav("whoosh.wav", whoosh(), peak=0.25) write_wav("ping.wav", ping(), peak=0.30) print("wrote 4 sounds to", OUT) if __name__ == "__main__": main()