#!/usr/bin/env bash # Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # verify-psp-audio.sh - PSP audio gate, graded on the sound itself. # # The PSP port mixes everything in software (src/hosted/audio.c, the sdl3 # port's mixer) and plays the mix through SDL3's PSP audio driver, which # hands it to the PSP's audio channels. PPSSPPHeadless (scripts/lib/pspGate.sh) # records what reaches them (--dump-audio: PPSSPP's own recording, a 44.1 kHz # stereo WAV on the emulated clock) while AUDIOPRB runs from its folder on a # private memory stick, with every memory access checked as a PSP checks it. # # AUDIOPRB (make/examples.mk) is examples/audio pressing its own keys: the # PSP has none to type with. An --input script presses Select at # QUIT_MS, which the port gives as Escape: AUDIOPRB must quit on it, which # also ends the run and the recording. scripts/lib/pspAudioGrade.py grades # the recording: the tracker song alone at the start, three streamed takes # loud and each at its own pitch (so the PSP plays the mix at the rate it # was made for), and the end at Select. # # Usage: scripts/verify-psp-audio.sh [program folder] # Default build/psp/probe/AUDIOPRB (make -f make/psp.mk # psp-verify-audio builds it and runs this). # Requires: PPSSPPHeadless, python3; AUDIOPRB built for the PSP. set -uo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" source "$repo/scripts/lib/pspGate.sh" pspNeed label=verify-psp-audio dir=${1:-$repo/build/psp/probe/AUDIOPRB} [ -f "$dir/EBOOT.PBP" ] || { echo "$label: build AUDIOPRB first (make -f make/psp.mk psp-verify-audio)" >&2; exit 2; } # Real seconds the run may take, and when (emulated milliseconds since # boot, the recording's start) Select is pressed: past the third take. runSeconds=60 quitMs=6000 msPerSecond=1000 work=$(mktemp -d -t joeylib-psp-audio.XXXXXX) cleanup() { pspStop rm -rf "$work" } trap cleanup EXIT printf '%d buttons select\n' "$quitMs" > "$work/input.txt" folder=$(pspStage "$work" "$dir") pspRun "$work" "$folder" "$runSeconds" --dump-audio --input="$work/input.txt" pspWait pspStrictCheck "$work" "$dir" || { echo "$label: FAIL - a bad memory access" >&2; exit 1; } if grep -q '^TIMEOUT' "$work/ppsspp.log"; then echo "$label: FAIL - AUDIOPRB did not quit on Select (Escape)" >&2 exit 1 fi wav=$(find "$work/.ppsspp/PSP/AUDIO" -name '*.wav' -print -quit 2> /dev/null) [ -n "$wav" ] || { echo "$label: FAIL - PPSSPP recorded nothing" >&2; exit 1; } python3 "$repo/scripts/lib/pspAudioGrade.py" "$label" "$wav" "$(awk -v ms="$quitMs" -v k="$msPerSecond" 'BEGIN { print ms / k }')"