CD quality sound processing, integrated with Arduino sketches
Some projects need a lot of audio I/O. Maybe you’re doing positional audio sound effects (using the 8-tap delay effect) where ordinary stereo or even 5 channel “surround” isn’t enough? Maybe you’re making the ultimate Eurorack synthesizer module? Or you just want a lot of signals, because you can!
Here’s a board for the Cirrus Logic CS42448 chip, which provides 6 inputs and 8 outputs. All are high quality audio, and all work simultaneously.
Normally digital audio is communicated between chips using I2S protocol (which is different than I2C, despite the similar acronym). Two I2S streams can be used for quad channel, but to really step up to more channels, you need TDM protocol.
TDM, which stands for Time Division Multiplexing, communicates a frame of 256 data bits. For 44.1 kHz, this means the bit clock must be 11.3 MHz. Only 4 signals are used, one to transmit all 256 bits and another to receive all 256, a frame sync signal the marks where each 256 bit frame begins, and of course the 11.3 MHz clock.
Here is the TDM waveform documented by Cirrus Logic for the CS42448 chip.
When viewed on an oscilloscope, here is how the TDM signal actually appears:
During this test, the code below was running. The output from Teensy is the blue trace. It sends a 16 bit guitar synthesis to CS42448 AOUT1 & AOUT2. Because the CS42448 outputs are 32 bits, but the audio is only 16 bits you can see the lower 16 bits are always zero. Most of the rest of the output is zeros, except this example also brings in AIN1 and sends its top 16 bits to AOUT5 and its lower 16 bits to AOUT6.
Of course, the green trace is the data being received from the CS42448. All 6 inputs were left unconnected. Even through the channel slots of 32 bits, the CS42448 only produces 24 bits of data, and its lower 8-9 bits are mostly random noise. This PCB uses only the simplest single-ended input circuit. The better opamp-based differential circuit documented in the CS42448 could be expected to improve performance.
TDM support has recently been added to the Teensy Audio Library. It’s accessed by creating AudioInputTDM and AudioOutputTDM objects.
Each AudioInputTDM creates 16 simultaneous inputs. Like all communication in the Teensy Audio Library, the data is 16 bits wide. 16 of these channels gives access to all 256 incoming TDM bits. For CS42448, only channels 0, 2, 4, 6, 8 & 10 would be really useful.
Likewise, each AudioOutputTDM object can accept 16 simultaneous 16 bit audio streams, to fully control all 256 bits of the TDM output frame. For CS42448, only the 8 even numbered channels are useful.
You might think sustained 11.3 Mbit/sec communication would be difficult on a microcontroller, but it turns out Teensy's digital audio port with FIFO and its DMA engine make this quite easy and efficient. Yes, really!
Development of the audio software support is being discussed on this forum thread. If you make one of these boards, please join the conversation!
Read more »
1 CS42448, Codec Chip 598-1033-ND 1 CAT811T, Reset Chip CAT811TTBI-GT3OSCT-ND 7 Connector, audio CP1-3525N-ND 7 Resistor, 150 ohm, 603 311-150HRCT-ND 8 Resistor, 560 ohm, 603 RMCF0603FT560RCT-ND 2 Resistor, 2.2K ohm, 603 311-2.20KHRCT-ND 8 Resistor, 10K ohm, 603 311-10.0KHRCT-ND 7 Resistor, 100K ohm, 603 311-100KHRCT-ND 14 Capacitor, 2.7nF, NP0, 805 445-7508-1-ND 4 Capacitor, 10nF, X7R, 603 490-1512-1-ND 7 Capacitor, 0.1uF, X7R, 603 490-1524-1-ND 14 Capacitor, 4.7uF, X5R, 805 1276-6463-1-ND 7 Capacitor, 10uF, X5R, 805 399-4925-1-ND 1 Capacitor, 22uF, X5R, 805 490-1719-1-ND 1 Capacitor, 100uF, X6T, 1206 490-10525-1-ND 1 Inductor, Ferrite Bead, 805 490-1054-1-ND 1 Circuit Board oshpark.com/shared_projects/2Yj6rFaW 1 Teensy 3.2, 3.5 or 3.6 www.pjrc.com/store/teensy32.html 2 Socket, 14x1 www.pjrc.com/store/socket_14x1.html 2 Header, 14x1 www.pjrc.com/store/header_14x1.html 1 Heatsink (optional: CS42448...
Thanks to a great contribution from Frank and Ben, the PT8211 DAC which sells for about 20 cents is now supported. They even put in 4X oversampling, so you get nice-looking waveforms at higher audio frequencies with only a simple analog low-pass filter.
USB audio connectivity has recently been added, based partly on earlier work by @Michele Perla
You can now place AudioInputUSB and AudioOutputUSB objects in your Arduino sketch and connect them to any of the other Teensy Audio Library stuff. Any sound send to a AudioOutputUSB object arrives on your PC/Mac as if you'd connected a line-in. Sound your PC plays (if the Teensy's audio is selected in your sound control panel) arrives at the AudioInputUSB object.
Currently this is all very new code, only on Github. Details are here:
Within the next few weeks, a Teensyduino beta test installer will be published, to make trying this much simpler. But if you'd like to give this a try, of course you can download the stuff from github and copy to the correct location within your copy of Arduino, and edit boards.txt to make Audio appear in the Tools > USB Type menu.
At this very early stage, the design tool hasn't been updated with these new objects. You'll need to edit the audio objects right in your sketch. The simplest way involves using the I2S objects and then you just change from I2S to USB.
Today I added 4 channel I2S output support to the library.
Teensy sends 4 audio channels simultaneously.
To use it, you need 2 audio shields... or 2 of anything else that takes I2S digital audio input. With the audio shields, a small hardware mod is needed on the 2nd shield, to route the 2nd stereo data stream to its input, and to configure for a different I2C address to you can control is separately from the 1st board.
Conversation about the development is on this forum thread. The design tool has been updated with "i2s_quad", so you can easily use it with whatever 4 audio channels you can design. The library has a simple example sketch that plays 2 WAV files to both outputs at the same time.
Maybe I ought to create more examples? What things would you like to have 4 channel audio output do?
Frank's 6-chip Memoryboard (version 4) was tested today. It works great!
The audio library (latest on github) now supports this hardware.
Here's a simple test where it delayed a beep sound, with copies output at 8 and 9 seconds.
Sound delays this long are really surreal. Delays in the 1-2 second range are about as long as our brains are ever used to hear in the natural world.
It's like nothing happened, like the project is doing nothing and not working and you give up waiting (at least it's way beyond my attention span for stuff working) and then there's the beep, exactly like it was several seconds ago!
Here's a demo of the new delay line feature, using external ram chip(s).
Thanks mostly to Frank B, we now have direct S/PDIF output from the Teensy Audio Library!
Here's a detailed blog article.
You can get optical TOSLINK digital audio with a $1 connector (Digikey 1080-1434-ND) or just a red LED shining into the optical cable.
In the photo above, the TOSLINK connector is mounted on this OSH Park PCB (under $2 for three of them).
The S/PDIF output is also now supported by the Audio System Design Tool, so you can just connect it to whatever complex audio system you like, to get S/PDIF digital output!
Here's the lengthy forum thread where this development was discussed.
Version 1.0, the first stable release, is now available.
Here's Hack-a-Day's coverage.
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!