aboutsummaryrefslogtreecommitdiff
path: root/scripts/normalize-notify-sounds.sh
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-21 20:16:34 -0400
committerCraig Jennings <c@cjennings.net>2026-05-21 20:16:34 -0400
commitf7079db3aa3e0073df6ce5409d4b6de0a431e26f (patch)
treee6ed90fdbd40c0122c4a2cd6c4ac25b34cb02be6 /scripts/normalize-notify-sounds.sh
parentd6fa23bb592ce4184c3a8b62de5cb6826f874ee2 (diff)
downloadarchsetup-f7079db3aa3e0073df6ce5409d4b6de0a431e26f.tar.gz
archsetup-f7079db3aa3e0073df6ce5409d4b6de0a431e26f.zip
feat(notify): add --silent flag, volume knob, and level sound files
The touchpad toggle's notification was too loud, and the eight notify sounds varied by ~13 dB in RMS loudness — bug and fail came out two to three times louder than info or security. I added a --silent flag to notify (shows the popup, plays no sound) and a NOTIFY_VOLUME knob (paplay scale, default 65536) so the master level can drop without re-encoding. toggle-touchpad now passes --silent on both enable and disable. normalize-notify-sounds.sh measures each .ogg and shifts it to a uniform -31 dB mean. It writes through the file instead of mv-ing over it, so the stow symlinks survive when the script runs against the live sound dir. I re-encoded all eight sounds to the new level. Tests: a new tests/notify suite (12 tests) covers --silent, the volume knob, flag composition, and the error paths.
Diffstat (limited to 'scripts/normalize-notify-sounds.sh')
-rwxr-xr-xscripts/normalize-notify-sounds.sh48
1 files changed, 48 insertions, 0 deletions
diff --git a/scripts/normalize-notify-sounds.sh b/scripts/normalize-notify-sounds.sh
new file mode 100755
index 0000000..52c1d36
--- /dev/null
+++ b/scripts/normalize-notify-sounds.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Normalize notify sound files to a uniform RMS loudness so every notification
+# plays at the same perceived level. Re-encodes each file in place (ogg -> ogg).
+# Run once after adding or changing a sound in the notify set.
+#
+# Each file is measured with ffmpeg's volumedetect, then shifted by a constant
+# gain so its mean (RMS) volume lands on TARGET_DB. Peaks sit near 0 dB already,
+# so the spread was all in the RMS; leveling the RMS makes them match by ear.
+#
+# Usage:
+# normalize-notify-sounds.sh [SOUND_DIR]
+#
+# Environment:
+# TARGET_DB Target mean (RMS) loudness in dB. Default -31 (gentle + even).
+# Lower is quieter. The notify script's NOTIFY_VOLUME knob tunes
+# the master level at playback time without re-encoding.
+
+set -euo pipefail
+
+SOUND_DIR="${1:-$HOME/.local/share/sounds/notify}"
+TARGET_DB="${TARGET_DB:--31}"
+
+command -v ffmpeg >/dev/null || { echo "ffmpeg not found" >&2; exit 1; }
+command -v ffprobe >/dev/null || { echo "ffprobe not found" >&2; exit 1; }
+
+shopt -s nullglob
+files=("$SOUND_DIR"/*.ogg)
+(( ${#files[@]} )) || { echo "No .ogg files in $SOUND_DIR" >&2; exit 1; }
+
+for f in "${files[@]}"; do
+ mean=$(ffmpeg -hide_banner -nostats -i "$f" -af volumedetect -f null /dev/null 2>&1 \
+ | grep -oP 'mean_volume: \K[-0-9.]+' || true)
+ if [ -z "$mean" ]; then
+ echo "skip (could not measure): $f" >&2
+ continue
+ fi
+ gain=$(awk -v t="$TARGET_DB" -v m="$mean" 'BEGIN { printf "%.1f", t - m }')
+ tmp=$(mktemp --suffix=.ogg)
+ ffmpeg -hide_banner -loglevel error -y -i "$f" \
+ -af "volume=${gain}dB" -c:a libvorbis -q:a 6 "$tmp"
+ # Write through the file rather than mv over it: when SOUND_DIR is the
+ # stow-symlinked ~/.local copy, mv would replace the symlink with a real
+ # file and decouple it from the repo. cat preserves the symlink target.
+ cat "$tmp" > "$f"
+ rm -f "$tmp"
+ printf "%-14s mean %7s dB gain %+6s dB -> target %s dB\n" \
+ "$(basename "$f")" "$mean" "$gain" "$TARGET_DB"
+done