APC Australia

Play 48kHz stereo WAV les with nano Player 2

Our new Arduino Nano-powered WAV player now supports 32, 44.1 and 48kHz/8-bit stereo files. Darren Yates explains how he did it.

-

Last month, we introduced nanoPlayer, a small Arduino Nano-powered audio player that plays 8-bit mono WAV files to 19kHz sample rate using just a microSD card reader, some passive electronic components and the popular TMRpcm library.

Since then, we’ve ditched the TMRpcm library and written our own code from scratch. Now, nanoPlayer 2 handles 8-bit stereo WAV files at 32, 44.1 and 48kHz. Here’s how.

COUNTERS/TIMERS

The Arduino Nano is powered by a tiny chip called the Atmel ATMEGA328P. Inside are three key functions called ‘timers’. More accurately, they’re counters that increment one count per clock cycle (the Nano has a 16MHz clock speed). Timer0 is an 8-bit (256-count) timer that controls Arduino’s millis() and delay() code functions. Timer1 is a 16-bit (65536-count) timer and Timer2 is another 8-bit timer — both are general purpose and free to use. You can use Timer0 also but doing so may muck up the millis() and delay() functions.

However, each timer is also capable of creating PWM (pulse-width modulation) output and this is the key to turning WAV file digital data into an analog voltage.

AUDIO SAMPLE TIMING

For the audio files to play at the correct speed, we must play the samples at the required rate. The WAV file header provides all that informatio­n — we’ve got no space here but read my previous story on our website ( tinyurl.com/ zr5d9zr).

The ATMEGA Timers have two important variables or ‘registers’ — 0CRxA and OCRxB — where ‘x’ is replaced by the timer number, for example, OCR1A/OCR1B for Timer1.

Timer1 has an output, OC1B, which produces the PWM signal that, when filtered, will be our audio signal. If the OC1B output isn’t time-controlled precisely, the audio will be at the wrong pitch.

As the timer begins its count run, the OC1B output immediatel­y switches high. As the timer counts up, it eventually reaches the audio sample number we’ve previously loaded in to register OCR1B — this forces OC1B output to drop low. The timer continues counting, but when it hits the number in OCR1A, it does two things — it resets the timer count back to zero, but also triggers the timer interrupt.

HARDWARE INTERRUPTS

When you interrupt a conversati­on, you interrupt (politely), say your piece, leave and the original members of the conversati­on continue as before. A code interrupt does the same thing — it allows us to bookmark the current code position to run another function and, when completed, go back to the bookmark point and carry on. The code we launch at the interrupt is called an Interrupt Service Routine (ISR). By attaching this to a timer, we can have

this code run at precise intervals — those intervals can be set by the number we load into OCR1A.

Let’s say we set OCR1A to decimal ‘250’. Setting the Timer to count using what’s called ‘Phase-Corrected PWM’ technique, we start with 16MHz (the ATMEGA clock speed) and divide it by two. We now divide the resultant 8MHz by 250 and we get 32,000 — that means the timer will hit the OCR1A point and launch our ISR 32,000 times per second or 32kHz. This also happens to be one of the common sample rates for WAV audio files.

Change OCR1A to decimal ‘181’ and do it again. Divide 8MHz by 181 and you get 44,198, which is as close as we can get to 44,100Hz or 44.1kHz, the CD audio sample rate.

RING BUFFERS AND CARD STORAGE

But what are we actually doing 44,198 times a second? The ISR code grabs the next audio sample from the ring buffer and loads it into OCR1B. The ring buffer is two 256-byte blocks of RAM — while data is regularly picked out from one block by the ISR, the rest of our code keeps count of the bytes played and continues to load up data from the microSD card into the other block. The ISR alternates between each ring buffer block.

How does this create the audio output? Say the audio sample value is low compared to the OCR1A value, say ‘10’ — Timer1 takes little time to reach that OCR1B number, resulting in short positive-going pulses, or a short ‘pulsewidth’. When filtered, this produces a low analog voltage. If the sample is high, say ‘170’, Timer1 takes much longer to reach the OCR1B count, resulting in a long pulse-width, which becomes a higher analog voltage. Do this fast enough and you get an audio signal. This whole process continues until we run out of samples (reach the end of the file) and nanoPlayer starts playing the next file.

To get stereo, Timer1 handles the ISR and the left-channel audio, Timer2 the right channel, but no ISR (Timer1’s ISR handles both channels).

HOW IT WORKS

Our new nanoPlayer 2 has play, pause and next track functions using just one momentary push-button switch. Press the button to start playback of the first file, press again to pause, press again to un-pause. Hold down the button to skip to the next track.

All files must be 32, 44.1 or 48kHz sample rate with 8-bit stereo samples. The source code automatica­lly skips files that don’t match these requiremen­ts and all files must be in the root folder of a FAT32-formatted microSD card up to 32GB capacity. Files can be 4GB in size and you can create 8-bit WAV files using Audacity ( audacityte­am.org).

HOW TO BUILD IT

www. Get a 400-point breadboard, an Arduino Nano, a microSD card module and the other components shown on the overlay diagram (try eBay). Some soldering will be required, wires to the 3.5mm stereo socket and possibly the header pins on the Arduino Nano. Can’t solder? Get a knowledgea­ble mate to help or learn via one of the many online tutorials — it’s time you learned anyway. Practise before soldering the Arduino Nano.

CODING THE ARDUINO NANO

Download the Arduino IDE v1.6.5 (not the latest version) from arduino.cc/ download, grab the source code from our website at apcmag.com/magstuff. Unzip the source code file, copy the contents of the libraries subfolder to the same of your Arduino IDE install and restart the IDE. Load up the source code, plug in the Arduino Nano and flash the source code. Plug a 3.5mm stereo cable from the socket to your computer speakers. Now plug in the microSD card, plug in USB power into the Arduino, wait for the ‘card ready’ twin LED flashes, press the button and set the volume to suit.

 ??  ?? The Arduino nano is a compact version of the Arduino Uno.
The Arduino nano is a compact version of the Arduino Uno.
 ??  ?? Use this overlay diagram to build your own nanoPlayer.
Use this overlay diagram to build your own nanoPlayer.
 ??  ?? Select ‘Other uncompress­ed files’, Options to make 8-bit WAV files in Audacity.
Select ‘Other uncompress­ed files’, Options to make 8-bit WAV files in Audacity.
 ??  ?? Our nanoPlayer 3 is built on a small 400-point breadboard.
Our nanoPlayer 3 is built on a small 400-point breadboard.
 ??  ?? Timers enable precise PWM timing to make (almost) correct sample rates.
Timers enable precise PWM timing to make (almost) correct sample rates.
 ??  ?? Pulse Width Modulation can turn digital data into an analog voltage.
Pulse Width Modulation can turn digital data into an analog voltage.

Newspapers in English

Newspapers from Australia