My daughter is approaching the 6 month mark. This is a time when kids start to develop gross motor skills and begin to express themselves through play. In anticipation, I jumped at the chance to make some dynamic toys for her in addition to the mostly rigid ones she’s collected so far.
Ended up doing a Friday late night build. Since I didn’t have a collection of sounds ready, I just dumped all the sound effects from the DOS game Blood as a test.
Hardware
A few items were at my disposal for this project:
- 1 x Raspberry Pi model B+
- 1 x JBL Clip with an aged battery (3.7v 600mAh)
- 1 x cheap USB numpad
- 1 x microUSB power pack – free conference knick-knack
- 1 x 2GB microSD card
- 1 x Chinese green tea tin
The primary component for this sound tin is the JBL Clip. After all, you can’t hear anything without a decent speaker! Disassembling it revealed a PCB with a footprint just the right size to fit on the floor of the tin.
A few holes drilled in a hexagonal pattern on one side of the tin serve as the speaker grill. The JBL Clip battery was losing capacity due to age but is still functional.
After the guts of the JBL Clip were mounted inside, the USB numpad needed a similar treatment; the only difference was that the keys were mounted on the outside.
Software
The SD card was loaded with the latest version of Raspbian Lite, leaving
a little over 600MB free for sound files and everything else. I turned on
console auto-login via raspi-config
and created two bash scripts:
1. playRandom.sh
Used to randomly select a single WAV
file within a folder and play it back with aplay
.
#!/bin/sh
ls *.wav |sort -R |tail -$N |while read file; do
aplay $file
exit 0
done
2. randomSoundPlayer.sh
Used to continuously listen for key presses so it can either execute playRandom.sh
or quit to the shell.
#!/bin/sh
echo Press Q to exit, any other key to play a random sound
while true; do
read -t 0.3 -N 1 input
if [[ $input = "q" ]] || [[ $input = "Q" ]]; then
echo
break
elif [[ -n $input ]]; then
./sfx/playRandom.sh &
fi
done
All that was needed to finish this was to add
a line at the end of ~/.bash_profile
to run
randomSoundPlayer.sh
on login. This ensures the final step of
any boot sequence on the device will start the sound player loop.
Getting sounds
There are lots of nice sound libraries and sound effects banks on the internet, but one particularly good example was “soundsnap.com”. I chose this one since it had an exceptionally simple filtering and searching mechanism (e.g. search all sounds for “animal” tag and duration of < 2 seconds).
Needed a few other pieces of glue code to turn this site into an easy to download source of sound effects:
- puppeteer (headless Chromium API)
- ffmpeg (optionally convert MP3 into PCM-WAV)
- ffmpeg-normalize (normalize audio loudness)
I’ve put all the code together for this into a soundscraper. Just follow the readme instructions and you should have some scraped sounds for personal use in no time.
Normalizing the audio loudness
The downloaded sound files can be all over the place in terms of loudness. To ensure
sounds are never too quite nor too loud, we have to normalize them: for this,
I’ve selected the EBU R128 normalization preset in ffmpeg
. This is a broadcasting
standard norm that should be good enough for our purposes.
Using yarn normalize
, we can run an ffmpeg-normalize
in batch mode to convert
all our non-normalized MP3s into MP2s. They end up in a mp3/normalized
folder within our
tool.