2026-04-28 16:47:13 -04:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# Audio subcommands — sourcing pipeline + design app DX.
|
|
|
|
|
#
|
|
|
|
|
# The launch-pack assets are sourced via per-pack TSV mappings under
|
|
|
|
|
# `tools/audio-batch-*.tsv`. Each row goes:
|
|
|
|
|
# curl → ffmpeg loudnorm + Ogg Vorbis encode → write to assets tree →
|
|
|
|
|
# append `sources.csv` → re-render LICENSES.md → run audio-validate.py.
|
|
|
|
|
# Idempotent: re-running skips files already on disk + already in the
|
|
|
|
|
# ledger.
|
|
|
|
|
#
|
|
|
|
|
# ./run audio show status (file count, manifest health)
|
|
|
|
|
# ./run audio:fetch run every batch in tools/audio-batch-*.tsv
|
|
|
|
|
# ./run audio:fetch:01 run a single numbered batch (01/02/03/04)
|
|
|
|
|
# ./run audio:design start the design-app dev server (port 7777)
|
|
|
|
|
# ./run audio:validate python3 tools/audio-validate.py
|
|
|
|
|
# ./run audio:render regenerate LICENSES.md from sources.csv
|
|
|
|
|
#
|
|
|
|
|
# `./run validate` (in test.sh) already calls audio-validate.py +
|
|
|
|
|
# audio-licenses-render.py --check; the audio:* targets here are the
|
|
|
|
|
# write-side complement.
|
|
|
|
|
|
|
|
|
|
AUDIO_THEME="${AUDIO_THEME:-age-of-dwarves}"
|
|
|
|
|
AUDIO_ASSETS="$REPO_ROOT/public/games/$AUDIO_THEME/assets/audio"
|
|
|
|
|
AUDIO_MANIFEST="$REPO_ROOT/public/games/$AUDIO_THEME/data/audio.json"
|
|
|
|
|
AUDIO_DESIGN_APP="$REPO_ROOT/.project/designs/app"
|
|
|
|
|
AUDIO_DESIGN_PORT="${AUDIO_DESIGN_PORT:-7777}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd_audio() {
|
|
|
|
|
echo -e "${BLUE}Audio status — theme '$AUDIO_THEME'${NC}"
|
|
|
|
|
if [[ ! -f "$AUDIO_MANIFEST" ]]; then
|
|
|
|
|
echo -e " ${RED}✗ manifest missing: $AUDIO_MANIFEST${NC}"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
local ogg_count
|
|
|
|
|
ogg_count=$(find "$AUDIO_ASSETS" -name '*.ogg' 2>/dev/null | wc -l | tr -d ' ')
|
|
|
|
|
local sources_rows
|
|
|
|
|
sources_rows=$(grep -c '^audio/' "$AUDIO_ASSETS/sources.csv" 2>/dev/null || echo 0)
|
|
|
|
|
local manifest_refs
|
|
|
|
|
manifest_refs=$(python3 -c "
|
|
|
|
|
import json
|
|
|
|
|
m = json.load(open('$AUDIO_MANIFEST'))
|
|
|
|
|
n = 0
|
|
|
|
|
for e in m['sfx'].values():
|
|
|
|
|
streams = e.get('streams') or ([e['stream']] if e.get('stream') else [])
|
|
|
|
|
n += len(streams)
|
|
|
|
|
n += len(m['music']['tracks'])
|
|
|
|
|
print(n)
|
|
|
|
|
")
|
|
|
|
|
|
|
|
|
|
echo " Manifest references: $manifest_refs streams"
|
|
|
|
|
echo " Files on disk: $ogg_count .ogg"
|
|
|
|
|
echo " Sources.csv rows: $sources_rows"
|
|
|
|
|
|
|
|
|
|
if [[ -x "$REPO_ROOT/tools/audio-validate.py" ]]; then
|
|
|
|
|
echo ""
|
|
|
|
|
python3 "$REPO_ROOT/tools/audio-validate.py" --theme "$AUDIO_THEME"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo " Available batches:"
|
|
|
|
|
for tsv in "$REPO_ROOT"/tools/audio-batch-*.tsv; do
|
|
|
|
|
[[ -f "$tsv" ]] || continue
|
|
|
|
|
local rows
|
|
|
|
|
rows=$(grep -cE '^audio/' "$tsv")
|
|
|
|
|
printf " %-50s %d rows\n" "$(basename "$tsv")" "$rows"
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e " ${DIM}./run audio:fetch run every batch${NC}"
|
|
|
|
|
echo -e " ${DIM}./run audio:design open the design app at http://localhost:$AUDIO_DESIGN_PORT/audio${NC}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd_audio_validate() {
|
|
|
|
|
python3 "$REPO_ROOT/tools/audio-validate.py" --theme "$AUDIO_THEME" "$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd_audio_render() {
|
|
|
|
|
python3 "$REPO_ROOT/tools/audio-licenses-render.py" --theme "$AUDIO_THEME" "$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_audio_run_batch() {
|
|
|
|
|
local tsv="$1"
|
|
|
|
|
if [[ ! -f "$tsv" ]]; then
|
|
|
|
|
echo -e "${RED}batch not found: $tsv${NC}"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
bash "$REPO_ROOT/tools/audio-fetch-batch.sh" "$tsv"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmd_audio_fetch() {
|
|
|
|
|
# Run every TSV under tools/audio-batch-*.tsv in lexical order. Each
|
|
|
|
|
# batch is idempotent so re-running is cheap.
|
|
|
|
|
local any=0
|
|
|
|
|
local failed=0
|
|
|
|
|
for tsv in "$REPO_ROOT"/tools/audio-batch-*.tsv; do
|
|
|
|
|
[[ -f "$tsv" ]] || continue
|
|
|
|
|
any=1
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e "${BLUE}── $(basename "$tsv") ─────────────────${NC}"
|
|
|
|
|
if ! _audio_run_batch "$tsv"; then
|
|
|
|
|
failed=$((failed + 1))
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
if [[ $any -eq 0 ]]; then
|
|
|
|
|
echo -e "${YELLOW}No tools/audio-batch-*.tsv files found.${NC}"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
if [[ $failed -gt 0 ]]; then
|
|
|
|
|
echo ""
|
|
|
|
|
echo -e "${RED}$failed batch(es) had failures — see output above${NC}"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Numbered batch shortcuts: ./run audio:fetch:01 → tools/audio-batch-01-*.tsv
|
|
|
|
|
cmd_audio_fetch_01() { _audio_fetch_numbered 01; }
|
|
|
|
|
cmd_audio_fetch_02() { _audio_fetch_numbered 02; }
|
|
|
|
|
cmd_audio_fetch_03() { _audio_fetch_numbered 03; }
|
|
|
|
|
cmd_audio_fetch_04() { _audio_fetch_numbered 04; }
|
|
|
|
|
cmd_audio_fetch_05() { _audio_fetch_numbered 05; }
|
|
|
|
|
cmd_audio_fetch_06() { _audio_fetch_numbered 06; }
|
|
|
|
|
cmd_audio_fetch_07() { _audio_fetch_numbered 07; }
|
|
|
|
|
cmd_audio_fetch_08() { _audio_fetch_numbered 08; }
|
|
|
|
|
cmd_audio_fetch_09() { _audio_fetch_numbered 09; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_audio_fetch_numbered() {
|
|
|
|
|
local n="$1"
|
|
|
|
|
local matches=( "$REPO_ROOT"/tools/audio-batch-${n}-*.tsv )
|
|
|
|
|
if [[ ! -f "${matches[0]}" ]]; then
|
|
|
|
|
echo -e "${RED}no batch matching tools/audio-batch-${n}-*.tsv${NC}"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
_audio_run_batch "${matches[0]}"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-04-28 17:39:46 -04:00
|
|
|
cmd_audio_options() {
|
|
|
|
|
bash "$REPO_ROOT/tools/audio-fetch-options.sh" "$@"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-04-28 16:47:13 -04:00
|
|
|
cmd_audio_design() {
|
|
|
|
|
if [[ ! -d "$AUDIO_DESIGN_APP" ]]; then
|
|
|
|
|
echo -e "${RED}design app not found: $AUDIO_DESIGN_APP${NC}"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
if [[ ! -d "$AUDIO_DESIGN_APP/node_modules" ]]; then
|
|
|
|
|
echo -e "${BLUE}Installing design-app dependencies...${NC}"
|
|
|
|
|
(cd "$AUDIO_DESIGN_APP" && pnpm install) || return 1
|
|
|
|
|
fi
|
|
|
|
|
echo -e "${BLUE}Starting audio design app on http://localhost:$AUDIO_DESIGN_PORT/audio${NC}"
|
|
|
|
|
exec pnpm --dir "$AUDIO_DESIGN_APP" dev -- --port "$AUDIO_DESIGN_PORT"
|
|
|
|
|
}
|