Multiple Stereo Inputs on Teensy 3.1 with Audio Shield

Status
Not open for further replies.
I am trying to create a simple stereo mixer with effects and so on to output to a single stereo output. I have had success using a single stereo i2s input, controlling a filter on it, the volume and outputting it through the i2s output with the pre-soldered headphone jack on the shield, but I want to add a second stereo channel to mix with.

I have been able to mix the i2s with a WAV player in stereo but I cannot see a way to add a second stereo input. The ADC appears to only use a single pin so that will not do. In the GUI Audio System Design Tool it is possible to add a second i2s object, however I suspect that this uses the same pins as the first?

A stretch goal would also be to record a stereo signal. The example is Mono but has anyone tried recording or playing 2 at concurrently?

Any help with this would be really useful, Thanks!
 
I have been able to mix the i2s with a WAV player in stereo but I cannot see a way to add a second stereo input. The ADC appears to only use a single pin so that will not do. In the GUI Audio System Design Tool it is possible to add a second i2s object, however I suspect that this uses the same pins as the first?

There is only one I2S device on the Chip.
 
Ok, so only two I2S inputs. Do you know if it is possible to read audio from more than one of the ADC pins at the same time or is there something special about the A2 pin for this?
 
I haven't worked with the audio libraries yet, so I can't tell you if it supports more than one ADC source but there's one thing you should be aware of when using ADC: all ADC pins on the Teensy are multiplexed to a SINGLE ADC converter. So, even if you're able to use two ADC pins in the same software, they won't be sampled at the exact same moment. Which, IMHO, makes it unfeasible for stereo recording...
 
Ah I see. That is a shame. It would only be a small difference in time but I guess that matters a lot where human ears are concerned. It would be interesting to see if stereo recording is possible although I could see how this may suffer from the same problem of not recording at the exact same moment and instead jumping between the two channels.
 
@randomthumper:
Your question about 2x stereo in on the teensy + audio shield platform is a good one.

The teensy 3.1 DOES have two ADCs, and there is code support for it, look here.

Now, what about 2x stereo?

The easiest way will probably be to let the SGTL5000 chip on the audio board grab the ADC, stream it to the teensy via I2S, mix there with the teensy-ADC-sourced audio and then output the resulting mix via the SGTL5000 again (to headphone/lineout).

There is a second, more obscure way:
From the SGTL5000's perspective (which I've worked with intensively in the last weeks), there is one ADC (mono mic or stereo line-in) and I2S in, and they can both be mixed together by a feature called dual input mixer (each channels controllable 0-200%). The current SGTL5000 library doesn't know how to do this, but setting the right bits in the DAP_CONTROL register and writing volume configuration to DAP_MAIN_CHAN and DAP_MIX_CHAN will get you started.
This will probably only be of use to people that have I2S audio sources apart from the teensy.
 
but there's one thing you should be aware of when using ADC: all ADC pins on the Teensy are multiplexed to a SINGLE ADC converter.

Actually, the are two ADCs inside Teensy 3.1, called ADC0 and ADC1. Almost all the analog pins mux to ADC0, but pins A2 and A3 mux to either.

Currently there is no software support in the Audio library for ADC1. But the hardware is present. Someday the software will probably be improved to support it.
 
There is only one I2S device on the Chip.

This is true, but the I2S port has two receive and two transmit data signals. I believe this might be able to support (with a lot of software work) receiving two stereo streams from two SGTL5000 chips. On the latest rev of the audio board, I added some pads to cut apart, so a 2nd board could have the other I2C address, and it's TX and RX signals wired to other pins.

Frank, if you'd like to play with this, just say the word and I'll send you two of the newest audio boards for testing.
 
Sorry, Paul and everybody for the wrong statement about the single ADC. I had the datasheet of the original T3.0 in mind (the one I read). Actually, I wasn't aware that the T3.1 has two ADCs.

Now, exploring the issue further and looking at the code in analog.c, it seems that some inputs already are mapped to ADC1, namely A13 and A15-A20 (all on the bottom of the Teensy 3.1 PCB). And, as Paul said, A2 and A3 (pins 16 and 17) CAN be routed to ADC1.

Wouldn't it be nice to have an "analogReadStereo()" function on the T3.1 that reads both channels simultaneously? Volunteers?
 
Thanks for all the info on this! I don't have another I2S device so I'll have to keep looking for a way to have two stereo line level inputs. So am I correct in saying that the audio shield provides 2 I2S inputs that make up the stereo input as in the GUI, plus the Teensy 3.1 has 2 ADCs that are not implemented to provide inputs to the audio library in stereo currently?

On the stereo recording side I've had a go at modifying the record example to write 2 raw files simultaneously and then play them simultaneously. It does just about make for stereo playback but there is a large delay where it hangs before starting recording and the playback is sped up, presumably because it can't write the two files fast enough so some parts get skipped? There is also a fair bit of noise and general loss of quality.
 
Also I thought I'd mention that what you've done with both the Teensy and the audio shield is awesome. I love how you have simplified the audio stuff with the GUI as I have never used a DSP and this allowed me to do so straight away. I have used dozens of Teensy 3.1 boards on various wearable project prototypes and the capacitive sensing in particular is a really well implemented, flexible feature that is massively valuable on every project I do. Having worked with a big selection of Arduino and Arduino compatible boards, I always tell everyone that the Teensy 3.1 is THE one to use so thanks for creating such an awesome dev board! :)
 
So am I correct in saying that the audio shield provides 2 I2S inputs that make up the stereo input as in the GUI,

The audio board provides a single I2S input that is stereo. I2S protocol is always 2 channels. One channel is transferred while LRCLK is low and the other while LRCLK is high. That's how I2S works.

Currently the software supports only 1 audio board. Someday 2 might be supported, for four sound channels. Maybe. But today, no such software exists.

plus the Teensy 3.1 has 2 ADCs that are not implemented to provide inputs to the audio library in stereo currently?

Correct. Today the software only supports ADC0 for mono sound.



On the stereo recording side I've had a go at modifying the record example to write 2 raw files simultaneously and then play them simultaneously.

You might have better luck if you re-arrange the data into a bigger buffer and write to a single stereo file.
 
This is true, but the I2S port has two receive and two transmit data signals. I believe this might be able to support (with a lot of software work) receiving two stereo streams from two SGTL5000 chips. On the latest rev of the audio board, I added some pads to cut apart, so a 2nd board could have the other I2C address, and it's TX and RX signals wired to other pins.

Frank, if you'd like to play with this, just say the word and I'll send you two of the newest audio boards for testing.

So I'd love to do that - going before winter, or even later, I will have no time for it, unfortunately.
 
On the stereo recording side I've had a go at modifying the record example to write 2 raw files simultaneously and then play them simultaneously.

I think, writing only one file, stereo, is much better (faster) because of less overhead for accessing the card.
 
Paul, everybody,

as I raised the issue, I was looking for a way to implement analogReadStereo(). One of the issues is to start measurement on both ADCs at exactly the same moment. From what I see in the datasheet, ADC measurement can be triggered externally. Unfortunately, I haven't found a software trigger (is there any?), so we seem to be restricted to a hardware trigger and the SIM_SOPT7 register lists the available sources.

Now, checking these trigger sources, almost all of them seem to have some side effects:

  • PDB external trigger pin input (PDB0_EXTRG) - this is either PTC0 (Teensy pin 15, the A1 input) or PTC6 (Teensy pin 11). So we would lose one I/O pin
  • High speed comparator outputs - maybe, these could be used. I haven't found any library that uses it. But probably there is one out there. Comments?
  • PITs - these are used by Paul's IntervalTimer library
  • PDBs - used by the Audio and Servo libs
  • FTMs - used for PWM output and various other libraries (FastLED, FreqMeasure, IRRemote, OctoWS2811, PulsePosition, TimerOne, TimerThree, Tlc9540, ...?)
  • RTC alarm and RTC seconds - could be used, but takes too long to occur

So, of all these sources, the one with the least impact seems to be the High speed comparator. We should be able to create a defined comparator output state by selecting appropriate fixed voltages as input (Badgap and DAC ref) and switching the PSEL and MSEL fields in CMPx_MUXCR - in theory.

For now, I would like to validate the approach with the following questions:

  • Am I right that there is no software approach to trigger conversions on both ADCs at EXACTLY the same moment?
  • If so, which of the mentioned hardware triggers seems be most feasible and have the least side effects?

Comments welcome...
 
@jdbliesener:
Is the analogSyncRead(...) implemented by the dual-ADC library not good enough?
I see that they're just started sequentially, but if that means microsecond-level delay, it might be fine for audio.
Should be testable by sampling a fast signal with both ADCs and looking for variations.
 
Thank you CyborgEars. I didn't know that library - should have checked first.

I'll see if I can replace the two "startReadFast()" calls in "analogSynchronizedRead()" with a hardware trigger through CMP and send a pull request to Pedro Villanueva, the author of the library. I'll also try to run some tests, I'll see if I can find some sort of signal generator.
 
Am I right that there is no software approach to trigger conversions on both ADCs at EXACTLY the same moment?

Correct, there is no software-only approach to trigger both ADCs at exactly the same instant. Likewise with DMA. Each as its own register to initiate the conversion. Software (or DMA) can only write to one address at a time, so it's impossible to cause both to begin conversions at exactly the same instant, by writing to their registers.

Of course, you could decrease the time to only a couple CPU cycles, which is a very tiny fraction of the time the ADCs take to convert the signals.

If so, which of the mentioned hardware triggers seems be most feasible and have the least side effects?

Probably the PDB timer, unless you're using the Servo library. Even then, you could edit Servo to use LPTMR, if you need the PDB for triggering ADCs.

Maybe the analog comparator would be useful, but I'm not sure if it's usable without dedicating a specific pin.
 
Maybe the analog comparator would be useful, but I'm not sure if it's usable without dedicating a specific pin.

I was thinking about feeding the analog comparator with two internally generated reference values: Badgap and DAC ref. I would assign one of them to the positive comparator input and one of them to the negative input. As one should always be either higher or lower than the other, this would give a fixed comparator output, either 0 or 1. Then, to change this output, I would switch PSEL and MSEL. Of course, I would have to configure the right settings for filter, window, etc. But it should give a clear 0-1 transition that can be used to trigger conversion on both ADCs.

Does this sound promising?
 
I think, writing only one file, stereo, is much better (faster) because of less overhead for accessing the card.

Do you know if this is possible with the Audio library? There isn't a module for this in the GUI that has stereo input for recording, only the queue one.
 
There isn't a module for this in the GUI that has stereo input for recording, only the queue one.

Correct. Someday the library might get recording objects that access media.

Until that day, to accomplish this you'd need to use a pair of the queue objects, where you receive their data in your sketch and combine the samples into a buffer, which you write to a stereo-format file. At least the queue objects handle the difficult task of automatically queuing up any data that arrives while your code is temporarily busy, such as the occasions where the SD card takes much longer than usual to complete a write (for whatever reason... allocating FAT clusters, FAT sector updates, region erase or wear leveling internally in the SD card, etc).
 
Status
Not open for further replies.
Back
Top