fix(audio): replace synthesized catalog tones with preview WAVs (#708)

#707 wrote generated start/stop files for the family picker. Swap those
for the downloaded preview bytes (voca is pair 05) and skip the catalog
ids in generate_sounds.py so they stay put.
This commit is contained in:
Jatin K Malik
2026-08-18 22:02:18 -07:00
committed by GitHub
parent d8ff7052cd
commit d946668319
41 changed files with 26 additions and 54 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+26 -54
View File
@@ -5,7 +5,9 @@ Writes 16-bit PCM mono files at 44.1 kHz into resources/sounds/:
- start_recording.wav / stop_recording.wav / error.wav: the original Linux
pair. Kept on disk; not used as the implicit default anymore.
- {id}_start.wav / {id}_stop.wav for each family tone except Off.
Family catalog pairs ({id}_start.wav / {id}_stop.wav) are downloaded preview
bytes. This script never synthesizes or overwrites them.
Usage:
python scripts/generate_sounds.py
@@ -15,7 +17,6 @@ from __future__ import annotations
import math
import os
import shutil
import struct
import wave
@@ -207,59 +208,30 @@ def main() -> None:
lambda: generate_glide_tone(error_path, E4, C4, duration=0.7, amplitude=0.14),
)
# lift: Linux-family F4→A4 sine glide (own files; does not replace the originals)
generate_glide_tone(os.path.join(sounds_dir, "lift_start.wav"), F4, A4, 0.48, 0.16)
generate_glide_tone(os.path.join(sounds_dir, "lift_stop.wav"), A4, F4, 0.48, 0.16)
# Family catalog pairs are downloaded preview bytes. Never synthesize or
# overwrite them.
family_ids = (
"lift",
"flick",
"ember",
"step",
"voca",
"soft",
"chirp",
"scale",
"drop",
"glass",
)
family_names = {f"{tone_id}_{kind}.wav" for tone_id in family_ids for kind in ("start", "stop")}
for name in sorted(family_names):
path = os.path.join(sounds_dir, name)
if os.path.exists(path):
print(f"Keeping downloaded catalog: {path}")
else:
print(f"Missing catalog WAV (not synthesizing): {path}")
# flick: same interval, shorter
generate_glide_tone(os.path.join(sounds_dir, "flick_start.wav"), F4, A4, 0.18, 0.15)
generate_glide_tone(os.path.join(sounds_dir, "flick_stop.wav"), A4, F4, 0.18, 0.15)
# ember: low warm G3→C4
generate_glide_tone(os.path.join(sounds_dir, "ember_start.wav"), G3, C4, 0.55, 0.15)
generate_glide_tone(os.path.join(sounds_dir, "ember_stop.wav"), C4, G3, 0.55, 0.15)
# step: two soft C/E ticks
generate_ticks(os.path.join(sounds_dir, "step_start.wav"), (C4, E4), 0.07, 0.05, 0.11)
generate_ticks(os.path.join(sounds_dir, "step_stop.wav"), (E4, C4), 0.07, 0.05, 0.11)
# voca: open fifth swell (id is voca, not fifth)
generate_fifth_swell(os.path.join(sounds_dir, "voca_start.wav"), C4, G4, 0.44, 0.14, True)
generate_fifth_swell(os.path.join(sounds_dir, "voca_stop.wav"), C4, G4, 0.40, 0.13, False)
# soft: very short muted ticks
generate_ticks(os.path.join(sounds_dir, "soft_start.wav"), (C5,), 0.05, 0.0, 0.07, decay=22.0)
generate_ticks(os.path.join(sounds_dir, "soft_stop.wav"), (A4,), 0.055, 0.0, 0.07, decay=22.0)
# chirp: light high chirp
generate_glide_tone(os.path.join(sounds_dir, "chirp_start.wav"), A5, C6, 0.09, 0.10)
generate_glide_tone(os.path.join(sounds_dir, "chirp_stop.wav"), C6, A5, 0.10, 0.10)
# scale: pentatonic A4→C5
generate_scale(os.path.join(sounds_dir, "scale_start.wav"), (A4, C5), 0.09, 0.025, 0.12)
generate_scale(os.path.join(sounds_dir, "scale_stop.wav"), (C5, A4), 0.09, 0.025, 0.12)
# drop: low start, deeper stop
generate_glide_tone(os.path.join(sounds_dir, "drop_start.wav"), D3, F3, 0.40, 0.16)
generate_glide_tone(os.path.join(sounds_dir, "drop_stop.wav"), C3, G2, 0.48, 0.16)
# glass: thin glass ping
generate_ping(os.path.join(sounds_dir, "glass_start.wav"), E7, 0.30, 0.10)
generate_ping(os.path.join(sounds_dir, "glass_stop.wav"), C7, 0.34, 0.09)
# Package data lives in src/vocalinux/resources and is what ResourceManager
# prefers when running from a checkout. Keep both trees in sync.
packaged_dir = os.path.join(repo_root, "src", "vocalinux", "resources", "sounds")
os.makedirs(packaged_dir, exist_ok=True)
for name in os.listdir(sounds_dir):
if not name.endswith(".wav"):
continue
if name in {"start_recording.wav", "stop_recording.wav", "error.wav"}:
continue
shutil.copy2(os.path.join(sounds_dir, name), os.path.join(packaged_dir, name))
print(f"Copied: {os.path.join(packaged_dir, name)}")
print("\nCatalog pairs written. Original start/stop/error files were left in place.")
print("\nOriginal start/stop/error files were left in place.")
print("Family catalog WAVs were not written.")
if __name__ == "__main__":
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.