Scheduling your audio actions

In this section, we'll be looking at different techniques for triggering a recording or a playback, and optionally how to make it stop after a certain period of time.

Start on power up

The first method we'll cover is also the bluntest: how to start a recording or playback directly when powering up the Raspberry Pi. There isn't really a standardized way of auto-starting regular user applications on boot, so we'll have to improvise a bit to come up with our own way of doing what we want.

The Raspbian boot process is basically a collection of shell scripts being run one after the other, with each script performing some important task. One of the last scripts to run is /etc/rc.local, which is a good starting point for our custom auto-run solution. Right now, the script doesn't do much, it just prints out the IP address of the Pi.

You can try running the script any time using the following command:

pi@raspberrypi ~ $ /etc/rc.local

We could just jam our list of commands right in there, but let's try to make our solution a little more elegant. We want the system to check whether there's an autorun script in our home directory, and if it exists, run it as the pi user. This will make sure our script doesn't accidentally wipe our entire SD card or write huge WAV files in random locations:

  1. Let's start with the minor addition to rc.local:
    pi@raspberrypi ~ $ sudo nano /etc/rc.local
    
  2. We're going to add the following block of code just above the final exit 0 line:
       if [ -x /home/pi/autorun.sh ]; then 
         sudo -u pi /home/pi/autorun.sh 
       fi 
    

    The preceding shell script means if there is an executable file named autorun.sh in the pi user's home directory, then run that script as the pi user (not as root, which would be the normal behavior for boot scripts).

    If we run /etc/rc.local right now, nothing new would happen-not until we create the autorun.sh script in our home directory and make it executable.

  3. So let's create our autorun script:
    pi@raspberrypi ~ $ nano ~/autorun.sh
    
  4. After the first #!/bin/sh line, you're free to put anything in this script. Just keep in mind that you won't be able to use aliases here-you'll have to enter full commands. Here's an example record and playback script:
    #!/bin/sh 
    # 
    # Auto-run script for Raspberry Pi. 
    # Use chmod +x ~/autorun.sh to enable. 
     
    PLAYORREC=P # Set to P for Playback or R for Record 
     
    INPUTFILE="playme.wav" 
    OUTPUTFILE="myrec.wav" 
    MICROPHONE="-t alsa plughw:1" 
    SPEAKERS="-t alsa plughw:0" 
     
    case "$PLAYORREC" in 
      P|p) sox ~/"$INPUTFILE" $SPEAKERS ;; 
      R|r) sox $MICROPHONE ~/"$OUTPUTFILE" ;; 
      *) echo "Set the PLAYORREC variable to P for Playback or R for Record" ;; 
    esac
    
    • The first #!/bin/sh line is called a shebang and is used to tell the system that any text that follows is to be passed on to the default shell (which is dash during boot and bash for logins on Raspbian) as a script.
    • The other lines starting with # characters are comments, used only to convey information to anyone reading the script.
    • The PLAYORREC variable is used to switch between the two operating modes of the script.
    • INPUTFILE is what will be played if we are in the playback mode, and OUTPUTFILE is where we will record to if we are in the record mode. MICROPHONE and SPEAKERS lets us update the script easily for different audio gadgets.
    • The case block compares the character stored in the PLAYORREC variable (which is P at the moment) against three possible cases:
      • If PLAYORREC contains a capital P or a lowercase p), then run this sox playback command a hint to the user about it.
      • If PLAYORREC contains a capital R or a lowercase r, then run this sox record command.
      • If PLAYORREC contains anything else or is left blank, then display a hint to user about it.

    • The sox command is launched with the values of the variables inserted as arguments, and we assume that the file specified is located in the pi user's home directory.
  5. Once we've saved the autorun.sh script and exited the editor, there's one last thing we need to do before we can actually run it. We need to give the script executable permission with the chmod command:
    pi@raspberrypi ~ $ chmod +x ~/autorun.sh
    
  6. Now we can give the script a test run:
    pi@raspberrypi ~ $ ~/autorun.sh
    

If everything works fine now, it should also run fine when you reboot.

One major improvement we could do to the script is to have tmux start the playback or recording process in the background. That way we'll be able to log in remotely to check on sox as it runs. Simply change the two sox command lines as follows:

P|p) tmux new-session -s autostart -n $PLAYORREC -d "sox ~/"$INPUTFILE" $SPEAKERS" ;; 
 
R|r) tmux new-session -s autostart -n $PLAYORREC -d "sox $MICROPHONE ~/"$OUTPUTFILE"" ;; 

Here we tell tmux to create a new session named autostart, create a new window named P or R depending on the mode, and start in a detached state. Then we specify the command we'd like to run inside the tmux session surrounded by double quotes. Because $INPUTFILE and $OUTPUTFILE are also surrounded by double quotes, we have to escape those characters by prefixing them with the character.

The easiest way to temporarily disable the script when you don't need to play or record anything on boot is to remove the executable permission from the script:

pi@raspberrypi ~ $ chmod -x ~/autorun.sh

Scheduled start

When we simply want to postpone the start of something for a few minutes, hours, or days, the at command is a good fit.

Add it to the system using the following command:

pi@raspberrypi ~ $ sudo apt-get install at --no-install-recommends

The at command can optionally send e-mails with status reports, but since that would require a small local mail server to be installed and running, we've told apt-get not to install the additional recommended packages here.

Let's start with a demonstration of the basic at facilities. First, we specify the time we want something to occur:

pi@raspberrypi ~ $ at now + 5 minutes

Next, at will enter command input mode where we enter the commands we would like to execute, one per line:

at> sox ~/playme.wav -d
at> echo "Finished playing at $(date)" >> ~/at.log

We then press Ctrl + D to signal that we are done with our command list, and we'll get an output with our job's ID number and the exact time it has been scheduled to start.

After five minutes have passed, your job will start running in the background. Note that there won't be any visible output from the application on your console. If you need to be sure that your command ran, you could write a line to a log file, as was done in the previous example.

Alternatively, you may schedule commands for an exact date and time:

pi@raspberrypi ~ $ at 9am 1 April 2016

Jobs in the queue waiting to be executed can be viewed using the following command:

pi@raspberrypi ~ $ atq

Once you know the job ID, you can remove it from the queue by replacing # with your job ID:

pi@raspberrypi ~ $ atrm #

Another nifty trick is to specify a shell script to be executed instead of entering the commands manually:

pi@raspberrypi ~ $ at now + 30 minutes -f ~/autorun.sh

The Raspberry Pi board lacks a real-time clock (RTC), which computers use to keep track of the current time. Instead, the Pi has to ask other computers over the network what time it is when it boots up. Alternatively, it can obtain the correct time from a GPS module, as described in the Using GPS as a time source section of Chapter 5, Taking Your Pi Off-Road. The Pi is equally unable to keep track of the time that passes while it's powered off.

If we need to time something but know we won't have network access, we can combine the technique discussed in the Start on power up section with the at command. This allows us to implement the idea Start the playback 1 hour after I plug in the Pi.

All we have to do is modify one line in our /etc/rc.local script to add an at timer:

if [ -x /home/pi/autorun.sh ]; then
  sudo -u pi at now + 1 hour -f /home/pi/autorun.sh
fi

Controlling recording length

An automated SoX recording will continue to run until the Pi runs out of SD card space. We can use the trim effect to stop the recording (or playback) after a certain amount of time has elapsed:

pi@raspberrypi ~ $ sox -t alsa plughw:1 myrec.wav trim 0 00:30:00

The previous command will record thirty minutes of audio to myrec.wav and then stop. The first zero tells the trim effect to start measuring from the beginning of the file. The position where you want to cut the recording is then specified as hours:minutes:seconds.

Another function useful for long recordings is to be able to split it into multiple files, each file with a certain duration. The following command will produce multiple WAV files, each file being one hour in length:

pi@raspberrypi ~ $ sox -t alsa plughw:1 myrec.wav trim 0 01:00:00 : newfile : restart

Start recording with noise detection

Wouldn't it be cool if the Pi could listen for activity in the room and only start recording when something or someone makes a sound? Once again SoX comes to the rescue.

Our noise detection method works in two simple steps:

  1. Start listening for one second and measure the noise level during that second.
  2. If the measured noise was above a certain threshold, start recording for 5 minutes; if not, start over and listen for another second.

First, let's calibrate the microphone and figure out a good amplitude threshold value:

pi@raspberrypi ~ $ sox -t alsa plughw:1 -n stat trim 0 00:00:01 : restart

This command starts monitoring your microphone, but the -n argument tells SoX to discard the output since we are only interested in the statistics produced by the stat effect. The trim effect then cuts of the monitoring after one second, the important statistics are printed, and a new monitoring second starts thanks to the restart argument.

Now, keep your eyes on the Maximum amplitude value in the statistics output. As long as you stay quiet, the value shouldn't fluctuate too much from one readout to the other.

Next, make a loud noise and watch the Maximum amplitude value jump. Now try moving further away from the microphone and say something in your normal tone of voice. If there was a significant change in amplitude value, write that value down as a rough starting point for your threshold value. If not, try raising the capture volume of your microphone in alsamixer until you see a significant increase in the amplitude value.

Alright, now all we need to do is translate the theory into program logic with the following script:

#!/bin/bash 
# 
# Noise activated recorder script for Raspberry Pi. 
# Use chmod +x ~/noisedetect.sh to enable. 
 
THRESHOLD=0.010000 
 
noise_compare() { 
  awk -v NOISE=$1 -v THRESHOLD=$2 'BEGIN {if (NOISE > THRESHOLD) exit 0; exit 1}' 
} 
 
while true ; do 
  NOISE=$(sox -t alsa plughw:1 -n stat trim 0 00:00:01 2>&1 > /dev/null | grep 'Maximum amplitude' | cut -d ':' -f 2 | tr -d ' ') 
  if noise_compare $NOISE $THRESHOLD; then 
    echo "Noise detected ($NOISE) - Recording..." 
    sox -t alsa plughw:1 $(date +%Y%m%d-%H%M%S).wav trim 0 00:05:00 
  fi 
done
noise-detect.sh

Note

Be careful not to introduce line breaks within each of your lines of script, or the script will not work - breaks are only shown here for display reasons.

The THRESHOLD variable holds, of course, the threshold amplitude value that you found out by calibrating your microphone. Next comes the noise_compare function. A function is a piece of code that can be called from other places in a script. In this case, we use it to compare two floating point numbers by passing them to the awk command, since bash doesn't have this ability built in.

Then we enter an infinite loop, which means our script will continue to run until we press Ctrl + C to break out of the loop. Next, we chain together a series of commands to extract the Maximum amplitude value from sox and store it in the NOISE variable, which is then compared with our THRESHOLD variable with the help of the noise_compare function.

If the NOISE value is larger than the THRESHOLD value, we start a 5-minute recording with the current date and time as the filename.

Now that you know how to do sound detection, you can easily swap out the sox recording command to play an alarm bell or send an e-mail warning about a possible noisy intruder, as described in the Sending e-mail updates section of Chapter 5, Taking Your Pi Off-Road.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.179.225