Knowledge for the World

How to detect sound output in Linux and use it to call a program (or drive a motor!)

  • by Zach (130)
  • 15 minutes

This guide will show you how to detect Linux sound output and use it to run a program -- like driving a servo, stepper motor or DC motor! I used this method to control a motor via my Raspberry Pi's GPIO pins, turning my Furby into an Amazon Echo -- but you can use it to call pretty much anything.

In a nutshell, there's a specific audio status file that gets written to when sound is actively being output; we'll monitor this file and its contents and hook into the state change to call our program.

1

Connect to your Pi (or other Linux machine) and create the following file. The installation directory and filenames will vary based on your project, so be sure to update them however you'd like. The naming here is based on my driving my Furby's DC motor while sound was being output.

sudo nano ~/furby/output-monitor.sh

Enter the following, save and exit:

#!/bin/bash

DIR='/proc/asound/card1/pcm0p/sub0/status'
CMD='python /home/pi/furby/furby.py'

content=''
while true
do
    new_content=`cat $DIR`  
    if [[ "$content" != "$new_content" ]]; then
        content=$new_content
        $CMD
    fi
    sleep 0.25
done

Change DIR above to point to the status file for your active audio device -- I'm using a USB sound card, and this is the path for its status file.

To figure out which status file is in use for your audio device, simply play an audio sample:

speaker-test -t wav -c 6

.. and then view each of the status files and see which one contains the string "state: RUNNING". There should be 4 status files total you'll need to check, and they follow the pattern:

/proc/asound/card*/pcm0p/sub*/status

You can view each file as such. For example:

cat /proc/asound/card1/pcm0p/sub0/status

I found when using the Pimoroni Speaker pHAT that it used card0 (/proc/asound/card0/pcm0p/sub0/status), but your mileage may vary.

Change CMD above to point to the command you'd like to run when sound is detected (in my case, I'm executing a python script, furby.py, with the aforementioned file path).

2

This script will start the audio monitor script. Create the file:

sudo nano /etc/init.d/go-furby-go.sh

Paste the following, save, and exit:

#!/bin/bash
# /etc/init.d/go-furby-go.sh

case "$1" in
  start)
    echo "Starting go-furby-go.sh"
    /home/pi/furby/output-monitor.sh
    ;;
  stop)
    echo "Stopping go-furby-go.sh"
    killall output-monitor.sh
    ;;
  *)
    echo "Usage: /etc/init.d/go-furby-go.sh {start|stop}"
    exit 1
    ;;
esac

exit 0

3

Make both these scripts executable:

sudo chmod +x /etc/init.d/go-furby-go.sh
sudo chmod +x /home/pi/furby/output-monitor.sh

4

To make sure our shell script runs at boot:

sudo update-rc.d go-furby-go.sh defaults

5

Reboot your Pi:

sudo reboot

Play a sample audio file and you should see the desired function execute. You're all done!