#!/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-web-audio.sh - Web audio gate, graded on the sound the page plays. # # Runs AUDIO's page in headless Chromium (scripts/lib/webDriver.mjs, which # lets it play without a click) and records what it plays: SDL3 hands the # browser its sound through a ScriptProcessorNode, and the driver keeps a # copy of every buffer the node fills, as a WAV. tools/gradeAudioPhases.py # grades it through the same six phases as the SDL3 gate -- music, paused, # SFX into the pause, resumed, the noise sweep alone, the MOD -- so the # browser's audio path (the page's audio context, SDL's resampling to its # rate) is checked as well as the mix, which is the SDL3 port's own. # # The recording, and the driver's key script, start with the first buffer # the page plays, so the phases fall where the SDL3 gate's do. # # Usage: scripts/verify-web-audio.sh # Env: WEB_AUDIO_KEEP set to keep the recording as build/web/headless-audio.wav # Requires: Chromium, emsdk's node, python3; build/web/bin/AUDIO (make web). set -uo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" source "$repo/scripts/lib/webGate.sh" webNeed grader=$repo/tools/gradeAudioPhases.py label=verify-web-audio dir=$repo/build/web/bin/AUDIO [ -f "$dir/AUDIO.html" ] || { echo "$label: build AUDIO first (make web)" >&2; exit 2; } work=$(mktemp -d -t joeylib-web-audio.XXXXXX) cleanup() { webStop rm -rf "$work" return 0 } trap cleanup EXIT webServe "$dir" # The same timeline as verify-sdl3-audio.sh (seconds since the first buffer). if ! webDrive "AUDIO.html" --seconds 120 --audio "$work/out.wav" \ --step wait:5 --step hold:p:400 \ --step wait:8 \ --step "hold: :400" --step wait:1.5 --step "hold: :400" --step wait:1.5 --step "hold: :400" --step wait:1.5 \ --step wait:4 --step hold:p:400 \ --step wait:5.6 --step hold:p:400 \ --step wait:0.6 --step hold:n:400 \ --step wait:4.6 --step hold:m:400 \ --step wait:7.6; then echo "$label: FAIL - the page could not be driven" >&2 exit 1 fi [ -s "$work/out.wav" ] || { echo "$label: FAIL - recorded no audio at all" >&2; exit 1; } # Thresholds sit at about half the measured levels (music ~3090, paused 0, # sfx ~1240, noise ~1500, mod ~7980, the grader averaging the two channels). python3 "$grader" "$label" "$work/out.wav" \ "music:1:5:1500:" \ "paused:8:13::100" \ "sfx:15:22:600:" \ "resumed:25:29:1500:" \ "noise:31.5:34:700:" \ "mod:37:43:4000:" status=$? if [ -n "${WEB_AUDIO_KEEP:-}" ]; then cp "$work/out.wav" "$repo/build/web/headless-audio.wav" fi exit $status