Create a network-connected stereo audio player that you control via a web browser. Darren Yates shows you how with an Arduino microcontroller.
Our NetPlay project is built on a standard breadboard.
In our previous Arduino masterclass, we briefly introduced the Ethernet Shield, an Arduino expansion board that adds Ethernet connectivity plus microSD card storage. We used that storage as the basis of a simple one-button digital audio player. It was functional, but limited to 8-bit mono WAV files with a 19kHz sample rate. We also gave you the software to create those specific files. The audio quality was a bit better than AM radio level, which is good enough for audiobook and basic music playback.
Several weeks on and we’re continually astounded by this little Arduino Uno board and just what software developers are able to scrape out of its 16MHz/8-bit ATMEG328P microcontroller.
Thanks to recent online work by Lutz Lisseck, it’s now technically possible to push this little chip to pump out 16-bit stereo audio with a 31.25kHz sample rate — that’s basically FM radio — with little more than six resistors and a couple of capacitors. We’re going to combine the Ethernet Shield with Lisseck’s work to create a stereo 8-bit audio player that comes with its own web server we’re calling NetPlay.
Getting around limitations
The ‘SimpleSDAudio’ library makes it possible to push the boundaries of the Arduino Uno and create a standalone project that leaves us gobsmacked.
Unfortunately, it’s not possible to combine the Ethernet Shield’s Ethernet function with 16-bit stereo audio — basically, there just aren’t enough pulse-width modulated (PWM) outputs to go around. However, we’re taking one of Lisseck’s ‘SimpleSDAudio’ examples and creating a stereo 8-bit audio player with 15kHz bandwidth that you can control via a web browser on your PC, tablet or smartphone.
The $10 Ethernet Shield you can grab from eBay contains a Wiznet W5100 Ethernet controller chip that comes with its own TCP/IP stack. Combined with its microSD card slot, which supports up to 32GB of storage, and it’s a seriously impressive little add-on board. It’s enough to create your own little web server that can dish up web pages to a browser on your PC, laptop, tablet or smartphone. More importantly, it’s a web server you can use to control the outputs of the Arduino Uno and get it to do some seriously cool stuff.
To give you a taste, we’ll start this month with a simple example: turning an LED on and off over your home network. Using the Ethernet library bundled with the Arduino 1.0.3 IDE, it’s reasonably simple to create a web server that waits for incoming traffic and spits out HTML code back to the client. Using an HTML form, our little WebLED sketch accepts data back from the client to control the digital output D5 to switch an LED on and off.
Sure, it’s pretty simple, but use your imagination and some extra electronics, and that LED could be a motor, an emergency beacon, a video recorder, model railway, coffee machine or a water pump. You’ve also got up to 21 digital outputs you can individually control via the web, exponentially expanding the possibilities.
The circuit is about as simple as you can get: a 470ohm current-limiting resistor and an LED. Go through the ‘APC_06_WebLED.ino’ sketch (download it from apcmag.com/arduino.htm under Project 06) to see how it works. You need little more than half a dozen lines of code to create a web server. In fact, most of the code (and there’s not much of it there) is setting up the web page and parsing the response from the client.
This will give you a taste not only for the possibilities, but also for how our NetPlay stereo audio player works.
The $10 Arduino Ethernet Shield provides microSD storage, Ethernet and built-in TCP/IP stack.
Building our NetPlay project isn’t much more complicated than building the WebLED. In fact, it’s pretty similar to the last project’s audio player.
Again, we’re using the Arduino’s PWM outputs to turn digitally sampled audio back into an analogue voltage approximation. These outputs appear at the D5 and D6 pins on the Ethernet shield. (The Shield doesn’t do anything at this point — these outputs are feed-throughs from the Arduino board underneath.)
These are fed through a resistor divider network, which doubles as a basic first-order low-pass filter to knock off some of the PWM clock signal to just leave the audio signal we want. If you've built the audio player in the last project, you can use the same 3.5mm stereo socket, so there’s no more soldering required.
Once you’ve programmed the NetPlay sketch into the Arduino, you can power the project by using a USB charger straight into the USB port of the Arduino board. Plug an Ethernet cable into the Ethernet Shield and the other end into a spare port on your ADSL modem/router. Plug the Ethernet cable in first and then apply the power, as the project will be up and running within a second or two of that power being applied.
Creating NetPlay audio tracks
While NetPlay can’t handle standard 44.1kHz/16-bit stereo WAV files (well, not yet at any rate), we’ve made decent progress from the previous audio project, jumping from 19kHz sample rate/8-bit mono PCM audio playback to 31.25kHz/8-bit stereo PCM.
Thanks to Nyquist’s Theorem, a 31.25kHz sample rate gives us a practical audio bandwidth of around 15kHz, which as we said before is FM radio territory and much better than the 9kHz bandwidth we were talking about in the last project.
However, we still need to create these files, so we’ve modified the Auduino Windows audio converter app from the last project to create a NetPlay version — it’s a Windows registry key file that integrates the encoding commands straight into Windows Explorer’s right-click context menu. When activated, it converts any audio file into NetPlay stereo format using a combination of FFmpeg and SoX open-source audio converters.
Like in the previous project, we also need to keep the files in an 8.3 DOS file naming format and our NetPlay audio converter does this automatically.
Follow this overlay diagram when building our NetPlay project.
Install the converter
To install the NetPlay audio converter, simply launch the ‘installnetplay.reg’ registry key file. It adds a key for the menu text you’ll see on the right-click menu, as well as the commands we want those menu options to carry out. The ‘uninstallnetplay.reg’ file removes those registry keys and the menu entries.
First, grab the ‘netplay.zip’ file from dl.techlife.net/apps/netplay.zip. Unzip it to your C: drive, where it will automatically create the C:\netplay folder and dump the contents there.
We use a combination of FFmpeg to convert audio files into a standard 44.1kHz/16-bit stereo WAV format and feed that into SoX to create our 31.25kHz/8-bit stereo raw PCM files. FFmpeg can also create these files, but unfortunately, it has fixed steps in its audio bandwidth settings that are locked, irrespective of the sample rate you choose. For example, create a 19kHz audio file with FFmpeg and the audio bandwidth is no better than 7.5kHz — the same bandwidth you get when creating a 16kHz file. Do it with SoX and a 19kHz sampled file gets a bandwidth closer to 9kHz, which sounds much better. The same thing happens creating a 31.25kHz sample rate audio file — you get 10kHz bandwidth with FFmpeg, but 15kHz with SoX.
Launch the ‘installnetplay.reg’ registry key file to install the audio converter.
How NetPlay works
The key to NetPlay is Lutz Lisseck’s ‘SimpleSDAudio’ library. What makes this library impressive is that it greatly increases the sample rate/audio bandwidth possible from an Arduino Uno board. The key to that is the speed of data processing and it’s only made possible by using large dollops of Assembler programming rather than the standard Arduino C++ derivative programming. It’s also impressive because it uses what little RAM the Arduino Uno’s ATMEGA328P has (just 2KB) and manages to create a loopback buffer that continually reads the audio file data from the microSD card slot into two 512-byte segments — while the data is being played from one, it’s being loaded up into the other.
The circuit for our NetPlay audio player.
In order to get the comparatively high sample rates we’re using, the microSD card slot on the Ethernet Shield has to run at half SPI speed at least. The diode-based level translation circuit we used in the last project with that cheap $2 SD card reader won’t work (at least not reliably). You’d need to add a CMOS 74HC4050 level translator chip and do the translation properly. Thankfully, the Ethernet Shield has this covered, so you can use any microSD card and it should work perfectly well.
The other limitation is a little more serious and prevents us from playing back 16-bit stereo audio. The Ethernet port and the microSD card reader both operate using the SPI bus, so only one device can be accessed at a time. Given the way our NetPlay audio player works, that’s not too much of a problem. More importantly, the Ethernet port uses pins D10 through D13.
Lisseck realised that by using two PWM outputs and combining them with a simple 256R-R resistor ladder, you could approximate 16-bit audio output. The problem is the ‘SimpleSDAudio’ library requires the two primary PWM outputs to be D9 and D10, with the secondary two as D5 and D6. With D10 being locked up by the Ethernet port, it means not only can the Ethernet Shield not deliver 16-bit stereo, you can’t even get 8-bit stereo.
While there’s no way at present around the problem of D10 being locked up, it is possible to re-route the primary PWM outputs to D5 and D6 so that we can at least get 8-bit stereo. We’ve applied these modifications to the ‘SimpleSDAudio’ library we’ve included in our sketch package so we can at least get 8-bit stereo happening. Unfortunately, the library doesn’t yet support 16-bit mono, which would’ve been nice…
However, there’s one extra task you must do that we can’t. In our ‘netplayarduino.zip’ file (available at apcmag.com/arduino.htm under Project 06), you’ll find a ‘wiring.c’ file. This has to replace the one inside the Arduino 1.0.3 IDE, which you’ll find under \hardware\arduino\cores\arduino. Rename the original file as ‘wiring_orig.c’ and then copy the new version across.
In short, this enables the swapping of these PWM outputs (D9/D10 to D5/D6) as well as changing the function of the interrupt timer that some of the back-end functions use. Note that in order for other Arduino project sketches to work correctly, you’ll need to swap the original ‘wiring.c’ file back in when you’re done with this one.
Ethernet/SD card code
Lisseck has also added in a basic FAT32 file system reader for the microSD card to the ‘SimpleSDAudio’ library, which makes it pretty trivial to read the contents of the card and play audio files from it. By bringing in the Ethernet library as well, you can use the ‘SimpleSDAudio’ library to automatically read the filenames from the card and output them as part of HTML code. The Ethernet library turns the Arduino Uno into a basic web server you can access via any PC, laptop, tablet or smartphone on your home network.
Making things simple, Lisseck provides an example sketch for doing exactly this in his library. However, because of the D10 issue, he’s limited the example to 8-bit mono audio files only through the D9 output. We’ve modified the library and the example to handle 8-bit stereo through outputs D5 and D6 instead (you must still make the ‘wiring.c’ file substitution in the Arduino IDE folder) and improved the web server code so you can choose different songs and stop playback at any time, rather than having to use the browser’s ‘Back’ button all the time.
The ‘SimpleSDAudio’ library is so CPU efficient that we’re not even using half the capacity of the ATMEGA328P processor. As it’s capable of playing 16-bit stereo at the same 31.25kHz sample rate, there’s room left over to add your own extra functionality (within reason) and still get stereo audio happening.
We’ve modified Lisseck’s example with a ‘play and stay’ web interface and stop link.
How you use it
First, build the project following the circuit and overlay diagrams. Next, grab the ‘netplayarduino.zip’ file, unzip it to your C: drive and copy the ‘SimpleSDAudio’ library to your Arduino IDE’s \libraries folder. Next, back up the original ‘wiring.c’ file we mentioned before and copy in the new one from the ZIP folder.
Fire up the Arduino IDE and load in the ‘apc_06_netplay_v4.ino’ sketch file. The most important thing here is to change NetPlay’s IP address to one that suits your home network. It’ll need to match the first three 8-bit numbers of your network; for example, if you live on a 192.168.0.xxx subnet, pick a spare address from that same subnet. Change the sketch, save it and program the Arduino Uno board.
After that, using NetPlay is pretty easy: create a bunch of audio files using our NetPlay audio converter and copy them to a microSD card slot. Load them into the Ethernet Shield and start it up. On your client, enter the Arduino’s IP address into your browser and you’ll see a list of filename hyperlinks. Click on one and that file will begin playing through NetPlay and your powered speaker system. Click on another at any time and the new track will start. Click the ‘Stop Playback’ link to stop.
In the end, the Arduino Uno controller does double-shift as an audio player and web server in one.
Give it a try
Granted, there’s not much in the way of hardware, but this is still a pretty complex example of what the Arduino Uno is capable of. The fact that it can do all this with just a handful of components makes it even more impressive. While we all love our GHz-powered computers and tablets, hopefully this is a good reminder that not every application needs more than 16MHz of CPU clock speed and a huge operating system to run it. When you build for a specific application, you might be surprised at just how little processing power you actually need to interact with the real world.
It doesn’t get much simpler than this for a network-controlled circuit.
Abit about 8-bit audio
Much of today’s music is so dynamically compressed that you don’t need the dynamic range afforded by having 16 bits of sample depth. Basic 8-bit audio gives you 48dB of dynamic range, which is often more than enough for R&B, rock and hip hop. For classical music, it’s woefully inadequate because you’ll clearly hear the background noise during quieter passages — a reason why 16-bit/96dB dynamic range audio came alive with the first audio CDs.
For upcoming Arduino projects, follow us on facebook, twitter or RSS.