USB Audio for Teensy 3.0

Status
Not open for further replies.
I still have hope that T4 will be compatible with prop shield and use of I2S

A new product isn't going to magically change the pinouts of those other 2 existing products.

But if you really want to use them together, all you need to do is not solder headers directly on the SPI pins. Yeah, maybe soldering some wires may not be ideal, but this is DIY electronics. These 2 shields weren't meant to be used together, but you can connect them both if you really want.

To only add to this, the DAC pin isn't going to end up in the same location either. It's going to move to the outside edge.
 
A new product isn't going to magically change the pinouts of those other 2 existing products.

But if you really want to use them together, all you need to do is not solder headers directly on the SPI pins. Yeah, maybe soldering some wires may not be ideal, but this is DIY electronics. These 2 shields weren't meant to be used together, but you can connect them both if you really want.

To only add to this, the DAC pin isn't going to end up in the same location either. It's going to move to the outside edge.
My hope was that on T4, there is a 2nd opportunity (not only pin13) to access I2S0_RXD0.

edit: on K66: I2S0_RXD0 is available on PTC6 (AKA pin13 T3.2) but also PTA15
 
Last edited:
I tested the Audio USB on an iPhone 5 and a Samsung Galaxy SIII.

I tried it on an iPhone 5 using the Apple USB-on-the-go cable and it worked! I could hear the audio output just fine. I also tested the audio input (that is, Teensy behaving as a microphone) by recording a constant 440 Hz tone, but it had a very slight noise at regular intervals when I played it back though both the Teensy and the built-in speakers.

On Samsung Galaxy SIII running Android 4.3 (using an on-the-go cable), it worked as a headphone but not as a microphone. I couldn't figure out how to make it recognize and use the Teensy as a microphone. It always used the internal microphone. I don't know if it's the same for all Android phones, or just the version of Android on this one.
 
If I may also request a new feature, it would be volume control. But I think it requires solving the problem with oversized packets on EP0. I did get the host computer to request volume changes by adding the following feature descriptor:

Code:
// Feature Descriptor (Table 4.7, p. 43,  USB Device Class Definition for Audio Data Formats 2.0)
0x0A,			// bLength
0x24,			// bDescriptorType = CS_INTERFACE
0x06,			// bDescriptorSubtype = FEATURE_UNIT
0x31,			// bUnitID
0x30,			// bSourceID
0x01,			// bControlSize
0x03,			// bmaControls(0) (MASTER, VOL)
0x03,			// bmaControls(1) Left
0x03,			// bmaControls(2) Right
0x00,			// iFeature

bSourceID=0x30 is the terminal id of the "Input Terminal Descriptor". Then the "Output Terminal Descriptor" is modified to take the feature as input, instead of the previous input terminal.

Now's the time to submit a pull request, to at least add the feature descriptor. After 1.29-beta1, -beta2, etc, and especially after a 1.29 release, any changes to the known-good descriptors will become more difficult (increasingly risky) to accept as changes to code that's been well tested.

Don't worry too much about working code to actually read & parse the control messages. This very early stage (where it's github-only and we're not yet beta testing) is the best opportunity to submit a descriptor-only or descriptors+nonworking-code pull request.
 
Last edited:
Now's the time to submit a pull request, to at least add the feature descriptor. After 1.29-beta1, -beta2, etc, and especially after a 1.29 release, any changes to the known-good descriptors will become more difficult (increasingly risky) to accept as changes to code that's been well tested.

Don't worry too much about working code to actually read & parse the control messages. This very early stage (where it's github-only and we're not yet beta testing) is the best opportunity to submit a descriptor-only or descriptors+nonworking-code pull request.

I submitted a pull request for a change but it's not bug free. While it works on my Mac (OSX 10.11), it does not work on my Windows 10 machine. On Windows 10, the Recording device will show up by the Playback device (the one with the volume feature) will not. If I remove the feature from the descriptor but leave all the code then it will show up and work.
 
I submitted a pull request for a change but it's not bug free. While it works on my Mac (OSX 10.11), it does not work on my Windows 10 machine. On Windows 10, the Recording device will show up by the Playback device (the one with the volume feature) will not. If I remove the feature from the descriptor but leave all the code then it will show up and work.

The problem was I didn't change wTotalLength to fit the new descriptor. It seems neither Linux nor Mac care. But with this change, it works on Windows 10.

Code:
--- a/teensy3/usb_desc.c
+++ b/teensy3/usb_desc.c
@@ -880,7 +880,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
        0x24,                                   // bDescriptorType, 0x24 = CS_INTERFACE
        0x01,                                   // bDescriptorSubtype, 1 = HEADER
        0x00, 0x01,                             // bcdADC (version 1.0)
-       LSB(52), MSB(52),                       // wTotalLength
+       LSB(62), MSB(62),                       // wTotalLength
        2,                                      // bInCollection
        AUDIO_INTERFACE+1,                      // baInterfaceNr(1) - Transmit to PC
        AUDIO_INTERFACE+2,                      // baInterfaceNr(2) - Receive from PC

I also added a change to my pull request to have separate left/right volume control to make it more flexible and more consistent with other devices.
 
I've merged your changes. So far I haven't tested much, but I did notice the Linux kernel is printing this warning:

Code:
Apr 24 06:10:01 preston kernel: [510099.057287] usb 2-1.2.4: Warning! Unlikely big volume range (=4095), cval->res is probably wrong.

Any thoughts?
 
I've merged your changes. So far I haven't tested much, but I did notice the Linux kernel is printing this warning:

Code:
Apr 24 06:10:01 preston kernel: [510099.057287] usb 2-1.2.4: Warning! Unlikely big volume range (=4095), cval->res is probably wrong.

Any thoughts?

I hadn't noticed that. The USB device decides the volume range it can handle and returns it in the SET_MIN/SET_MAX requests. If you make the following change, it should cut that range down.

Code:
--- a/teensy3/usb_audio.h
+++ b/teensy3/usb_audio.h
@@ -4,7 +4,7 @@
 #include "usb_desc.h"
 #ifdef AUDIO_INTERFACE
 
-#define FEATURE_MAX_VOLUME 0xFFF  // volume accepted from 0 to 0xFFF
+#define FEATURE_MAX_VOLUME 0x100  // volume accepted from 0 to 0x100
 
 #ifdef __cplusplus
 extern "C" {
 
There is another problem I've noticed on my Mac (OSX 10.11.4).

I have the Teensy using AudioInputUSB to receive from the computer. It then sends the sound to the Audio Shield. I listen with headphones.

If I play a single file for more than 2 minutes, I begin to hear a crackling noise that grows until it's very noticeable by minute 3 and overwhelms everything by minute 4. This happens with iTunes, VLC, "play", Safari, Chrome and others. In iTunes, if I press Pause, wait more than 3 seconds, and press Play again, the sound reverts to normal, but after 2 minutes, it's crackling again. On VLC, pressing Pause and Play makes no difference but if I press Stop and Play, the sound reverts to normal. I have observed that in both cases where the sound is fixed, the Mac sends a SET_INTERFACE to 0, thus resetting the sound.

I have tried this on two different Macs. One running OSX 10.11.4 and the other OSX 10.10.

On Windows 10 and Linux, this doesn't seem to happen.

Here is my test code:

Code:
#include <Audio.h>

AudioInputUSB            usbin;
AudioOutputI2S           out1;
AudioConnection          patchCord1(usbin, 0, out1, 0);
AudioConnection          patchCord2(usbin, 1, out1, 1);
AudioControlSGTL5000     sgtl5000;

// the setup routine runs once when you press reset:
void setup() {
  AudioMemory(12);
  sgtl5000.enable();
  sgtl5000.volume(0.5);
}

void loop() {
}
 
Last edited:
If I play a single file for more than 2 minutes, I begin to hear a crackling noise that grows until it's very noticeable by minute 3 and overwhelms everything by minute 4. This happens with iTunes, VLC, "play", Safari, Chrome and others. In iTunes, if I press Pause, wait more than 3 seconds, and press Play again, the sound reverts to normal, but after 2 minutes, it's crackling again. On VLC, pressing Pause and Play makes no difference but if I press Stop and Play, the sound reverts to normal. I have observed that in both cases where the sound is fixed, the Mac sends a SET_INTERFACE to 0, thus resetting the sound.

I looked at this a little closer and decided to try removing the SYNC_ENDPOINT. I made the changes below and now I don't observe the problem.

Code:
diff --git a/teensy3/usb_desc.c b/teensy3/usb_desc.c
index c813a43..f20b3a5 100644
--- a/teensy3/usb_desc.c
+++ b/teensy3/usb_desc.c
@@ -416,7 +416,8 @@ static uint8_t flightsim_report_desc[] = {
 
 #define AUDIO_INTERFACE_DESC_POS       KEYMEDIA_INTERFACE_DESC_POS+KEYMEDIA_INTERFACE_DESC_SIZE
 #ifdef  AUDIO_INTERFACE
-#define AUDIO_INTERFACE_DESC_SIZE      9+10+12+9+12+10+9 + 9+9+7+11+9+7 + 9+9+7+11+9+7+9
+//#define AUDIO_INTERFACE_DESC_SIZE    9+10+12+9+12+10+9 + 9+9+7+11+9+7 + 9+9+7+11+9+7+9
+#define AUDIO_INTERFACE_DESC_SIZE      9+10+12+9+12+10+9 + 9+9+7+11+9+7 + 9+9+7+11+9+7
 #else
 #define AUDIO_INTERFACE_DESC_SIZE      0
 #endif
@@ -1051,7 +1052,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
        LSB(AUDIO_RX_SIZE), MSB(AUDIO_RX_SIZE), // wMaxPacketSize
        1,                                      // bInterval, 1 = every frame
        0,                                      // bRefresh
-       AUDIO_SYNC_ENDPOINT | 0x80,             // bSynchAddress
+       0, //AUDIO_SYNC_ENDPOINT | 0x80,                // bSynchAddress
        // Class-Specific AS Isochronous Audio Data Endpoint Descriptor
        // USB DCD for Audio Devices 1.0, Section 4.6.1.2, Table 4-21, page 62-63
        7,                                      // bLength
@@ -1060,16 +1061,6 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
        0x00,                                   // bmAttributes
        0,                                      // bLockDelayUnits, 1 = ms
        0x00, 0x00,                             // wLockDelay
-       // Standard AS Isochronous Audio Synch Endpoint Descriptor
-       // USB DCD for Audio Devices 1.0, Section 4.6.2.1, Table 4-22, page 63-64
-       9,                                      // bLength
-       5,                                      // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR
-       AUDIO_SYNC_ENDPOINT | 0x80,             // bEndpointAddress
-       0x01,                                   // bmAttributes = isochronous
-       3, 0,                                   // wMaxPacketSize, 3 bytes
-       1,                                      // bInterval, 1 = every frame
-       5,                                      // bRefresh, 5 = 32ms
-       0,                                      // bSynchAddress
 #endif
 };
 
I'm sorry to keep bringing up problems. I know this is just alpha code.

When streaming directly from USB to the Teensy, I was hearing a small distortion so I connected USB-to-USB and observed a problem. This is my code:

Code:
#include <Audio.h>

AudioOutputI2S           out1; // if I don't have this, it won't work at all. Bug or feature?

AudioOutputUSB           usbout;
AudioInputUSB            usbin;
AudioConnection          patchCord3(usbin, 0, usbout, 0);
AudioConnection          patchCord4(usbin, 1, usbout, 1);

void setup() {
  AudioMemory(12);
}

void loop() {
}

I played a 400 Hz sine wave on the computer. I recorded it in Audacity. As you can see it appears that odd/even samples are swapped:
screenshot-distort.jpg

Looking at the code, I think the culprit is copy_to_buffers() in usb_audio.cpp. It's hard for me to follow the code well enough to catch the bug, but I just rewrote it to:
Code:
static void copy_to_buffers(const uint32_t *src, int16_t *left, int16_t *right, unsigned int len)
{
        int16_t *data = (int16_t*)src;
        while(len--) {
                *left++ = *data++;
                *right++ = *data++;
        }
}

And now the output sounds fine and looks good on Audacity:

screenshot-smooth.jpg
 
I tested the Audio USB on an iPhone 5 and a Samsung Galaxy SIII.
...
running Android 4.3 (using an on-the-go cable), it worked as a headphone but not as a microphone. I couldn't figure out how to make it recognize and use the Teensy as a microphone. It always used the internal microphone. I don't know if it's the same for all Android phones, or just the version of Android on this one.

Last year I was trying to get Android to use the Bluetooth devices on earpiece mic for dictation - tablet and phone - what I saw was that Android used the internal microphone - I couldn't get it to allow hands free remote dictation on applicable apps. I tried a few Bluetooth earpieces with different profiles. I just got Marshmallow on my phone that came with lollipop - my tests were before either of those.
 
Step one: get something to compile against cores from github.com/PaulStoffregen/cores

I want to start working with this, but I'm confounded by the arduino IDE - I can't get it to compile any examples against the github version of cores/ (I cloned from Paul's repo, the stock teensyduino stuff does fine). It uses Documents/Arduino/libraries/Audio for library includes (Audio.h), where I've put the versions of Audio/ that I cloned from Paul's github repo, but not the version of cores with all the USB Audio goodness. The compile output tells me it finds and uses Documents/Arduino/libraries/Audio, but it still isn't getting the correct headers/source files from cores which I don't really know where to put - I tried replacing it in the arduino.app directory to no avail, and no surprise, and also tried putting it in Documents/Arduino/libraries/cores. It's telling me
Code:
sketch_apr26a:4: error: 'AudioInputUSB' does not name a type
I'm trying to compile this code, which I just copied from Paul's post on 04-17-2016, 04:33 AM
Code:
#include <Audio.h>
#include <SD.h>

AudioPlaySdWav           playWav1;
AudioOutputUSB           audioOutput;
AudioOutputAnalog        dac;
AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);
AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);

// Use these with the audio adaptor board
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

void setup() {
  Serial.begin(9600);
  Serial1.begin(115200);
  Serial1.println("=======================");

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(20);

  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}

void playFile(const char *filename)
{
  Serial1.print("Playing file: ");
  Serial1.println(filename);
  playWav1.play(filename);
  // A brief delay for the library read WAV info
  delay(5);
  // Simply wait for the file to finish playing.
  while (playWav1.isPlaying()) {
  }
}


void loop() {
  playFile("SDTEST1.WAV");  // filenames are always uppercase 8.3 format
  delay(500);
  playFile("SDTEST2.WAV");
  delay(500);
  playFile("SDTEST3.WAV");
  delay(500);
  playFile("SDTEST4.WAV");
  delay(1500);
}

What's the key to this? (Using OS X btw)

Thanks,
Michael
 
Last edited:
EDIT: these steps are no longer necessary. 1.29-beta2 has all this stuff built in.


To try this very early code, before a beta test installer is published, you're going to have to edit stuff within your copy of Arduino.

On a Mac, control-click Arduino and choose "Show Package Contents" from the popup menu. On Linux and Windows it's a normal folder, but on Mac it's a special "application bundle" folder, so you have to do this step to gain access.

Once inside, navigate to Contents/Java/hardware/teensy/avr (on Linux & Windows, it's just hardware/teensy/avr). There you'll find a "cores" folder, which is the core library. You need to replace that with the code lib from github.

https://github.com/PaulStoffregen/cores

You'll also find boards.txt, which configures how Arduino uses all this stuff. You can add 3 lines to enable audio, as previously mentioned in this thread. Or just replace it with this copy, which also enables the other new combinations and the not-yet-implemented touchscreen (which wouldn't work with OSX anyway, since Apple doesn't believe in touchscreens outside of phones & tablets).

While you're poking around in there, you'll notice a libraries folder. If you put the Audio library from github inside that folder, instead of Documents/Arduino/libraries, then it will only be used with this one copy of Arduino. If you do leave the experimental code in Documents, later remember to clean it up, so you're not forever stuck with this version.
 

Attachments

  • boards.txt
    27.9 KB · Views: 628
Last edited:
Thanks Paul, the boards file was the key. I saw those 3 lines, but since Frank B said it caused some errors it didn't stick in my mind as something to try.

I'm totally unfamiliar with the arduino IDE (I'm a text editor and make file oriented person), so it took me quite a while of digging in menus and settings, but it works now. Thanks!
 
Hi guys,

with my macos 10.11.5 and my arduino 1.6.8 (and not the last one 1.6.9 which is not supported), I did all what you said here and now I have still an error from the compiler with the exemple wavefileplayerUSB :

Arduino : 1.6.8 (Mac OS X), TD: 1.28, Carte : "Teensy 3.2 / 3.1, Audio, 96 MHz optimized (overclock), Canadian French"

/Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Audio/analyze_notefreq.cpp:86:1: error: 'FASTRUN' does not name a type
FASTRUN void AudioAnalyzeNoteFrequency::process( void ) {
^
Error compiling for board Teensy 3.2 / 3.1.

Ce rapport pourrait être plus détaillé avec
l'option "Afficher les résultats détaillés de la compilation"
activée dans Fichier -> Préférences.



With other basic exemple, it is working perfectly.

Did you had the same issue ?

Thanks,
 
The easiest is to remove that word "FASTRUN".
But, really, given you use Arduino/Teensyduino, you should'nt see this error...
 
Thanks Frank B
I did so, and now I am getting a new error.... Never had something like that since I change the boards.txt and the cores.
Now the error is : Arduino : 1.6.8 (Mac OS X), TD: 1.28, Carte : "Teensy 3.2 / 3.1, Audio, 96 MHz optimized (overclock), Canadian French"

In file included from /Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Audio/analyze_peak.cpp:27:0:
/Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Audio/analyze_peak.h: In member function 'float AudioAnalyzePeak::read()':
/Applications/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Audio/analyze_peak.h:53:16: error: 'abs' was not declared in this scope
min = abs(min);
^
Error compiling for board Teensy 3.2 / 3.1.
 
I do not understand how you could get this error. I retested compiling File > Examples > Audio > WavFilePlayer with Arduino 1.6.8 and Teensyduino 1.28. The entire audio library compiles without error. Here is a screenshot:

sc.png

Perhaps you did something differently, which isn't described in your message?

Which example or program are you compiling? I want to recreate this error here on my mac, but I do not know how. As you can see, I tried the exact same version you said you are using, but there is no error.
 
Perhaps you could also try with Arduino 1.6.9 and Teensyduino 1.29-beta2. This newer beta version does indeed support Arduino 1.6.9. On the normal download page, it's linked next to "Arduino 1.6.9" in red text.

sc2.png
 
Hi Paul,

perhaps I am missing something,

my arduino app is an the application folder.
I installed arduino 1.6.9 (dragged into the application folder).
Then I runned Teensyduino .dmg and choose the arduino folder to install it. (the new beta test one)

Then the audio master files are in files folder >arduino> librairies > audio master.
I runned once arduino app.

Then I replaced in the arduino ide as you said to do, the boards.txt file and the core files.

Finally, I lunch once more arduino ide, try wavefileplayer : it works
I tried next wavefileplayerUSB : and here this error ... :
Arduino : 1.6.9 (Mac OS X), TD: 1.29-beta2, Carte : "Teensy 3.2 / 3.1, Serial, 96 MHz optimized (overclock), French"

WavFilePlayerUSB:8: error: 'AudioOutputUSB' does not name a type
AudioOutputUSB audioOutput;
^
WavFilePlayerUSB:10: error: 'audioOutput' was not declared in this scope
AudioConnection patchCord1(playWav1, 0, audioOutput, 0);
^
WavFilePlayerUSB:11: error: 'audioOutput' was not declared in this scope
AudioConnection patchCord2(playWav1, 1, audioOutput, 1);
^
'AudioOutputUSB' does not name a type



We followed the same guidlines on my windows 10 pc and it worked. Not working though on my macos device >_>

Thanks,,,
 
Last edited:
Then I replaced in the arduino ide as you said to do, the boards.txt file and the core files.

Skip this step! It's no longer necessary with 1.29-beta2.

Just install 1.29-beta2 with Arduino 1.6.9 and you have the very latest code.

However, there seems to be a bug with USB audio on macs. Windows and Linux are using the sync feedback, but Mac (probably) is not. Why is still a mystery...
 
My progress on the Mac bug is here

@ftrias - In one of your responses on this thread you mention "the Mac sends a SET_INTERFACE to 0" - how are you able to monitor the information which the Mac is sending? I've tried to find USB packet sniffing software for Mac but can't find anything (USB Probe doesn't do real-time logging). I'm considering buying a hardware USB protocol analyzer but would like to avoid that cost if at all possible.
 
Status
Not open for further replies.
Back
Top