The Circuitry and Audio Library
For an amateur doing sound recording using Digital Audio Workstation (DAW) software, it can make sense to combine two external accessories into one unit. The Teensy Audio Station combines a 2-channel audio interface to the PC computer with a Control Surface containing the standard Transport controls and an automated Fader control.
In this project, I am again utilizing the Teensy 3.6 ARM MCU module and the excellent Audio library provided for it, to design a versatile audio processing unit for the small recording studio. This project actually combines functions normally performed by two separate products, into one unit:
- A two-channel analog IN, two-channel analog OUT digital audio interface, which interfaces to a PC via a standard USB connection.
- A Digital Audio Workstation (DAW) Control Surface containing various switches, a motorized fader pot, and an audio “scrub” wheel. The Control Surface follows the industry-standard Mackie Control Universal (MCU) protocol. This uses MIDI messages to send/receive the control surface commands.
A unit like this one would be useful for an individual such as a podcaster doing audio content production. Such applications would generally utilize a professional condenser microphone and one or two inputs for sound synthesizer modules. There would be no need for the large number of audio tracks that would be required for most music production. Similarly, fewer control surface buttons, pots, and other parts would be needed to handle just the frequently used operations. All of these functions could be performed using a computer keyboard and mouse. However, people working in this business generally prefer to work with actual switches, fader pots, and other equipment. Figure 1 shows the front panel of the unit.
Front view of the finished unit. The motorized fader pot is at the left and the large Jog Wheel (marked SODKJ) is a nice rotary encoder/dial assembly I purchased from Banggood.
OVERVIEW OF PROJECT FEATURES
Let’s look quickly at the project’s features. Figure 2 is a block diagram of the audio signal chain. I incorporate one channel containing a professional-grade preamplifier IC to handle a professional condenser microphone, commonly used for recording. Since these microphones contain electronic circuitry, they require a 48V power source, which, in the recording industry, is called “phantom power.” I provided a 48V power supply for such microphones. Of the two input channels, channel 1 contains an XLR combo socket, which will accept either a condenser microphone (using an XLR plug) or a Line-level signal (using a ¼” phone plug). Channel 2 only accepts a Line-level signal on a ¼” phone plug.
Block diagram of the audio signal chain
The audio outputs are two line-level signals terminated in two ¼” phone sockets. This two-channel (stereo) output is also fed to a separate pot which then feeds a ¼” stereo phone jack for the Headphone Output.
The source of the signal going to each of these two outputs consists of the following two signals:
- The stereo outputs from existing recorded track(s) present in the PC’s DAW software. This is generated by the UDA1334 stereo I2S DAC.
- A “mix” of whatever signals are present on the two input channels. There is a two-section pot labeled “Mix,” which feeds in a user-defined amount of this “live” signal coming from the microphone or other Line-level input sources. This is referred to as “live monitoring”, because these analog input signals are fed directly to the outputs without being converted to digital (and back to analog again). Thus, they don’t experience the slight delays that are inherent in the digital signal processing occurring in the DAW software itself (plus other buffering delays introduced by the PC’s operating system). All professional digital audio mixers/interfaces have this live monitoring feature.
For the Control surface, I settled upon the following four broad sets of functions:
— ADVERTISMENT—
—Advertise Here—
- Transport Control. This comprises Play, Stop, Record, and Rewind (to Start) buttons.
- Content Navigation. This allows you to scroll around, in time, within an existing recording. It consists of the Forward and Backward buttons, which move the “now” cursor in units of beats or measures (set in the DAW software). There is an “acceleration” factor built into my firmware; the longer you press either of these buttons, the faster it moves around the recording. For fine time adjustments, I have a large “scrub” wheel attached to a rotary encoder, which moves around in units of “ticks” (0.001 seconds).
- Channel Functions. A channel button, when pressed, allows you to set the current (active) channel by turning the “scrub” wheel encoder and watching the channel number on the OLED display. The Mackie Control Universal protocol that I am using for this project defines up to eight channels, but also allows for more than this by also defining Banks of channels (needed for large studio mixers). I allow for only eight channels (no Banks) since that is sufficient for a small unit such as this one. Once you have selected the desired Channel, there are buttons for ARM, SOLO, and MUTE the active channel. A PAN button allows you to adjust the PAN value for the active channel by adjusting the “scrub” wheel encoder. There are also buttons to select automation READ and automation WRITE for that channel. While not a channel function per se, the last button that I have is UNDO, which reverses the DAW’s last-performed operation.
- Automated Fader. I include a 100mm fader pot, which is adjustable by both the user and the attached servo-motor. This fader pot acts as the volume control on the selected channel. The pot element, itself, is not connected up to any of the analog circuitry in either of the two input or output channels. Instead, when it is moved by the user, it sends out volume control messages that are targeted at the selected (active) channel only. The format of these messages is discussed later.
It is intended that these fader motion control messages are recorded within the selected channel as a “volume profile.” When one plays back a track with a volume profile embedded in it, that track’s audio signal will have its volume adjusted digitally, in the DAW’s software, while the track plays. Also, these previously-recorded volume control messages will be sent out to the Control Surface.
These messages are then used to activate the fader pot’s servo-motor, which causes the fader pot to follow the movement of the pot, as was done by the user earlier in the recording process. The actual recording and playback of these volume profiles are controlled (on a channel-by-channel basis) by the DAW software under the control of the settings of the channel’s automation Read and automation Write options. These options are controlled by buttons of the same name, as mentioned earlier. More details on the motorized fader are included in the Motorized Volume Fader section later on.
When I first thought of designing/building the project, I was most concerned with two things. First, I was making sure that the Teensy Audio library would handle both the ADC and DAC and send the data, with very low latency, to the PC, using the USB port. That same USB port has to also handle all the MIDI control messages needed by the Control Surface function. Second, was ensuring that the analog audio circuitry was “quiet” enough, given that it would have to co-exist with the Teensy 3.6 MCU, along with other noisy digital circuitry. Also, it had to deal with very low-level signals from Condenser microphones.
I was quite limited in what enclosure I could use since it had to be a reasonable size and an existing commercial enclosure. My homemade CNC milling machine does a really nice job on Hammond’s extruded aluminum cabinets. Therefore, I settled on the 1455T2201 which is 8.7” high, 6.5” wide, and 2” deep. It is the biggest extruded box they make, but it was a real squeeze to fit everything inside—particularly since the front panel has to slide into place from top to bottom (via a slot in the extrusion).
When I was designing the circuit, I didn’t really consider how many interconnecting wires there would be:
- Between the digital and the analog circuit boards.
- Between both of those boards and the 23 front panel switches, pots, display, and so on.
- Between both boards and the Audio Inputs, Outputs, and Headphone jacks.
DIGITAL AUDIO FUNCTIONALITY
Let’s look at the digital audio functionality of the project. Figure 3 is a schematic of the analog and mixed-signal parts of the project. The project supports two channels of audio input and two channels of audio output. Conversion of the two analog input signals into the digital domain is performed by a Texas Instruments PCM1808 24-bit ADC. I chose this ADC for several reasons. Being a 24-bit device, it is a high-performance device. It has a high SNR of 99dB, and a built-in oversampling decimation filter, which eliminates the need for an external analog anti-aliasing filter. It is an older part, and not used much in current designs, but is still available on small break-out modules at a very low cost. While I admire the newest devices available, they are only available in tiny SMT packages that are impossible for me to solder and mount.
Schematic of the analog audio circuitry and the mixed-signal circuitry consisting of the PCM1808 DAC and UDA1334 ADC. As shown on this schematic, the ADC and DAC are actually mounted on a separate board, which also holds the Teensy 3.6 ARM MCU.
The two audio output channels are provided by an NXP UDA1334 24-bit two-channel DAC. This is also an older part that is now available on a small break-out module at a reasonable cost. It contains both a digital interpolation filter and a noise-shaper. Its output buffer contains an analog low-pass filter, and the data sheet states that no external analog post-filtering is needed. This device contains a PLL to generate its own system clock—not really necessary in this project since Teensy 3.6 generates its own MCLK signal.
Both the ADC and DAC are interfaced to the MCU using the Teensy 3.6’s I2S port. This port can handle the 24-bit word lengths used by both the ADC and DAC used in the project. Note that the Teensy Audio library accepts only 16-bit data input, and outputs only 16-bit values. Therefore, it will only operate on the 16 MSBs of the ADC data, and the UDA1334 DAC will effectively have its 8 LSBs read as zero. This means that some of the intrinsic resolutions of both the ADC and DAC are lost. However, 16-bit audio has been used by CDs for decades and is perfectly satisfactory in most use cases. Where 24-bit ADCs/DACs really become necessary is in multichannel mixers. If you have 16-32 channel mixing boards, even the small amount of noise introduced by 16-bit ADC/DACs will add up and become noticeable.
The default sample rate used by the Teensy Audio library is 44.1kHz, the standard audio CD sample rate. I leave this as-is, but it could be changed by modifying some constants in the library code (which I’ve done in other projects). In this project, the digital audio signals are being fed into/out of a PC computer using the USB port. It turns out that transferring a digital audio signal via the USB port is not a trivial exercise. It is much harder than using the synchronous I2S port that the ADC/DAC use. The reason for this is that a digital audio source, external to the PC itself, is generating digital samples at a fixed sample rate of 44,100Hz. The I2S port that interfaces the ADC to the Teensy MCU depends upon a BCLK clock (at 256 times the sample rate) to synchronize the data transfer. However, the USB port on a PC has no dedicated clock line to synchronize the data transfer. For most USB protocols, the data flow is asynchronous. For digital audio sent over USB, an iso-synchronous protocol is used, when audio samples must be sent at a constant rate. However, there is still no USB equivalent of the BCLK signal used by the I2S protocol to transfer digital audio from ADC/DAC to/from the MCU.
— ADVERTISMENT—
—Advertise Here—
Within the PC, there has to be the equivalent of the BCLK clock signal to synchronize the digital audio data transfer. This 256 times the sample-rate clock is generated in the PC, using a PLL-based circuit based on the user-selected sample rate as the reference. If the external digital audio peripheral and the PC are both set to the same sample rate, in theory this method should work. In practice, however, the crystal-based clocks in each unit will not match exactly, given the tolerances of the crystals themselves. The effect is that after a period of time—tens of seconds to many minutes—the data coming in from the external peripheral will either be getting a bit ahead of the rate at which the PC is absorbing the samples, or the PC will be expecting samples at a rate slightly faster than what the digital audio peripheral is capable of transmitting.
This slight sample rate discrepancy will present itself as a readily discernible “glitch” or “pop” in the audio signal, which is entirely unacceptable. To eliminate this problem, the USB protocol for digital audio transfers includes a PID-like tuning protocol. While the PC is receiving USB digital audio data, it will push that data into a circular buffer and also pop the data out of that buffer, for processing, at the PC’s defined sample rate. It’s possible to measure the difference between the ‘head” and “tail” pointers of the buffer to determine if data is coming in too quickly or too slowly to suit the PC’s sample rate. This discrepancy is constantly fed to a PID-like algorithm, and a calculated sample rate “correction” can be transmitted back to the external digital audio peripheral, allowing it to “trim” its sample rate slightly to match the PC’s sample rate.
I’ve mentioned all this because the MCUs contained on the earlier Teensy boards had a limited sample rate at which they could operate; this was due to limitations in their discrete clock dividers. Those earlier boards were only able to produce a sample rate of 44,117Hz (with the 16MHz MCU clock crystal that they used). The Teensy Audio library worked fine at this sample rate—until USB digital audio input/output blocks were added to the library. For a while, the Teensy USB audio functions suffered from the synchronization “glitches” mentioned above, particularly with Apple Mac computers.
I followed the Teensy forum closely, and it looked to me like this problem had been solved—at least for the Teensy 3.6 and newer Teensy 4x boards (which contain an NXP MIMXRT1062 ARM Cortex M7). The M7 MCU contains a PLL-based clock for the I2S block, which allows it to operate at a sample rate of exactly 44,100Hz. To be safe, though, I tested out the Teensy library’s USB audio blocks early in the project design and found that this problem has been solved, even when using the Teensy 3.6 that I settled upon.
For this project, the Audio Library software configuration was trivial. Referring to Figure 4, you can see that an I2S input block (for the ADC) has its two outputs fed into the inputs of the USB output block. An instance of the USB input block has its two outputs connected to an I2S output block which feeds the DAC. This is about as simple as it gets. You don’t see any mixer or amplifier blocks that could be used for gain control, for example. Due to the audio signal paths needed for this project, all the gain controls had to be done using pots, in the analog domain.
The working area of the Teensy Audio System Design Tool. While deceptively simple, these blocks are all that are needed to take the ADC data and feed it out the USB Digital Audio port and feed digital audio coming in from the same USB port to the DAC. The Design Tool translates this drawing into a code fragment that gets included in my main Arduino sketch.
The Audio System Design Tool produces the code (Listing 1), which must be pasted into the project’s Arduino sketch.
Listing 1
This snippet of code is auto-generated by the Teensy Audio System Design Tool.
AudioInputI2S i2s2;
AudioInputUSB usb2;
AudioOutputI2S i2s1;
AudioOutputUSB usb1;
AudioConnection patchCord1(i2s2, 0, usb1, 0);
AudioConnection patchCord2(i2s2, 1, usb1, 1);
AudioConnection patchCord3(usb2, 0, i2s1, 0);
AudioConnection patchCord4(usb2, 1, i2s1, 1);
The first four lines create instances of the I2S and USB drivers, and the last four lines dictate how they should be “wired” together in software. You also need to add the line “AudioMemory(20)” to the Setup routine in your program. I specified that 20 blocks of audio memory are allocated; this is overkill for this project, but there is lots of free memory for this program, and I routinely use a large number like this as insurance, in case I add more audio blocks later on in the program development.
If your program consisted only of the codes shown in Listing 1, the Teensy Audio library would be running in the background and would send ADC data to the USB port, receive USB audio packets, and forward them to the DAC. Apart from initialization functions in Setup, all the other functions of my AudioStation program are executed in the “loop” section of the sketch—with no required consideration of the timing needs of the audio signal processing going on in the background. In my experience, the Teensy Audio library is, by a long shot, the quickest way to implement digital audio functions in an ARM MCU program!
The Teensy Audio library contains a routine for monitoring the percentage of available MCU processing power being used by the Audio library. This is the function:
AudioProcessorUsage()
This function returns the percentage of MCU processing power used by the Audio library processing blocks, along with an approximation of what is needed for the audio I/O functions. In this program, I am using just the I2S and USB I/O functions; no processing blocks are used. I didn’t bother to include this function to monitor its results. Having used this function in the past, with various Teensy Audio library functions, I knew the audio functions used in this project would consume less than 20% of the processor’s power—probably much less.
ANALOG AUDIO SIGNAL PATHS
From the preceding section, you can see that the software needed to handle the digital audio paths between this unit and the PC are quite basic. Wiring up the circuitry needed for the ADC and DAC was greatly simplified by the use of small breakout modules for both the PCM1808 DAC and the UDA1334 ADC. As shown in Figure 3, the UDA1334 requires two power sources: 5V for its analog section and 3.3V for its digital section. The Adafruit UDA1334 breakout module that I used contains a low-noise 3.3V LDO (for the UDA1334’s digital section), fed from the board’s 5V input. This 3.3V regulated source is available on one of the UDA1334 board’s I/O pins, and I use this 3.3V source to power the PCM1808 DAC. The 5V to supply the UDA1334 board is provided by an LM1086CT-5 regulator—a separate 5V power source from that used by the Teensy 3.6 Module (which derives its power from the PC via the USB port).
Both the ADC and DAC are contained on the same protoboard as the Teensy 3.6 MCU and associated digital circuitry. However, all the analog audio circuitry is contained on a separate board.
For the various amplifiers, I decided to use op-amps that were specifically designed for low-noise audio operation. These parts generally require bipolar power supplies in the range of 12V to 15V. To provide this, I used a tiny CUI PEM1-S12-D15-S. This isolated DC-DC converter takes a 12V input and provides ± 15V output (unregulated). I use LM78L12 and LM79L12 regulators to provide quiet, regulated ±12V for the op-amps. The common terminal for this ±12V supply is isolated from the ground on the MCU/ADC/DAC board. to reduce any chance of ground loops/ ground noise. You need to connect the analog circuit’s ground to the mixed signal (ADC/DAC) common node at some point, but you can control ground loops much better when using an isolated power supply.
— ADVERTISMENT—
—Advertise Here—
Most professional microphones (including my own) are condenser microphones, which have an internal preamplifier that requires power. This has traditionally been supplied by a 48V source (called “phantom” power). This is generally provided by the mixing console that the microphone is plugged into. Early condenser microphones actually contained a tiny vacuum tube preamplifier, so a 48V supply was about the lowest voltage that would allow the tube to perform properly. Such microphones need three-wire connections and generally use an XLR 3-Pin connector. A differential signal is output on two of the pins (#2 and #3) and the 48V phantom power is applied between both these pins and the third, the ground pin (#1). The condenser microphone’s differential output signal is very low impedance—typically 100Ω. The combination of a differential signal, with a low source impedance, means that the self-noise figure for good condenser microphones will be very low, and the cables can be of significant length without degrading this significantly.
I used a similar CUI DC-DC converter, the PDME-S12-D24-S for the 48V phantom power source. This module also needs a 12V input and provides an isolated ±24V (unregulated). The specifications for 48V phantom power call for 6.8kΩ resistors in series with the supply to both differential terminals. This means that the maximum current that could be drawn by the microphone (with a shorted cable) would be:
The PDME-S12-D24-S has a current capacity of 21mA, so it’s more than adequate. I used an LM317T-HVT to drop the 48-55V unregulated output from the DC-DC converter down to 45V. This is a bit lower than the 48V standard but is perfectly adequate, and it allows headroom for the LM317T-HVT. Note that I didn’t use a regular LM317T, because it can only handle 35V input. The LM317T-HVT regulator also provides a quieter power source than the DC-DC convertor would on its own.
Because I had built various audio preamplifiers in the past, I was aware that designing a good, low-noise microphone preamplifier wasn’t easy. At the professional studios level, such preamplifiers are made using specially-chosen low-noise transistors. However, Analog Devices makes the SSM2019 Audio Preamplifier IC, which has specifications that rival the best discrete transistor designs.
Back when I first became interested in music in the 1970s, a Silicon Valley company called Solid State Music (SSM) produced analog synthesizers and other equipment. Later, they were acquired by Analog Devices. Since the SSM prefix is not a common Analog Devices prefix, I suspect the SSM2019 device was designed by the SSM company and kept alive by Analog Devices. The SSM2019 is still available in a DIP-8 package, which is what I used.
Almost no external circuitry is needed to implement a complete condenser microphone preamp using the SSM2019. The two input pins must be isolated from the 48V power present on the microphone’s differential signals. This is done using two 47µF capacitors that must be rated at 63V minimum. The SSM2019’s + and – inputs should have a 180pF capacitor placed across them, to filter out any stray RF noise that might be present. I connected a DB103G bridge rectifier across the + and – inputs. The bridge’s + and – terminals are connected to the plus and minus 12V power supplies, respectively. This shunts away any large transients that might occur when the 48V power is switched on/off or the microphone cable is unplugged. The SSM2019 is well-protected against transients within its ±12V power supply range, but not beyond that.
The gain of the SSM2019 is set by the value of the resistor placed between pins 1 and 8, using the following equation:
Gain = 1 + 10,000/R
For this project, R can vary between 22Ω (Gain = 455) and 2,022Ω (Gain = 5.95). I used a 2kΩ antilog pot as the microphone trim pot. because it provides the “smoothest” gain variation—given the logarithmic nature of human hearing and the pot’s location in the feedback loop.
If you look at J2, the microphone input jack shown in Figure 3, you might wonder what kind of jack it is, given its complexity. I used a Neutrik NCJ9FI-H combo XLR jack. This is a rather clever design, incorporating both an XLR jack and a ¼” phone jack in one package. I have it wired up so that if a phone jack is plugged in, the internal switching will disconnect the SSM2019 (fed by the XLR input only), and instead use the signal coming directly from the phone jack.
Signals coming into the phone jack are expected to be at normal Line Input levels, that is, 100mV to 1V. I use a TL082 dual op-amp following the SSM2019 (or direct line input) to raise the signal by a factor of 4.7. The Line Input impedance is 47kΩ—not quite high enough for an electric guitar, but fine for synthesizers, for example. Each output of the TL082 is sent to two potentiometers. One pot is labeled Chan1 (or 2) and adjusts the level of the signal that is fed to the PCM1808 ADC. This ADC has a full-scale input of 3Vp-p. Just like I used with the SSM2019’s inputs, I use a DB103G bridge rectifier, referenced to ground and +5V, to limit the input signals to the safe range specified by the PCM1808 datasheet.
The second pot fed by both TL082 outputs is the 10kΩ MIX pot. This is a dual-pot, so it adjusts both channels simultaneously. The MIX pot allows a user-selected amount of the Chan1/2 signals to be sent to both the Headphone and the Line Outputs. This gives “real-time” monitoring of Chan1 and Chan2 during recording. Your DAW software can optionally feed the input signal(s) being recorded back out to the DAC (via USB) for monitoring purposes. However, in this case, there will be some latency introduced by the ADC/DAC and the digital signal path. Although I have carefully measured this latency in the Teensy Audio library blocks and found it to be 6.4ms, I don’t know how much more latency would be introduced when it is sent in/out through the USB port, plus that introduced by the DAW software running on the PC. In any case, all commercial digital mixers provide this real-time monitoring and don’t rely on monitoring the signal that goes through the ADC/DAC and the rest of the digital signal path.
For both the line output and headphone outputs, there is a TL082 dual op-amp, which mixes these two signals (from each channel): the Mix signal mentioned above, and the output of the UDA1334 DAC.
The output of both sections of this TL082 is fed to two dual pots. One of them is the headphone level pot and the other is the line output level pot. A NE5532 dual op-amp with a gain of 3.1 feeds the Line Outputs.
Early in the design process, I needed to be able to test the ADC and DAC long before I had built all of the analog circuitry previously mentioned. I just needed headphones to do this, and since I had not yet built the analog circuit board, I didn’t have the ±12V isolated power supplies, which would later be mounted on the analog board. I therefore used a TLV2462 single-supply/rail-to-rail dual op-amp for the headphone amplifier. This little amp, in a DIP-8 package, is capable of up to 80mA output current. This is much more than is ever needed by standard headphones with 32Ω transducers.
The separate board, which contains nearly all the audio analog circuitry and the two isolated DC/DC converters that power the analog circuitry. There turned out to be lots of connections between this board, the top/rear panel, and the MCU/mixed signal circuit board.
The components used on both the UDA1334 and the PCM1808 breakout boards are shown in Figure 3, within the dashed lines surrounding the respective devices. Figure 5 shows a photo of the analog audio circuitry plus the two tiny, isolated DC/DC converters that supply power for this board. Figure 6 shows a photo of the MCU/Motor Control/ADC/ DAC board.
The MCU/motor controller and mixed-signal board. I also included the analog headphone amplifier at the bottom/left, since there was no room left on the analog board for this circuitry. Here, too, there were a lot of connections between this board, the enclosure panels, and the analog board.
In my next article, I’ll finish describing the circuitry and explain how the motorized fader pot works.
RESOURCES
Teensy 3.6 Arm MCU module: https://www.pjrc.com/store/teensy36.html
SSM2019 microphone preamplifier:
https://www.analog.com/media/en/technical-documentation/data-sheets/SSM2019.pdf
PCM1808PWR ADC:
https://rocelec.widen.net/view/pdf/6wldnnshcx/pcm1808.pdf?t.download=true&u=5oefqw
UDA1334 DAC breakout board (Adafruit ID 3678):
https://www.adafruit.com/product/3678
(Note: This board has been discontinued and replaced by the Adafruit I2S 3W Class D Amplifier Breakout – MAX98357A
https://www.adafruit.com/product/3006
PDME1-S12-D24-S Isolated DC/DC converter ±24 volts:
https://www.cui.com/product/resource/peme1-s.pdf
PEM1-S12-D15-S Isolated DC/DC converter ±15 volts:
https://www.cui.com/product/resource/peme1-s.pdf
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • SEPTEMBER 2022 #386 – Get a PDF of the issue
Sponsor this ArticleBrian Millier runs Computer Interface Consultants. He was an instrumentation engineer in the Department of Chemistry at Dalhousie University (Halifax, NS, Canada) for 29 years.