Audio Block Compatibility

Status
Not open for further replies.

jkoffman

Well-known member
Hi all,

I am planning on migrating my project to the Teensy 4, mostly for more power and greater flexibility with some interfaces.

I'm trying to double check if various blocks will play nicely together.

There are two Teensys in this project. The auxiliary one would be simple, it would have USB in/out, then SPDIF out and SPDIF_async in. Will this combination work?

The main Teensy is a bit more complicated. I will have it connected to an audio board, so there will be I2S in and out. Then I'd like to do SPDIF out and SPDIF_async in (interfaced to the Teensy mentioned above). I'm having trouble figuring out if it's possible to use SPDIF and I2S together. I assume the two SPDIF options both want to use I2S1, and I'm not sure that's allowed. If I had to, I could put the SPDIF_async input on I2S1, use I2S2 as I/O to the audio board, then use I2S3 for the SPDIF3 output. But for future expansion I'd love to keep an I2S interface free to allow dual audio boards (though in the future I may just go TDM to solve that issue, the SGTL5000 is just so easy to use).

I'd also like to know if it would be possible to use the ADC input and DAC output.

I plan on running some tests, it will just be hard to get all interfaces working without spinning a board, so if anyone knows if I'm making a mistake I'd love to hear about it!

Thank you!
 
Hi all,

I am planning on migrating my project to the Teensy 4, mostly for more power and greater flexibility with some interfaces.

I'm trying to double check if various blocks will play nicely together.

There are two Teensys in this project. The auxiliary one would be simple, it would have USB in/out, then SPDIF out and SPDIF_async in. Will this combination work?

The main Teensy is a bit more complicated. I will have it connected to an audio board, so there will be I2S in and out. Then I'd like to do SPDIF out and SPDIF_async in (interfaced to the Teensy mentioned above). I'm having trouble figuring out if it's possible to use SPDIF and I2S together. I assume the two SPDIF options both want to use I2S1, and I'm not sure that's allowed. If I had to, I could put the SPDIF_async input on I2S1, use I2S2 as I/O to the audio board, then use I2S3 for the SPDIF3 output. But for future expansion I'd love to keep an I2S interface free to allow dual audio boards (though in the future I may just go TDM to solve that issue, the SGTL5000 is just so easy to use).

I'd also like to know if it would be possible to use the ADC input and DAC output.

I plan on running some tests, it will just be hard to get all interfaces working without spinning a board, so if anyone knows if I'm making a mistake I'd love to hear about it!

Thank you!

Note, the Teensy 4.0/4,1 has separate pins for direct S/PDIF input and output. I haven't tried it out personally, but pin 14/A0 is the S/PDIF output, and pin 15/A1 is the S/PDIF input. The Audio Design tool lists the following inputs and outputs;
  • input spdif3: Receive S/PDIF digital audio, at the rate of the external digital audio source. Note this has a warning: `This input is incompatible with most other inputs and outputs`;
  • input spidif3_async: Receive S/PDIF digital audio and resample to Teensy's audio sample rate.
  • output spdif: Use I2S support to output S/PDIF to the default I2S output pin (22 on Teensy 3.x, 7 on Teensy 4.x).
  • output spdif2: Use I2S2 support to output S/PDIF to the default I2S2 output pin (pin 2 only on Teensy 4.x).
  • output spdif3: Use hardware S/PDIF support on Teensy 4.x to pin 14/A0.

I don't believe the I2S3 pins are brought out.

The Teensy 4.x does NOT have DAC outputs. If you don't need the main SPI bus, you can use the hardware MQS support to output sound via PWM pulses. It uses pin 10 (default CS) and 12 (MOSI) for the outputs.

I don't know about ADC support.
 
Thank you for the quick reply, and for reminding me of a few things!

I completely spaced on the DAC thing, my mistake there. I can dispense with that part.

I didn't realize that SPDIF on these chips doesn't use the I2S system. Reading the descriptions again it all makes a lot more sense. So in that case for output I'd want to use spdif3 and for input spdif3_async. I'm hoping these can run at the same time.

That leaves two I2S ports available for I/O via two audio boards, so that's good.

Still curious about the ADC, though now that I'll have two I2S ports I could go that route, or step up to TDM if required.

Anything else I'm missing?

Thank you!
 
Well, I just had a bit of a disappointing test. I took two Teensy 4.0 boards, connected SPDIF in on one to SPDIF out on the other, and vice versa. I also connected ground together.

Here's the audio setup portion of the code I ran:
Code:
// Outputs
AudioOutputUSB           USB_Out_1;           //xy=652,236
AudioOutputSPDIF3        spdif3_1;       //xy=674,308

// Inputs
AsyncAudioInputSPDIF3    spdif_async1(true, true, 100, 20); //dither = true, noiseshaping = true, anti-aliasing attenuation=100dB, minimum resampling filter length=20   //xy=408,225
AudioInputUSB            USB_In_1;           //xy=408,299

// Patches
//SPDIF to USB
AudioConnection          patchCord1(spdif_async1, 0, USB_Out_1, 0);
AudioConnection          patchCord2(spdif_async1, 1, USB_Out_1, 1);

// USB to SPDIF
AudioConnection          patchCord3(USB_In_1, 0, spdif3_1, 0);
AudioConnection          patchCord4(USB_In_1, 1, spdif3_1, 1);

When I play audio out of one computer and read it into another, I'm hearing what sounds like clocking issues. Interestingly if I only have one of the In/Out pairs connected I don't have clocking issues. I thought that using the resampling version of the SPDIF3 input would have dealt with clock issues.

Anyone have any idea what I'm doing wrong here?

Incidentally, the AsyncAudioInputSPDIF3 object would cause the code to hang if the Output wasn't defined above it. Also the options I used were taken directly from the PassThroughAsyncSpdif example file.
 
Last edited:
Hi,
the bug that you described is already fixed on the master branch of the teensy audio library. However, this version is not deployed with Teensyduino yet and you would need to manually replace some files of the audio library to get it.
Regarding the noise that you hear: Since it only occurs when you connect both channels, it might be related to the processor load. We know that at your setup the input frequency is 44.1kHz and therefore aliasing won't be a problem. So you could decrease the anti-aliasing attenuation (third constructor argument of the AsyncAudioInputSPDIF3) from 100 to 0. That will decrease the processor usage of the spdif input.
 
Hi there,

Thanks for the reply!

I tried altering the anti-aliasing attenuation but I have the same issue. I added the debug code you had in the example file, and here is a sample of the output:

Code:
buffered time [micro seconds]: 887.04
processor usage [%]: 8.00
buffered time [micro seconds]: 1005.69
processor usage [%]: 8.00
buffered time [micro seconds]: 730.42
processor usage [%]: 8.00
buffered time [micro seconds]: 854.65
processor usage [%]: 0.00
buffered time [micro seconds]: 789.07
processor usage [%]: 8.00
buffered time [micro seconds]: 1088.44
processor usage [%]: 8.00
buffered time [micro seconds]: 866.49
processor usage [%]: 8.00

These numbers are from the RECEIVING Teensy. I was curious, so I loaded the same firmware on the sending Teensy, and started the experiment again. While the processor usage is exactly the same (8%), I get an audible glitch everytime the buffered time drops below 1000uS. I'm not entirely sure what that means, but I thought it might mean something.

I then switched the sending Teensy to receive via spdif3_async, but send via spdif2. I still had to create a spdif3 output object so that the async receive object would initialize properly. The results were basically the same. I can transmit fine from sender to receiver. If I connect the transmit line from receiver back to sender, I get glitches that seem to correspond to buffered time dropping below 1000.

Any thoughts?
 
Could you also please output the input frequency (getInputFrequency()) and if the input is locked all the time (isLocked())? Both functions are also used at the PassThroughAsyncSpdif-example. But there they were commented out.
 
The reason why I am interested in the input frequency is that the input seems to regularly run out of input samples. One reason could be that the internal input frequency is much higher than the real input frequency.
 
I hope I am able to explain this all clearly.

I reverted to using spdif3 for transmit and spdif3_async for receive. I added the two tests you asked (more info later).

I started with just the transmitter transmit connected to the receiver receive. No return. It sounds like there is a problem. Example:

https://www.dropbox.com/s/vtiusc78mh59d7j/Input Device Recording 20200814 1622.mp3?dl=0

The serial output looks like this:
Code:
buffered time [micro seconds]: 1089.99
processor usage [%]: 8.00
isLocked: 1
frequency: 44099.75
Memory max: 6

There is some variation in the buffered time, but I haven't caught it going outside 1088 or 1089. Frequency is stable, and isLocked is always 1.

If I wait long enough, the noise clears up on its own. If I connect the return (receiver transmit to transmitter receive) then the above noise goes away and I get this:

https://www.dropbox.com/s/r3yb9aueblivrrt/Input Device Recording 20200814 1629.mp3?dl=0

Here's what the serial output on my receiver looks like:
Code:
buffered time [micro seconds]: 929.96
processor usage [%]: 8.00
isLocked: 1
frequency: 44099.75
Memory max: 6

buffered time [micro seconds]: 708.37
processor usage [%]: 0.00
isLocked: 1
frequency: 45101.95
Memory max: 6

The transmitter is similar. Buffered time is below 1000 most of the time, isLocked is always 1, but the frequencies are jumping around quite a bit. My guess is that I'm missing out on a lot of the actual frequency readings as I'm only outputting the values every 500mS. Both computer appear to be putting out 44.1, but something seems to be going awry somewhere.

I hope this info helps!
 
Thank you for the test. If I understand you correctly, the signal flow at your first test was as follows: PC1 -> usbIn_Teensy1->spdif3Out_Teensy1->spdif3In_async_Teensy2->usbOut_Teensy2->PC2. Right? At this test there is some distortion at the beginning but it disappears after some time? The debug output of your first test looks fine. This slight variation of the buffered time is normal and also the input frequency is plausible. I suggest that we first get this simpler setup running before you connect this return signal path. Regarding the noise that shows up at the beginning: Maybe the signal is clipped due to the added dither and/or the noise-shaping. Can you please set the first two constructor arguments of the async-input to false to check that? Also, you could lower the volume at the PC to see if it influences the noise.

Regarding your second debug output: The detected input frequency of about 45kHz probably causes the buffer underrun, since we know that the actual frequency is very close to 44.1kHz But let's first focus on first setup/ the noise.
 
Sounds good, I'm happy to follow any troubleshooting plan you're thinking of.

You are correct on the setup. The noise/distortion is present when I first connect the sending Teensy. It persists for some time, though how long seems to be variable. It took about 1 minute 40 seconds one time. I then disconnected the sending Teensy and reconnected and it took 1 minute 15 seconds to go away.

You are right that it does sound like clipping, but doesn't seem to be on the incoming audio. I can lower the level in the playback and the noise tracks up and down with the music volume. Here's an example:

https://www.dropbox.com/s/j8lh9e6zoevg04q/Input Device Recording 20200815 1121.mp3?dl=0

For the record, I lowered the volume on the transmitting computer, I believe the recorder I am using bumped up the level. It was much softer live, but the relationship between the noise and music is the same.

I updated the arguments, and initial tests show the noise has disappeared. So then I put them back to what they were, and the noise won't come back. So now I'm really not sure what to do. I'm going to let the setup sit for a bit and try again in a bit.

Just for reference, reconnecting the return does bring back the stuttering noise.

Thank you!
 
I think the clipping is caused by the dither and noise of the noise-shaping that added to the signal when noise shaping and dither is activated. I think I should set the default values at the constructor to false since the benefits are really low. That you can't reproduce the problem anymore is strange. Maybe you could use a tone generator that generates a pure sine for testing. There are also online tone generators and I think normally if the volume of the generator is set to the maximum, the level should be 0dBFS. Then the noise should definitely appear when the noise-shaping/ dither is active.
Regarding the stuttering noise: You mentioned that it appeared again when you connected the return path. Is that the same signal path as the 'forward' path and there are only the roles of the two Teenys and PCs swapped? If yes, you could maybe not add the complete path at once, but add one connection/input/output at a time and test at which stage this stuttering noise appears.
 
I agree that it's weird i can't reproduce it. I'll try again in the morning to see if the computer it more likely to make it happen after having slept awhile. Honestly I have no idea why that would make a difference, but who knows.

I've done some work with tone generators. I used a couple of online tone generators, and while volume didn't seem to be a factor, frequency did. Above about 1250Hz I can hear sort of a clicking/popping. Here's an example of it at 5000Hz (warning this might not be the most fun to listen to, definitely start at a low volume):

https://www.dropbox.com/s/tqh5717zq0ow6k4/Input Device Recording 20200815 2227.mp3?dl=0

So while the pops seem to track with the volume, if I play music I don't hear the pops or the previous distortion.

As for the return path noise, you are correct, the signal chain is the same as the send path just in reverse. There isn't a whole lot to these paths, basically it just goes from a USB block directly to a spdif block. I removed the patch cords so that on the main Teensy there is no connection between the spdif_async block and the USB output block. On the auxiliary Teensy I removed the connection between the USB input block and the spdif3 output block. The stutter still happens though. I can see a variation in input frequency and buffered time on the aux Teensy:

Code:
buffered time [micro seconds]: 875.18
processor usage [%]: 5.00
isLocked: 1
frequency: 44099.75
Memory max: 6

buffered time [micro seconds]: 1072.86
processor usage [%]: 5.00
isLocked: 1
frequency: 44099.75
Memory max: 6

buffered time [micro seconds]: 1072.96
processor usage [%]: 0.00
isLocked: 1
frequency: 44109.95
Memory max: 6

buffered time [micro seconds]: 783.72
processor usage [%]: 5.00
isLocked: 1
frequency: 44099.75
Memory max: 6

buffered time [micro seconds]: 873.15
processor usage [%]: 5.00
isLocked: 1
frequency: 44099.75
Memory max: 6

buffered time [micro seconds]: 853.09
processor usage [%]: 0.00
isLocked: 1
frequency: 45352.52
Memory max: 6

buffered time [micro seconds]: 957.65
processor usage [%]: 5.00
isLocked: 1
frequency: 44099.80
Memory max: 6

On the main Teensy I don't see any debug variations, which makes sense as it shouldn't be getting any actual audio data. So frequency and buffered time are 0.
 
I did a bit more experimenting this morning. I still can't get the startup distortion to reappear. I'll keep trying to see if I can characterize that one better.

On to the return path issue. I started by replacing the USB input on the main Teensy with a sine wave generator. It works fine until I connect the return, then I get the choppiness.

Then I took the Main Teensy and powered it off battery, to help rule out some kind of weird power issue. Same results.

Finally I took a third Teensy and programmed it with the sine wave sender. I connected them in a chain: New Teensy -> Main Teensy -> Aux Teensy. And the skipping didn't happen. If I move the wire back to the output of the Aux Teensy, it skips. But the output of the New Teensy doesn't cause a skip. I did verify that the New Teensy is indeed sending the same tone.

I'm still puzzling out what this all means, but thought I should share.
 
Regarding the 'clipping noise': I suggest that you keep the noise shaping/ dither turned off for now. Currently I am not at home, but next Sunday I will be back home and will try to reproduce you problems. I have two teensys 4.0, so I think that won't be a problem.
Regarding the second problem: You mentioned above that the stuttering noise was also there when you removed all audio connections. I would continue at this setup and further remove objects until the noise disappears. Could it for example be that the noise is always present when you create an usb input object on the aux Teensy? It would be helpful if you can pinpoint the problem to the presence of a certain object.
 
Sounds good.

I am going to try tearing everything apart and starting again. Do you have any recommendations for the links between the two Teensys? Should I connect out->in directly, or put in a resistor, etc.

Thank you!
 
I didn't mean 'tearing the hardware appart'. Are there that many connections? I thought about removing all software objects/ AudioConnections. I thought your problems are software problems. Regarding the spdif connection: Until now I never directly connected two teensys via spdif and always needed 0.5V consumer level. Therefore I always use a circuit to transform the voltage level.
 
Nah, not only two connections but I wanted to clean up the wiring, get everything as short as possible to eliminate issues there, etc. I guess "tearing it apart" sounds a bit more intense than it was. It took about 5 minutes!

I started with connecting only Main Teensy -> Aux Teensy. I tried this with both a wire and with a 100R resistor, both were the same. There is some clicking but it's very faint. You can just hear it in the background of this 500Hz tone:

https://www.dropbox.com/s/x899t0a2d6kbgqi/Input Device Recording 20200818 1049.mp3?dl=0

Then I connected the return path and sent a 500Hz tone back. In this case the clicking is more prevalent.

https://www.dropbox.com/s/eu2kavcch85mw36/Aux to Main.mp3?dl=0

I started stripping things around again (USB, etc) and the clicking was still present. I was trying to figure out why one direction seemed to matter more than another. The Main Teensy is on a Windows machine, the Aux is on a Mac. I swapped them, so the Main Teensy is on the Mac and tried to see if I still got the clicking. Much like the first setup, I do hear slight clicking on the Mac, but not as bad as this exact setup but plugged into the Windows machine. I'm not really sure what that means either.

I'm going to keep poking at this but now I'm starting to doubt my test setup. If you do get a chance to test on your side once you're back I'd love to know your results.

Thank you!
 
Let's see if I can reproduce your issue on Sunday. I am sure that my spdif in- and out work properly and if I can't reproduce your problems with the same Teensy program, then they are probably related to your cabling. I a have another question: I think normally (if the distance between your teensys is short) one would use the I2S interface to exchange the audio data. Since the Teensy 4/4.1 has two i2s interfaces, you could use one to connect the Teensys and one to add an audio board. Theoretically it should even also be possible to connect two audio boards to the 'I2S1' interface since there are 4 data channels and it's possible to configure two of them as (stereo) inputs and two as (stereo) outputs.
The big advantage of using i2s instead of spdif is, that no resampling is required. The main Teensy would clock the audio pipline of the aux Teensy.
 
Not a rush, I'm slammed this weekend and won't have time to test anything until Monday at the earliest. It wouldn't surprise me if this was something on my end.

What you're describing was basically what I did on my first prototype. However it was using Teensy 3.2 boards, which made things a bit trickier. The i2s_quad object on the T3.2 uses a different bit clock ratio than the stereo object, and there is no quad slave object. I ended up modifying some blocks and worked on blocks that others had altered. Getting the basic setup working was easy, but much like my current issues, the return path from the aux Teensy to the main Teensy has timing issues which I have so far been unable to solve. I should put together a test with the T4 and a couple of audio boards. One thing I've never really been sure of is what happens when you're going from USB In -> I2S Out and you are being clocked by another chip. I don't have a good understanding of how the T4 would deal with that. Does USB input get a clock from the computer? If so, wouldn't get be in conflict?

Thank you!
 
Regarding your question about the clocking: I had a brief look at the code usb input. The audio data is buffered in the usb input class and it never clocks the audio pipline. It looks like the Teensy sends back feedback about how many samples are currently buffered, so that the PC can configure the rate at which it sends the audio data. I would be glad if somebody, who has a better understanding of the usb input, corrects me if I am wrong. Anyway, if there is a problem regarding the clocking it would not only be present when data is sent from usb in to i2s Out, but also spdifOut is used instead of i2s Out.
 
Yesterday I had time to do some tests. Since you lately thought that your problems are caused by your spdif connections, I setup a small program to test the spdif data transfer. I commited the program to Github: https://github.com/alex6679/teensy4_debug The only three important files are in the src folder: plotter.h/plotter.cpp is a block that sends the audio data via usb serial to the PC. Here it could be visualized with the Arduino Ide serial plotter. The third file is test1_main.cpp, which contains the setup- and loop- functions. At my tests I used this program for both Teensys: An AudioSynthWaveform object generates a sine wave and sends it to the spdif- output. At the same time there is async-spdif- input, which sends its received data to the plotter. That's very similar to the setup you used. The AudioSynthWaveform replaces the usb-input and the plotter replaces the usb-output. But, as in your case, each Teensy sends out audio data via spdif out and receives data via async-spdif in. Can you please try this program? Since it works with my setup, you would know that your problem is somehow hardware related if your problems persist.
At my tests I deactivated the debug output by commenting out the lines 5 and 6 of test1_main.cpp at one Teensy and I debugged the second Teensy. When only line 5 is uncommented, the typical debug information like the input frequency is sent to the pc. When lines 5+6 are uncommented, the wave form is sent to the pc.
 
Apologies for the delay, but I am back and sorting through things. I will try out that code as soon as I can. I'm hoping this eliminates the SPDIF hardware as the culprit and perhaps makes me focus more on the USB interface.

Out of curiosity, what environment are you coding in?

Thanks!
 
Ok, I have done some tests, and here are my results!

Since I have the two Teensys connected to two computers, I left DEBUG defined on both so I could get the serial output. When running both with just serial, one of them is showing a frequency of 44100.45, and the other 44099.71. After a bit of stabilizing (under 5s) both have ended up with about 1088uS of buffer. It moves a little bit, but usually within 2uS tops. Before it stabilized it was in the 600-800uS range.

On one of them I enabled the plotter, and I did see a sine wave output. Since it's not a true scope, and I've never used the plotter function before I'm not sure if there's a way to trigger so the wave doesn't walk across the screen. I did capture a screenshot to look at the waveform and while most of it is fairly smooth, there are a few glitches here and there. Here's the image:

Screen Shot 2020-08-27 at 10.46.33 AM.jpg

If you zoom in you can see a few areas where there are little irregularities, but I'm not sure if that's a result of the plotting or not.

If this isn't enough info to double check just let me know, I'm happy to run any kind of tests you think would help!

Thank you!
 
Regarding the used ide: About one year ago I switched from the Arudiono ide to Visual Studio Code.
I think your results look good so far. The input frequencies are plausible and it sometimes takes a few seconds until the buffered time finally settles. This is because the initial input frequency, which is received from the hardware spdif input, is not very accurate and it is therefore constantly adjusted a little bit by a pid controller. The range of 2us of buffer fluctuations are also totally normal.
Your plot also looks good. As far as I know there is no trigger function at this serial plotter. But the glitches and noises you encountered at your previous tests would be clearly visible. This little irregularities that you noticed are caused by downsampling inside of the Plotter class: In order to reduce the amount of transfered data the plotter only sends every n-th sample to the PC. (n is the constructor argument in line 10). Currently n is set to 6. The audio data is processed in blocks with a length of 128 and 6 is not a factor 128. Therefore there are only 2 (instead of 5) samples skipped between the last sample of one audio block and the first sample of next block. This plotter class can obviously be improved. But it's just meant for debugging and served that purpose quite well until now. Summerized: I think the wave form looks fine. Have you also tested frequencies larger than 1250Hz? I tested for example 1300 and that also worked in my setup. Just keep in mind that the wave form is downsampled by a factor of 6.
If higher frequency also work, I would introduce the usb output at one Teensy again, send the wave form to one PC via usb audio and see if the audio data is still not corrupted.
 
Status
Not open for further replies.
Back
Top