Hi folks,
first post plus newbie to Volumio and also in Python, so please be kind
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.
- 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.
- 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]
- 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 as well. Sharing is caring
Edit: Added 3).