First functioning ASRC with dante.

This commit is contained in:
2026-01-05 16:07:06 +01:00
parent ef5ca102e3
commit 0237cd98d8
8 changed files with 244 additions and 188 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
dep/dante_package/dante_data/config/
*.wav
recordings/
tmp/

71
asoundrc.danteasrc Normal file
View File

@@ -0,0 +1,71 @@
# ============================================================
# DEP Dante RX -> ALSA Loopback is now done by DEP ALSA ASRC.
# So: NO alsaloop needed anymore.
#
# Apps read from hw:Loopback,1,0 via dsnoop fanout,
# then we split into 6 mono virtual devices.
# ============================================================
# ---- shared 6ch capture from Loopback with dsnoop fanout ----
pcm.dante_asrc_shared6 {
type dsnoop
ipc_key 1048577
ipc_key_add_uid true
ipc_perm 0666
slave {
pcm "hw:Loopback,1,0" # capture side of ALSA loopback
channels 6
rate 48000
format S16_LE
period_size 256
buffer_size 1024
}
hint { show on ; description "DEP RX (via ASRC) shared 6ch (loopback+dsnoop)" }
}
# ---- 6 mono devices (each maps one of the 6 channels) ----
# (Using route explicitly makes the intent very clear.)
pcm.dante_asrc_ch1 {
type route
slave { pcm "dante_asrc_shared6"; channels 6; }
ttable.0.0 1
hint { show on ; description "DEP RX CH1" }
}
pcm.dante_asrc_ch2 {
type route
slave { pcm "dante_asrc_shared6"; channels 6; }
ttable.0.1 1
hint { show on ; description "DEP RX CH2" }
}
pcm.dante_asrc_ch3 {
type route
slave { pcm "dante_asrc_shared6"; channels 6; }
ttable.0.2 1
hint { show on ; description "DEP RX CH3" }
}
pcm.dante_asrc_ch4 {
type route
slave { pcm "dante_asrc_shared6"; channels 6; }
ttable.0.3 1
hint { show on ; description "DEP RX CH4" }
}
pcm.dante_asrc_ch5 {
type route
slave { pcm "dante_asrc_shared6"; channels 6; }
ttable.0.4 1
hint { show on ; description "DEP RX CH5" }
}
pcm.dante_asrc_ch6 {
type route
slave { pcm "dante_asrc_shared6"; channels 6; }
ttable.0.5 1
hint { show on ; description "DEP RX CH6" }
}

View File

@@ -1,45 +0,0 @@
# DEP dsoundcard ALSA plugin configuration
# Install with: sudo bash install_dsoundcard.sh
# Needs this command running in background to loopback the dsoundcard to dsnoop
# sudo alsaloop -C dsoundcard -c 6 -r 48000 -f S16_LE -P hw:Loopback,0,0
pcm_type.dsoundcard {
lib "/opt/dep/dsoundcard.so"
}
pcm.dsoundcard {
type dsoundcard
hint { show on ; description "DEP Sound Card (raw 6ch)" }
}
# ---- shared 6ch capture from Loopback with dsnoop fanout ----
pcm.dsoundcard_shared6 {
type dsnoop
ipc_key 1048577
ipc_key_add_uid true
ipc_perm 0666
slave {
pcm "hw:Loopback,1,0"
channels 6
rate 48000
format S16_LE
}
hint { show on ; description "DEP Sound Card (shared 6ch via loopback+dsnoop)" }
}
# ---- 6 mono devices (each maps one of the 6 channels) ----
pcm.dsoundcard_ch1 { type plug; slave.pcm "dsoundcard_shared6"; slave.channels 6; ttable.0.0 1
hint { show on ; description "DEP Sound Card - CH1" } }
pcm.dsoundcard_ch2 { type plug; slave.pcm "dsoundcard_shared6"; slave.channels 6; ttable.0.1 1
hint { show on ; description "DEP Sound Card - CH2" } }
pcm.dsoundcard_ch3 { type plug; slave.pcm "dsoundcard_shared6"; slave.channels 6; ttable.0.2 1
hint { show on ; description "DEP Sound Card - CH3" } }
pcm.dsoundcard_ch4 { type plug; slave.pcm "dsoundcard_shared6"; slave.channels 6; ttable.0.3 1
hint { show on ; description "DEP Sound Card - CH4" } }
pcm.dsoundcard_ch5 { type plug; slave.pcm "dsoundcard_shared6"; slave.channels 6; ttable.0.4 1
hint { show on ; description "DEP Sound Card - CH5" } }
pcm.dsoundcard_ch6 { type plug; slave.pcm "dsoundcard_shared6"; slave.channels 6; ttable.0.5 1
hint { show on ; description "DEP Sound Card - CH6" } }

View File

@@ -305,6 +305,16 @@
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
],
"resources":{
"devices":[
{
"allow": true,
"type": "c",
"major": 116,
"access": "rw"
}
]
}
}
}

View File

@@ -49,7 +49,18 @@
},
"alsaAsrc":
{
"enableAlsaAsrc": false
"enableAlsaAsrc": true,
"deviceConfigurations": [
{
"deviceIdentifier": "hw:0,0",
"direction": "playback",
"bitDepth": 16,
"numOpenChannels": 6,
"alsaChannelRange": "0-5",
"danteChannelRange": "0-5",
"bufferSize": 48000
}
]
},
"product" :
{

View File

@@ -62,7 +62,7 @@
"deviceIdentifier": "hw:0,0",
"direction": "playback",
"bitDepth": 16,
"bufferSize": 48000
"bufferSize": 480
}
]
},

View File

@@ -0,0 +1,148 @@
#!/bin/bash
set -euo pipefail
# Quiet locale warnings (optional)
export LC_ALL="${LC_ALL:-C}"
OUTPUT_DIR="./tmp"
DURATION=10
RATE=48000
FORMAT="S16_LE"
CHANNELS=1
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"
echo "======================================================"
echo "DEP ASRC -> ALSA Loopback -> dsnoop Test (parallel)"
echo "======================================================"
echo "Recording one channel from each device IN PARALLEL:"
echo " dante_asrc_ch1 .. dante_asrc_ch6"
echo "Duration: $DURATION seconds"
echo "Output directory: $OUTPUT_DIR"
echo "Timestamp: $TIMESTAMP"
echo "======================================================"
echo ""
# Check if DEP is running
if ! pgrep -f "dep_manager" >/dev/null; then
echo "ERROR: DEP is not running!"
echo "Start DEP first: cd /home/caster/dante_beacon && sudo bash dep.sh start"
exit 1
fi
device_exists() {
local dev="$1"
aplay -L 2>/dev/null | grep -qx "$dev" || arecord -L 2>/dev/null | grep -qx "$dev"
}
loopback_present() {
# Hardware device list is more reliable than arecord -L naming
arecord -l 2>/dev/null | grep -qi "Loopback" || aplay -l 2>/dev/null | grep -qi "Loopback"
}
# Warn (dont hard-fail) if Loopback hardware isn't visible
if ! loopback_present; then
echo "WARNING: ALSA Loopback hardware not found in 'arecord -l' / 'aplay -l'."
echo "If you expect Loopback, load it with:"
echo " sudo modprobe snd-aloop"
echo ""
fi
# Ensure our virtual per-channel devices exist (from your asound.conf)
missing=0
for i in $(seq 1 6); do
if ! device_exists "dante_asrc_ch${i}"; then
echo "ERROR: dante_asrc_ch${i} not found (asound.conf not applied?)"
missing=1
fi
done
if [ "$missing" -ne 0 ]; then
echo ""
echo "Hint: list relevant devices with:"
echo " arecord -L | grep -E 'dante_asrc_(shared6|ch[1-6])' -n"
echo ""
exit 1
fi
# Track background jobs
declare -a DEVICES=()
declare -a FILES=()
declare -a PIDS=()
cleanup() {
echo ""
echo "Stopping recordings..."
for pid in "${PIDS[@]:-}"; do
kill "$pid" 2>/dev/null || true
done
wait 2>/dev/null || true
echo "Done."
}
trap cleanup INT TERM
echo "Launching recordings..."
for i in $(seq 1 6); do
DEVICE="dante_asrc_ch${i}"
OUTPUT_FILE="${OUTPUT_DIR}/${DEVICE}_${TIMESTAMP}.wav"
LOG_FILE="${OUTPUT_DIR}/${DEVICE}_${TIMESTAMP}.log"
echo " -> $DEVICE => $OUTPUT_FILE"
arecord -D "$DEVICE" \
-c "$CHANNELS" -f "$FORMAT" -r "$RATE" -d "$DURATION" \
"$OUTPUT_FILE" >"$LOG_FILE" 2>&1 &
pid=$!
DEVICES+=("$DEVICE")
FILES+=("$OUTPUT_FILE")
PIDS+=("$pid")
done
echo ""
echo "All recordings started. Waiting for completion..."
echo ""
SUCCESS_COUNT=0
FAIL_COUNT=0
for idx in "${!PIDS[@]}"; do
pid="${PIDS[$idx]}"
dev="${DEVICES[$idx]}"
out="${FILES[$idx]}"
if wait "$pid"; then
if [ -f "$out" ]; then
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
size="$(ls -lh "$out" | awk '{print $5}')"
echo "OK $dev -> $out ($size)"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
echo "FAIL $dev -> file not created: $out"
fi
else
FAIL_COUNT=$((FAIL_COUNT + 1))
echo "FAIL $dev (arecord exit != 0). See log: ${out%.wav}.log"
fi
done
echo ""
echo "======================================================"
echo "Summary: $SUCCESS_COUNT successful, $FAIL_COUNT failed"
echo "======================================================"
echo ""
if command -v sox &>/dev/null; then
echo "Audio file info (sox stat):"
for out in "${FILES[@]}"; do
if [ -f "$out" ]; then
echo "---- $(basename "$out") ----"
sox "$out" -n stat 2>&1 | grep -E "Sample Rate|Channels|Duration|Length|Maximum amplitude|RMS"
fi
done
echo ""
fi
echo "To play a recording:"
echo " aplay ${OUTPUT_DIR}/dante_asrc_ch1_${TIMESTAMP}.wav"
echo ""

View File

@@ -1,139 +0,0 @@
#!/bin/bash
set -u
# Record ALL channels at the same time (one device per channel)
# Starts arecord for dsoundcard_ch1 .. dsoundcard_ch6 in parallel.
OUTPUT_DIR="./recordings"
DURATION=10 # seconds
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p "$OUTPUT_DIR"
echo "=========================================="
echo "DEP dsoundcard ALSA Plugin Test (parallel)"
echo "=========================================="
echo "Recording one channel from each device IN PARALLEL:"
echo " dsoundcard_ch1 .. dsoundcard_ch6"
echo "Duration: $DURATION seconds"
echo "Output directory: $OUTPUT_DIR"
echo "Timestamp: $TIMESTAMP"
echo "=========================================="
echo ""
# Check if DEP is running
if ! pgrep -f "dep_manager" > /dev/null; then
echo "ERROR: DEP is not running!"
echo "Start DEP first: cd /home/caster/dante_beacon && sudo bash dep.sh start"
exit 1
fi
# Check base dsoundcard plugin existence (list both playback+capture definitions)
if ! (aplay -L 2>/dev/null | grep -q "^dsoundcard$" || arecord -L 2>/dev/null | grep -q "^dsoundcard$"); then
echo "ERROR: dsoundcard ALSA plugin not found!"
echo "Make sure dsoundcard.so is installed in /opt/dep/"
echo "And ~/.asoundrc is configured correctly"
exit 1
fi
device_exists() {
local dev="$1"
aplay -L 2>/dev/null | grep -q "^${dev}$" || arecord -L 2>/dev/null | grep -q "^${dev}$"
}
# Track background jobs
declare -a DEVICES=()
declare -a FILES=()
declare -a PIDS=()
# Kill all jobs on Ctrl-C / termination
cleanup() {
echo ""
echo "Stopping recordings..."
for pid in "${PIDS[@]:-}"; do
kill "$pid" 2>/dev/null || true
done
wait 2>/dev/null || true
echo "Done."
}
trap cleanup INT TERM
# Start all recordings
echo "Launching recordings..."
for i in $(seq 1 6); do
DEVICE="dsoundcard_ch${i}"
OUTPUT_FILE="${OUTPUT_DIR}/${DEVICE}_${TIMESTAMP}.wav"
LOG_FILE="${OUTPUT_DIR}/${DEVICE}_${TIMESTAMP}.log"
if ! device_exists "$DEVICE"; then
echo "WARNING: $DEVICE not found in ALSA device lists, skipping."
continue
fi
echo " -> $DEVICE => $OUTPUT_FILE"
# Run in background; capture stderr/stdout into a log for debugging
arecord -D "$DEVICE" \
-c 1 -f S16_LE -r 48000 -d "$DURATION" \
--buffer-size=4096 \
"$OUTPUT_FILE" >"$LOG_FILE" 2>&1 &
pid=$!
DEVICES+=("$DEVICE")
FILES+=("$OUTPUT_FILE")
PIDS+=("$pid")
done
if [ "${#PIDS[@]}" -eq 0 ]; then
echo "ERROR: No devices were started. Nothing to do."
exit 1
fi
echo ""
echo "All recordings started. Waiting for completion..."
echo ""
# Wait for all and collect results
SUCCESS_COUNT=0
FAIL_COUNT=0
for idx in "${!PIDS[@]}"; do
pid="${PIDS[$idx]}"
dev="${DEVICES[$idx]}"
out="${FILES[$idx]}"
if wait "$pid"; then
if [ -f "$out" ]; then
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
size=$(ls -lh "$out" | awk '{print $5}')
echo "OK $dev -> $out ($size)"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
echo "FAIL $dev -> file not created: $out"
fi
else
FAIL_COUNT=$((FAIL_COUNT + 1))
echo "FAIL $dev (arecord exit != 0). See log: ${out%.wav}.log"
fi
done
echo ""
echo "=========================================="
echo "Summary: $SUCCESS_COUNT successful, $FAIL_COUNT failed/skipped"
echo "=========================================="
echo ""
# Optional: show brief file stats
if command -v sox &> /dev/null; then
echo "Audio file info (sox stat):"
for out in "${FILES[@]}"; do
if [ -f "$out" ]; then
echo "---- $(basename "$out") ----"
sox "$out" -n stat 2>&1 | grep -E "Sample Rate|Channels|Duration|Length|Maximum amplitude|RMS"
fi
done
echo ""
fi
echo "To play a recording:"
echo " aplay ${OUTPUT_DIR}/dsoundcard_ch1_${TIMESTAMP}.wav"
echo ""