Audio For Teensy3 - What Features Would You Want?

Status
Not open for further replies.

PaulStoffregen

Well-known member
Edit: The audio board for Teensy3 is now available:

http://www.pjrc.com/store/teensy3_audio.html



Recently I've started working on audio for Teensy 3.0. It's still in the early stages. My hope is to make an alpha release in late September.

In the meantime, I'd like to start a conversation about possible audio interface hardware PJRC might sell. This is your chance to weigh in regarding features vs cost... what should I put on the board that you'd find really useful, and what should I leave off to keep the physical size small and the cost lower?

For projects where you only need moderate quality, like you'd get with Adafruit's Wave Shield on Arduino Uno, the option will be there to get it from Teensy3 using only resistors and capacitors on PWM and analog input pins.

For 16 bit stereo at 44.1 kHz (roughly CD quality sound), of course a CODEC or DAC is needed. I'm looking at several options. All have stereo line level output. Most have the ability to drive headphones (33 ohm load). Nearly all CODECs can accept a signal from a electret condenser microphone, the same type you'd plug into the pink audio jack on a PC. These are pretty much the baseline features.

The first big choice, where I'd really like your input, is connectors! Connectors increase the cost moderately, but of course the circuit board would become much larger than a Teensy3 if it had 4 RCA jacks for line in and out, a green headphone jack & pink mic jack, and big terminal blocks to wire up speakers. How important is small size? Should I keep the circuit board approximately the same size as a Teensy3, even if that means not bringing out every possible signal, or cramming stuff like line-level in/out to 0.1 inch spaced pads?

Another big question is how important are stereo line level inputs? Or microphone input? An output-only DAC or a CODEC with stereo output but mono-only input might really reduce the cost. Should I consider this, or is stereo input really an essential feature?

Another option which I personally think I'd use is a built-in amp capable of about 1 watt to an 8 ohm speaker. Sure, you can always build another board for the amp, or use amplified PC speakers. But for a Teensy-sized project running from three AA batteries or a 3.7V Lion battery, having a highly efficient (class-D) amp that can be power managed via the I2C seems pretty useful. But amplified speaker output does add a few dollars, and more if it's capable of 2 speakers. Is that worthwhile, or just an unnecessary expense?

Adafruit's shield has a nice volume knob. All solutions I'm considering have software controlled analog volume adjustment. But I could add a pot that connects to an analog input, so your program could periodically read the knob position and adjust the volume. Again, it's a matter of extra board size and extra cost... so is that worthwhile, or should I just leave it off?

Maybe there's other audio hardware I've not considered? I'm open to feedback. I'd like to make something that will really be useful, so I'd really like to hear your opinions, especially on the trade-offs between features, physical size, and cost?
 
Last edited:
nice. my 2 cents would be this (depending on your target audience, of course, but from what you're writing it seems it's neither greeting cards makers nor DAC hifi craziness.)

as to connectors, keep it flexible. i can't speak for everyone but i'd imagine people using won't just simply stack it onto their teensy but probably will put it somewhere (in a box, behind a panel, etc) along with any pots, encoders or what have you, so why have onboard jacks if these - RCA, or phone jacks, or 1/4", or XLR - who knows - ultimately are going to sit somewhere else (the audio codec shield, for example, though nice enough, is physically too unwieldy, for my taste at least). in that case, it would also make it easier to further condition your signals (eg amplify beyond line level), ie without having to desolder jacks or the like.

another thing to consider, again depending on your target audience, is SRAM ... though that wouldn't exactly reduce costs, of course. i'm not sure where you're heading with your audio API, but i'd image that it would increase the usefulness considerably; after all, there's only so much you can do in between i and o without. it certainly would fill a niche (audiophiles can get their i2s DACs on ebay already, there's plenty of lo-fi mp3 shields, not everyone is into blackfins et al).

anyways, thanks for doing this! i'm especially curious what you come up with with the API, but that's probably not the thread to bring this up.
 
Last edited:
Hi

Connectors:
None. Really. The connectors used in audio are to large. My Suggestion would be either solder pads/holes or small connectors that can be used with a short adapter cable.

Volume Knob:
I'd suggest a rotary encoder that can be pushed. Debouncing can be done in software i think.

Inputs:
Stereo line level is not important IMHO. I'd go for mono input. Instead of a microphone input I'd suggest a mic preamp (maybe with an option to add phantom power) with an option to route either a line level input or the mic amp to the CODECs input.

Outputs:
Well, I2S of course. Maybe S/PDIF would be a useful addition, CMOS-Level to attach an optical transmitter or consumer-level (which is 0.5Vpp IIRC). And unbalanced analog line level outputs.
Power Amp:

Other Hardware:
A micro SD slot would be excellent!

regards
ben
 
The ugly prototype on my desk today....

audio_1st.jpg

And a first attempt at a cleaner PCB with 2 jacks and a AC97 style header for line in & out.

http://www.oshpark.com/shared_projects/MQX1qj7Z

None of this is meant to be the final form.

Regarding the API and software, let's discuss that over on the other thread. It's all still at a pretty early stage of development, so there isn't a lot to tell at the moment.

This thread is really about the hardware, and specifically what trade-offs should PJRC make with features vs physical size vs cost.
 
Last edited:
I can't give too much input from a hardware point of view as I'm very new to all this. But... I've been a musician for 23 years and a (computer based) producer for 13 of those, so audio I can do!

For me, the ability to use stereo line level audio would be REALLY important. But this could (should?) be 2x mono... I can certainly see the value of having a microphone input for many projects, but for studio based projects my mind starts to go slightly crazy starting to think of all the options an easy access line level audio port would open up for me. As Ben said I would not be too concerned about selecting my own audio connector(s) so solder holes.

As for output - I'd probably say optical or sp/dif at this point as I could hook it straight into my desk with no D/A/D conversion going on. Actually, I could say that for input too, now I think about it!

Perhaps I'm not helping after all :)
 
Audio is such a large and diverse world... I've been using Twisted Pear audio products for quite a few years now. Specifically, their DAC and linestage products are quite good. I've built a few different versions of each. You might get some good ideas here: http://www.twistedpearaudio.com/landing.aspx

If you are interested in audio signal processing and other i/o types of features check out MiniDSP - http://www.minidsp.com/products for more ideas.

Food for thought
 
Obviously this won't be for Teensy 3.0, but I suspect some transformations people want to do with sound are easier if the chip has hardware floating in it. If you were going to change processors for Teensy 4.0 to get floating point, you would probably want to keep the single cycle multiply and some vector integer multiply instructions, which is another thing often times used for audio processing.
 
connector

I also quote to use empty pcb holes so It's easy solder a connector if needed. Audio connectors are too large and small ones are ok just for experimenting but nasty for a final project (think about boxing it)

volume knob
Don't know how much it's useful, but I will quote for a rotary encoder either.

outputs
Of course I2S is necessary, SPDIF useful too.

What I still not understand is if you want to use an audio codec chip, an interface chip or whatever! Audio codec chip have usually poor quality DACs, interface chip like wolfson are excellent in quality but has some small bug and need separate ADC/DAC, there's a really large amount of options, maybe too much to focus an hardware solution easily.
Maybe the best option is an audio codec for ready to go experiments with the ability to disable for add externally high quality ADC/DAC though I2S and SPI.
I have done a lot of experiments with DACs/ADCs and personally what I never got is an ADC with external audio clock that works without a massive jitter, I got close but have to use a FPGA and lots of pain...
 
I would prefer that the board

a) concentrate on things which it can do well and which other people may find hard
b) leave off things which are easy and where there are many different choices
c) avoid getting in the way or blocking off useful options
d) design for expandability

Since it is easier to discuss a concrete example I'm going to pick a board that I ordered a couple of and found dissapointing, and explain why. Have a look at audio codec board from MikroElectronika
(linked from http://www.mikroe.com/add-on-boards/audio-voice/ whichhas a variety of audio boards useful for comparison)

Here is the board description, mostly copied from the codec itself:
The on-board Audio Codec WM8731 provides stereo line and mono microphone level audio inputs. This module also uses stereo 24-bit multi-bit sigma delta ADCs and DACs with oversampling digital interpolation and decimation filters. Stereo audio outputs are buffered for driving headphones from a programmable volume control. Line level outputs are also provided along with anti-thump mute and power up/down circuitry.
and here is the reality:
one third of the board space is taken up by soldered-in mic and headphone connectors. The chip does indeed provide stereo line in and stereo line out but the board does not expose them. Not even some pads on the edge; if you want to access those, you need to solder directly onto the pins of the small, surface mount chip which is made harder by nearby components. Instead, the board gives access to the (mono) mic in and the (stereo) headphone outs, only.

Conclusions - avoid hiding features. Make expansion easy. An audio connector is two wires and takes space so please let people select and connect their own. Same for lofi speakers and lopower amps and such - these things are very widely available and easy to connect. One size does not fit all, let people select and connect what they want here.

That codec would make the basis for a great "audio for teensy" board, if the features were exposed, the connectors dropped, and maybe a couple of adjustable gain smd op-amp buffer stages added in as well.

As an example of making expansion easy - if the eventual board was mono, and if it had digital control over volume, then having a pair of pads that let you connect two boards and get stereo volume and balance would be neat.
 
So far, there seems to be 2 common themes:

1: One size does not fit all, maybe not even most?

2: Every available input & output option must at least come to solder pads.

On point #2, I'm using that same MikroElektronika board for prototyping. As you can see in the photo above (reply #4) I've already had to desolder the crystal, because it didn't provide a way to run in slave mode, and I've added a wire soldered to the side of one of those big capacitors, since it didn't provide the output at a pad or any other place where I could clip a scope probe.

Teensy 3.0 has I2S. If you want direct digital audio and you can use I2S, the pins are:

Code:
  TXD    22
  RXD    13
  BCLK   9
  LRCLK  23
  MCLK   11

Two of these conflict with the SPI port. I'm working on an extension to the SPI and SD library, which will appear in Teensyduino 1.16, to easily reassign the SPI signals to their alternate pins.

For S/PDIF and analog audio, of course a interface or dac/codec chip that takes I2S is needed.

I'm starting to think this might need to be 2 or 3 different boards. I'll probably make a low-cost board first, with line level stereo in and out and amplified output for headphones. It will very likely have a single 3.5mm jack, even though that adds to the size, because for just trying things out it's extremely convenient to be able to just plug headphone in.

I'll probably make a couple others boards to try S/PDIF and an audiophile quality DAC. These might be just DIY boards, maybe even just order the bare board from OSH Park, parts from Mouser and solder it yourself.
 
Last edited:
.. for just trying things out it's extremely convenient to be able to just plug headphone in.

no question, but one thing worth considering is that for just trying things out, things like that mikroe/wolfson board, or even some 12 bit dac shield, basically are around already. at the other end of the extreme are dsp development boards, but there's nothing, or little (i know of), in between, save certain dspics maybe. nor are these existing things typically very suited - connectors would be one example, buffering/amp stages another (not too mention form factors) - to actually be put in a usable design/device, which is, i guess, one of the strengths of the teensy and what i take a lot of the people here were getting at when asking for connectors being exposed etc.

i'm guessing specific needs are best served by coming up with one's own pcbs, but there also seems to be room for some kind of slightly more advanced audio (or dsp) shield*, which perhaps wouldn't be a matter of AD/DA only but also of memory (sd card / sram), op amps, power (rail to rail/single supply), etc, options. (i'm not saying i know how such a thing would look like, let alone how it could be made to fit everyone's needs).

* interesting project, for example, in this direction seems to be this - http://hoxtonowl.com/hardware/specification/ - though unfortunately, unless you are into that kind of thing, very much geared towards being a guitar effects thing.
 
Teensy 3.0 has I2S. If you want direct digital audio and you can use I2S, the pins are:

Code:
  TXD    22
  RXD    13
  BCLK   9
  LRCLK  23
  MCLK   11

I thought transmit and receive had their own set of pins. Can transmit and receive use the same BCLK and LRCLK pins?
 
There are many possible I2S configurations. However, I'm planning to support only 2 in Teensyduino: transmit-only using 4 pins and receive+transmit using 5 pins. The clocks are shared in receive+transmit mode. In both modes, all 3 clock pins are outputs from Teensy3, so whatever DAC or CODEC you use must be configured in slave mode, to receive all the clocks from Teensy3.

Edit: Most CODEC chips require shared clocks, so this 5 wire configuration is the only way that works with many of those chips. If you build a system with a separate DAC and ADC, it's perfectly fine to run the 3 clock signals to both chips, and of course the RXD pin to only the ADC and TXD to only the DAC.

Edit again: MCLK will always be created in 256*fs mode, which is by far the most common mode compatible with nearly all audio DACs and ADCs.
 
Last edited:
I'm not convinced having the Teensy provide the master clock is a good idea. E.g., if you look at the WM8731 datasheet, it needs a clock with less than 1ns jitter. The K20 I2S can use an external clock - any reason not to do that?

There are quite a few DAC boards with I2S out there, what do you want to do better than them?

I would prefer to see a Bluetooth Teensy over an audio board, which is even somewhat relevant to this thread, since it could drive Bluetooth speakers.
 
The K20 I2S can use an external clock - any reason not to do that?

The main issue is clock synchronization. The audio API will provide the ability to connect audio streams from many different types of objects, most of which are sync'd to the Teensy3 system clock. This system is intended to make building really interesting audio applications very simple, but to achieve that easy compatibility, all samples rates must be in sync.

Perhaps at some point, someone (maybe even me) might create an alternate I2S object that supports external clocking. But it will need to deal with the asynchronous relationship between the 2 sample rates. That's certainly possible, and in theory just a small matter of programming. However, in practice, someone needs to put the work in. At least in the forseeable future, the software layer will require all audio objects to be in sync.

Currently I'm generating MCLK from the system clock, which is based on the 16 MHz crystal multiplied by the on-chip PLL. The Teensy3 PLL probably isn't as good as the one inside that Codec chip. Then again, I'd be pretty amazed if a low-cost Codec chip like the WM8731 had a really great PLL. They mention their crystal oscillator is great, but that applies to pretty much all crystal oscillators, unless you do something really wrong like couple digital signals to the sensitive crystal signals (as Arduino Uno R2 did). In real systems jitter comes usually comes from noise sources in the PLL.

Wolfson doesn't give any specs on their WM8731 PLL, or even mention its jitter performance. If you read the WM8731 datasheet's "Test Conditions" above each set of specs, you'll see absolutely every audio performance parameter is specified only in slave mode. Presumably they're testing with a virtually perfect MCLK. When reading datasheets, the gotchas are almost always the things they don't mention (datasheets are written by marketing departments with one and only one goal, which is to sell you the part). I may be a bit too cynical, but I've been burned countless times by datasheets that only specified a part in one way, so when they don't give any specs at all for the other mode, I tend to assume that means it doesn't perform nearly as well.

I haven't looked at every part of the WM8731 datasheet and configuration. But if the chip has the ability to not use its PLL and if you use a 11.2896 MHz crystal, I would imagine it would probably perform very well (but still, that's just guesswork.... since the chip has no specs at all for master mode).

So, back to slave mode.... Teensy3 has an option, which I'm going to try soon, to generate MCLK by fractional dividing the direct (well, buffered) crystal oscillator output, without going through the PLL. If that works, odds are it should have very low jitter.

But even using the PLL might not be so bad. Looking at the Freescale datasheet, there are jitter specs for the PLL, at 48 and 100 MHz. Teensy3 runs the PLL at 96 MHz, which is pretty close to 100 (and the 100 MHz specs are much better than the 48 MHz ones). The datasheet claims 50 ps of "PLL period jitter (RMS)" and 600 ps of "PLL accumulated jitter over 1µs (RMS)", in section 6.3.1, pages 26-27. A footnote warns "This specification was obtained using a Freescale developed PCB. PLL jitter is dependent on the noise characteristics of each PCB and results will vary". Freescale also specifies RMS measurement. Wolfson's "clocks with less than approximately 1ns of jitter to maintain performance" recommendation isn't clear (at least to me) if they mean RMS or peak or something else. So while 600 ps seems pretty comforting compared to the 1 ns recommendation, I am concerned about jitter.

But my primary design goal is providing an API that makes audio extremely easy. Systems like MAX/MSP and Puredata do that on PC-class computers. I want to bring that to microcontrollers with the sort of extremely simple and easy interface you'd expect from using Arduino. I need the sample rates synchronous with the processor clock to do that.


There are quite a few DAC boards with I2S out there, what do you want to do better than them?

Well, that's a good question. Certainly you can use any DAC or Codec board, or make your own.

My main goals, at least for a first audio interface board, are convenient and affordable.
 
Last edited:
I'm not convinced having the Teensy provide the master clock is a good idea. E.g., if you look at the WM8731 datasheet, it needs a clock with less than 1ns jitter. The K20 I2S can use an external clock - any reason not to do that?

There are quite a few DAC boards with I2S out there, what do you want to do better than them?

I would prefer to see a Bluetooth Teensy over an audio board, which is even somewhat relevant to this thread, since it could drive Bluetooth speakers.

I agree, I'm running a WM8737 ADC as master with a 12.288MHz external oscillator and it's working correctly. When I try to run the ADC as slave using the teensy 3 I2S0_MCLK I can't get the timing right.
 
I agree, I'm running a WM8737 ADC as master with a 12.288MHz external oscillator and it's working correctly. When I try to run the ADC as slave using the teensy 3 I2S0_MCLK I can't get the timing right.
Do you have a scope to see what's wrong or different with the teensy-generated MCLK?
However, even if that particular issue will be solvable, I'd like to see the quality of T3s MCLK. Paul, I *think* I can provide you with measurements of the clock if you provide me with code for the T3. I have to check if I'm still capable of operating the measurement circuit though...
 
Do you have a scope to see what's wrong or different with the teensy-generated MCLK?

Oh man, you are a genius. I was thinking that the MCLK couldn't be used when the teensy 3 was in slave mode. It can! It works great. No need for the external oscillator. Thank you.

I'm not sure why (maybe 'cause my teensy is running at 48MHz?), but I have to configure the MCLK with the following in order to get 12.288MHz:

Code:
I2S0_MCR = I2S_MCR_MICS(0) | I2S_MCR_MOE;
I2S0_MDR = I2S_MDR_FRACT(31) | I2S_MDR_DIVIDE(124);
 
I must confess, I've been targeting only 44.1 kHz sample rate, which has been working very well so far. Admittedly, "so far" is at an early stage of development...

I just did a bit more testing with the MCLK generation. It looks like setting I2S_MDR_FRACT higher than 1 (where 1 means multiply by 2) creates an utterly unusable clock waveform. The edges have very low jitter, but the waveform doesn't have consistent duty cycle. At least that's my impression by looking at it on my scope, but I haven't tried actually using a DAC or Codec with it.

Luckily, 44.1 kHz sample rate needs only I2S_MDR_FRACT(1) when using the 96 MHz PLL as input.

If you want to make some measurements, here's a test program.

Code:
void setup() {
  boolean usePLL = true;  // from PLL
  //boolean usePLL = false;  // from Crystal
  
  SIM_SCGC6 |= SIM_SCGC6_I2S;
  CORE_PIN11_CONFIG = PORT_PCR_MUX(6);
  if (usePLL) {
    // MCLK = 96 MHz * 2 / 17
    I2S0_MCR = I2S_MCR_MICS(3) | I2S_MCR_MOE;
    I2S0_MDR = I2S_MDR_FRACT(1) | I2S_MDR_DIVIDE(16);
  } else {
    // MCLK = 16 MHz * 12 / 17
    OSC0_CR |= OSC_ERCLKEN;
    I2S0_MCR = I2S_MCR_MICS(1) | I2S_MCR_MOE;
    I2S0_MDR = I2S_MDR_FRACT(11) | I2S_MDR_DIVIDE(16);
  }
}

void loop() {
}
 
Last edited:
Here's the jitter I'm seeing. These are delayed to the next rising edge after the one the scope is triggering, and zoomed in to the fastest time scale my scope supports. So the fuzzy area is probably 2X what we'd consider jitter, since any jitter also affects when the scope triggers.

This first one is the PLL: 96 MHz * 2 / 17

scope_8.png

This second one is directly from the crystal: 16 MHz * 8 / 17.

scope_9.png

You can see how the rising edges are much sharper, because there's no PLL involved.

Unfortunately, the digital divider is creating different width pulses when configured to multiply by more than 2. Even though the edges have very low jitter, the different width pulses are effectively massive jitter. I'm pretty amazed Freescale would even bother putting this hardware in their chips. I can't see how this could ever work well with pretty much any DAC or Codec?

At least I2S_MDR_FRACT(1) works very nicely, admittedly with the PLL's extra jitter, which isn't huge but is obviously not as clean as directly from a crystal oscillator.

Edit: Here's a single-shot capture of the 16 * 8 / 17 waveform. Massive changes in clock period are present, not just the 2 ns spread seen above. Totally unacceptable!!

scope_10.png
 
Last edited:
My opinions/suggestions:

  • Leave the easy stuff to us, like soldering connectors, speakers, microphones, and controls.
  • Prioritize one interesting niche/use case.
  • Sell a kit for the number one use case.
  • Sell the module by itself for secondary use cases.


A few ideas for use cases:

  • Small battery-powered music player
  • Signal generator
  • Synthesizer for a portable musical instrument
  • Speech synthesizer for robotics
  • Signal processor for sensor applications, e.g. water flow monitoring via contact mic on water pipe
  • Sonar experimentation platform
  • Low-end radio transceiver (?), e.g. something that works in the unrestricted bands like garage door openers
  • 802.15.4 transceiver (?)
 
The Adafruit module seems good as a learning toy, but not so good for making a gadget that one would use on a daily basis. The the sound quality isn't so good for music, the module itself seems larger than need be, and it's a shield for an 8-bit processor so maybe processing audio in realtime will be a bit limited.
 
Maybe a standalone PLL-IC with a frequency ratio of 1 could help reduce the mclk jitter to an acceptable level. However I don't know if such chips exist, nor their price, nor wether they can lower the jitter far enough.
 
I'll toss my two cents into the pile:

1) I'm with the other posters, no actual output *connectors* on the board - let me decide if I want to use quarter inch, 1/8th, RCA, whatever. Just give me some through-hole .1" connectors for everything.

2) I can't think of a situation that would really require a stereo input. What might be nice, though (and quite probably impossible) is to have it split into multiple boards - an output module, and an input module, with the ability to stack one/two/four/whatever input boards.

3) I'm doubtful that an on-board amp is necessary. This board should be similar to a portable CD player of old, if I need to amplify it to get it to full speaker level, I can plug it into an amp.

4) No volume knob. Keep it simple. Again, like the audio connectors, it's best to leave it up to the end user to attach a rotary encoder or a pot to the Teensy, and then use that to control the volume output of the audio board.

5) I'm really tempted to use this thing as neat little lo-fi synthesizer now. That could be really, really fun. Teensynth. (Find some old SID chips and let me make a ridiculous Commodore 64 chiptune synth, Paul! :p)
 
Here's what I'm planning (so far) for the first simple & low cost audio interface.

audioboard.png

The pinout at the top is meant so you can use a PC front panel audio bracket. Of course, if you just want to solder wires, you can do that too.

The headphone output uses a virtual ground, which is actually about 1.5 volts, and then the 2 audio outputs to the headphones are relative to that voltage. The virtual ground must not be shorted to system ground.

This is still preliminary, so changes are possible.....
 
Status
Not open for further replies.
Back
Top