Is 16 bit 44 kHz digital audio really possible on Arduino?

A project log for Teensy Audio Library

CD quality sound processing, integrated with Arduino sketches

Paul StoffregenPaul Stoffregen 09/09/2014 at 12:000 Comments

I'm sure anyone familiar with Arduino must be skeptical.

16 bit, 44 kHz streaming, not just 1 input or output for monophonic playing, but many simultaneous streams between dozens of virtual objects, with I2S digital audio streaming to an external ADC/DAC/Codec is FAR beyond what anyone has done on the Arduino platform before.

The "catch", or the key enabling technology, is the 32 bit ARM Cortex-M4 processor and Freescale's eDMA engine (on Teensy 3.1).  This more powerful hardware, and a LOT of work in this library, make this tremendous increase in audio streaming possible.

ARM's Cortex-M4 processor has special DSP (Digital Signal Processing) instructions, which this library uses to dramatically speed up computationally intensive operations, like filters, mixing, linear interpolation, etc.  It also has a burst memory access mode which accelerates transfer of small groups of audio samples.

The DMA engine is the other key enabling hardware.  Without DMA, the CPU would need to handle each piece of data streaming on & off chip.  Even on a fast ARM microcontroller, 44100 interrupts per second burns a lot of CPU time.  Fortunately, the DMA engine can automatically move data between memory and the on-chip hardware.  It generates an interrupt only when half or all of a 128 sample block is complete.  The fast ARM processor can easily handle 689 interrupts/second.  It also allows other interrupt-based Arduino libraries to used together with audio.  As long as their interrupts complete reasonably fast (as most do), they don't cause audio glitches, because the DMA engine keeps the data flowing.

The library is designed to make efficient use of the hardware.  The live streaming between objects is actually implemented by passing shared, reference-counted buffers.  When the output of one object streams to the inputs on several others, shared copy-on-write memory management is used, to avoid memory-to-memory copying as much as is possible.

Of course, there always are limits.  This is a low power microcontroller, afterall.  The library efficiently implements CPU usage tracking on all objects.  Your Arduino sketch can query each object, to get its current and worst-ever CPU usage, or the total usage for all objects.

For example, the pink noise generator takes 3%.  The 1024 point FFT object uses bursts of 52% (a future version may smooth its usage over time).  Simple effects like the AHDSR envelope are well under 1%.  The Synthesis/PlaySynthMusic, which generates 16 simultaneous waveforms, routed to 16 simultaneous AHDSR envelopes, and then mixed down to stereo output by six 4-channel mixes, consumes a worst case CPU usage of 31%.

I've been working on this library for about 1 year, and dreaming & planning it much, much longer.  It's getting close to *finally* a 1.0 release.  So many other audio projects have required PC-class hardware, or suffered low quality sound and difficult limitations on what an Arduino sketch can do while sound plays.  I'm really excited to finally have a solution for the world that will make high quality sound easy on microcontrollers!