Volumio and external audio device in parallel

Hi folks,

first post plus newbie to Volumio and also in Python, so please be kind :wink:

My goal was to use Volumio together with an Amazon Echo Dot (could be any device) plugged into the microphone input of a cheap external USB sound card attached to a Raspberry PI and use GPIO to switch an amplifier on whenever and only when there is sound coming from Volumio or the Echo.

After some sleepless hours I came up with the following solution that I would like to share and hope for positive input. There’s obviously space for improvements but in general I am pretty happy with it now.

  1. Change /etc/asound.conf to the following. This will allow the parrallel playback of Volumio and the attached Echo:

[code]pcm.!default {
type plug
slave.pcm “dmixer”
}

pcm.dmixer {
type dmix
ipc_key 1024
ipc_perm 0666
slave {
pcm “hw:5,0”
}
bindings {
0 0
1 1
}
}

ctl.dmixer {
type hw
card 5
}

pcm.softvolume {
type plug
slave.pcm “softvol”
}

pcm.softvol {
type softvol
slave {
pcm “dmixer”
}
control {
name “SoftMaster”
card 5
device 0
}
max_dB 0.0
min_dB -50.0
resolution 100
}[/code]

If everything has been configured well, test with arecord -V mono -D plughw:5,0 -f cd | aplay to playback the sound of the Echo in parallel to Volumio.

Unfortunately I couldn’t find a decent way via Alsa to figure out if the Echo was playing or not but luckily Python offers a few nice tools for that.

  1. The following script not only writes the mic input to audio output but also checks the “playback” state of Volumio (via mpc) plus the current RMS level from the input and then switches a GPIO correspondingly:

[code]#!/usr/bin/python

import alsaaudio, audioop, time, subprocess, threading, wiringpi

Define mic input (plughw:5,0) and audio output (dmixer)

Fine tune framerate, periodsize and sleepy for better performance

audioformat = alsaaudio.PCM_FORMAT_S16_LE
channels = 2
framerate=48000
periodsize = 2000
sleepy = 0.02

inp = alsaaudio.PCM(type=alsaaudio.PCM_CAPTURE,mode=alsaaudio.PCM_NONBLOCK,device=“plughw:5,0”)
inp.setchannels(channels)
inp.setrate(framerate)
inp.setformat(audioformat)
inp.setperiodsize(periodsize)

out = alsaaudio.PCM(type=alsaaudio.PCM_PLAYBACK,mode=alsaaudio.PCM_NONBLOCK,device=“dmixer”)
out.setchannels(channels)
out.setrate(framerate)
out.setformat(audioformat)
out.setperiodsize(periodsize)

global global_micRms
global_micRms = 0

Check audio status every second and switch GPIO (23) on or off after a 30s delay

wiringpi.wiringPiSetupGpio()
wiringpi.pinMode(23, 1)
global offDelay
global_offDelay = 0

def checkStatus():
global global_offDelay
threading.Timer(1.0, checkStatus).start()
volumioTemp = subprocess.Popen([“mpc”, “status”], stdout=subprocess.PIPE)
volumioState = volumioTemp.stdout.read()
#print(global_micRms)
#print(volumioState)
if ((global_micRms > 10) or ("[playing]" in str(volumioState))) and not (wiringpi.digitalRead(23)):
wiringpi.digitalWrite(23, 1)
#print(“ON”)
# Fine tune micRms threshold (above/below 10) for more accurate switching
if (global_micRms > 10) or ("[playing]" in str(volumioState)):
global_offDelay = 0
#print(“RUNNING”)
if ((global_micRms < 10) and ("[playing]" not in str(volumioState))) and (wiringpi.digitalRead(23)):
global_offDelay+=1
#print(global_offDelay)
if (global_offDelay == 30):
wiringpi.digitalWrite(23, 0)
global_offDelay = 0
#print(“OFF”)
checkStatus()

Write mic input to audio output and read RMS from mic input

while True:
l,data = inp.read()
time.sleep(sleepy)
out.write(data)
global_micRms = audioop.rms(data, 1)[/code]

  1. To get all of this nicely running on a fresh Volumio installation, I had to perform the following extra steps:

Install Python3 and necessary modules
sudo apt-get update
sudo apt-get install python3 python3-pip
sudo pip3 install pyalsaaudio wiringpi

Edit playback settings in Volumio
USB Audio Device
DSD over PCM
Mixer Type: Software

Fine tune “alsamixer”
(might need to press F5/F6 to see USB device settings)
Speaker: -5db
Mic: Mute
Capture LR: -5db
Auto Gain Control: Mute
Close alsamixer with ESC and save settings with “sudo alsactl store”.

As said, I am no Alsa or Python expert but hope my findings will also help some other :nerd: as well. Sharing is caring :wink:

Edit: Added 3).