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.
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.
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:
Used to randomly select a single
WAV file within a folder and play it back with
#!/bin/sh ls *.wav |sort -R |tail -$N |while read file; do aplay $file exit 0 done
Used to continuously listen for key presses so it can either execute
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.
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.
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