Created
December 19, 2025 18:07
-
-
Save darkseed/c0b5234bec02978b149a54ba000ddb25 to your computer and use it in GitHub Desktop.
Reachy Mini Audio diag script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # audio_diag_focus.sh — Focused audio diag for Reachy/Pollen/ReSpeaker class devices | |
| # Usage: | |
| # ./audio_diag_focus.sh | |
| # PATTERNS='Reachy|Pollen|reSpeaker' ./audio_diag_focus.sh | |
| set -euo pipefail | |
| PATTERNS="${PATTERNS:-Reachy|Pollen|reSpeaker}" | |
| # Case-insensitive grep helper | |
| igrep() { grep -Ei "$PATTERNS" || true; } | |
| have() { command -v "$1" >/dev/null 2>&1; } | |
| hr() { printf '%*s\n' "${1:-92}" '' | tr ' ' '-'; } | |
| title(){ echo; hr; echo "$1"; hr; } | |
| kv(){ printf "%-30s %s\n" "$1" "$2"; } | |
| # ---------- PipeWire (wpctl) ---------- | |
| pw_block() { | |
| title "PipeWire (wpctl) — matching devices/nodes: /$PATTERNS/i" | |
| if ! have wpctl; then | |
| kv "wpctl" "not found" | |
| return | |
| fi | |
| kv "Default sink volume" "$(wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null || echo '<unavailable>')" | |
| kv "Default source volume" "$(wpctl get-volume @DEFAULT_AUDIO_SOURCE@ 2>/dev/null || echo '<unavailable>')" | |
| echo | |
| echo "wpctl status (filtered to matches + surrounding headers):" | |
| # Print only Audio section and filter to matching lines plus structure lines. | |
| wpctl status 2>/dev/null \ | |
| | awk ' | |
| /^Audio$/ {in_audio=1} | |
| /^Video$/ {in_audio=0} | |
| { if(in_audio) print } | |
| ' \ | |
| | awk -v pat="$PATTERNS" ' | |
| BEGIN{IGNORECASE=1} | |
| # always keep structural lines | |
| /^[A-Za-z]/ || /^[[:space:]]*├─/ || /^[[:space:]]*└─/ || /^[[:space:]]*\*/ { print; next } | |
| # keep only matching lines | |
| $0 ~ pat { print } | |
| ' | |
| echo | |
| echo "Quick list (matching sinks/sources with IDs):" | |
| wpctl status 2>/dev/null \ | |
| | awk ' | |
| /^Audio$/ {in_audio=1} | |
| /^Video$/ {in_audio=0} | |
| { if(in_audio) print } | |
| ' \ | |
| | grep -E "Sinks:|Sources:|^\s*\*?\s*[0-9]+\." \ | |
| | igrep || true | |
| } | |
| # ---------- Pulse (pactl) ---------- | |
| pulse_block() { | |
| title "PulseAudio compat (pactl via PipeWire) — matching sinks/sources: /$PATTERNS/i" | |
| if ! have pactl; then | |
| kv "pactl" "not found (pulseaudio-utils)" | |
| return | |
| fi | |
| local def_sink def_source | |
| def_sink="$(pactl info 2>/dev/null | awk -F': ' '/Default Sink:/{print $2}')" | |
| def_source="$(pactl info 2>/dev/null | awk -F': ' '/Default Source:/{print $2}')" | |
| kv "Default sink" "${def_sink:-<unavailable>}" | |
| kv "Default source" "${def_source:-<unavailable>}" | |
| echo | |
| echo "Matching sinks (name | state):" | |
| pactl list short sinks 2>/dev/null | igrep | awk '{print $2 " | " $NF}' || true | |
| while read -r id name _; do | |
| [ -z "${name:-}" ] && continue | |
| echo | |
| hr | |
| echo "Sink: $name" | |
| pactl get-sink-volume "$name" 2>/dev/null | head -n1 || true | |
| pactl get-sink-mute "$name" 2>/dev/null | head -n1 || true | |
| done < <(pactl list short sinks 2>/dev/null | igrep | awk '{print $1, $2, $3}') | |
| echo | |
| echo "Matching sources (name | state):" | |
| pactl list short sources 2>/dev/null | igrep | awk '{print $2 " | " $NF}' || true | |
| while read -r id name _; do | |
| [ -z "${name:-}" ] && continue | |
| echo | |
| hr | |
| echo "Source: $name" | |
| pactl get-source-volume "$name" 2>/dev/null | head -n1 || true | |
| pactl get-source-mute "$name" 2>/dev/null | head -n1 || true | |
| done < <(pactl list short sources 2>/dev/null | igrep | awk '{print $1, $2, $3}') | |
| } | |
| # ---------- ALSA (amixer) ---------- | |
| alsa_block() { | |
| title "ALSA (amixer) — matching cards: /$PATTERNS/i" | |
| if ! have aplay || ! have arecord || ! have amixer; then | |
| kv "alsa-utils" "missing (need aplay/arecord/amixer)" | |
| return | |
| fi | |
| echo "Matching playback devices (aplay -l):" | |
| aplay -l 2>/dev/null | igrep || echo "<none>" | |
| echo | |
| echo "Matching capture devices (arecord -l):" | |
| arecord -l 2>/dev/null | igrep || echo "<none>" | |
| # Collect cards that appear in either aplay -l or arecord -l and match PATTERNS | |
| local cards | |
| cards="$( | |
| { aplay -l 2>/dev/null; arecord -l 2>/dev/null; } \ | |
| | awk -v pat="$PATTERNS" 'BEGIN{IGNORECASE=1} | |
| /^card [0-9]+:/ {line=$0} | |
| { if($0 ~ /^card [0-9]+:/) line=$0 } | |
| $0 ~ pat && $0 ~ /^card [0-9]+:/ { print $2 } | |
| ' \ | |
| | sed 's/://g' \ | |
| | sort -nu \ | |
| | tr '\n' ' ' | |
| )" | |
| if [ -z "${cards// }" ]; then | |
| echo "No ALSA cards matched." | |
| return | |
| fi | |
| for c in $cards; do | |
| echo | |
| hr | |
| echo "Card $c info:" | |
| amixer -c "$c" info 2>/dev/null | sed -n '1,8p' || true | |
| # Playback controls to try in order (USB mixers vary) | |
| echo | |
| echo "Playback mixer snapshot:" | |
| local found_play=0 | |
| for ctl in "PCM" "PCM,0" "PCM,1" "Master" "Speaker" "Headphone"; do | |
| if amixer -c "$c" sget "$ctl" >/dev/null 2>&1; then | |
| echo "Control: $ctl" | |
| amixer -c "$c" sget "$ctl" 2>/dev/null | sed -n '1,14p' | |
| found_play=1 | |
| break | |
| fi | |
| done | |
| [ "$found_play" -eq 0 ] && echo "<no common playback control found>" | |
| echo | |
| echo "Capture mixer snapshot:" | |
| local found_cap=0 | |
| for ctl in "Capture" "Mic" "Microphone" "ADC" "Input"; do | |
| if amixer -c "$c" sget "$ctl" >/dev/null 2>&1; then | |
| echo "Control: $ctl" | |
| amixer -c "$c" sget "$ctl" 2>/dev/null | sed -n '1,14p' | |
| found_cap=1 | |
| break | |
| fi | |
| done | |
| [ "$found_cap" -eq 0 ] && echo "<no common capture control found>" | |
| done | |
| } | |
| main() { | |
| echo "audio_diag_focus.sh — $(date)" | |
| echo "Patterns: /$PATTERNS/i" | |
| pw_block | |
| pulse_block | |
| alsa_block | |
| echo | |
| hr | |
| echo "Tip: If output is quiet, ALSA 'PCM' (amixer) is often the real limiter even when wpctl/pactl show 100%." | |
| hr | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment