Enabling/Disabling USB Audio at runtime

Davidelvig

Well-known member
I have a USB audio output at the end of my audio chain (as well as I2S to the SGTL5000)

once define in the design tool, and instantiated at the top of my code file, is there any way to disable that USB Audio at runtime, so that it would cease to be seen by a connected USB host as an Audio input?

Alternatively, could it be enabled at runtime?
 
Without modifying the library source code, you could insert a queue object, which has a begin() and end() method. It may do what you wanted.
 
I've done more testing.

iPad (9th generation) with iOS 18.1.1
GarageBand

USB Camera Adaptor
My Teensy 4.1-based MIDI controller

With USB_MIDI_SERIAL defined
I can send USB MIDI and the GarageBand receives and plays it.

With USB_MIDI_AUDIO_SERIAL defined
No luck.

I've tried these things:
  • with USB_MIDI_AUDIO_SERIAL still defined, removing the AudioOutputUSB object and any references
  • in USB_AUDIO.H, commenting out the begin() statement in
    AudioOutputUSB(void) : AudioStream(2, inputQueueArray) { begin(); }
One app on the iPad (ThumbJam) still seem so t"see" the controller as a MIDI input and output, but does not respond to play i.e. when messages are being sent).

So, at the moment, I can:
  1. Use USB Audio; or
  2. Allow USB MIDI to iPads
with different firmware builds.

I expect the hook to USB Audio comes in instantiation of classes, before loop() is called.

Any ideas for how to get the best of both worlds?

(BTW, the Apple USB Camera adaptor appears key to USB MIDI to the iPad. A standard USB C to Lightning does not result in a detected MIDI controller.)
 
I think I'm seeing the light.
If anyone is groking this and can confirm or deny assumptions, I'd welcome it:

  1. Teensy's USB Audio, when enabled through a define, becomes the equivalent of a stereo USB Microphone and USB headphones
  2. When plugged in to a Mac, the Teensy's USB audio IO becomes available to any app on the Mac
  3. Applications (zoom, GarageBand) may decide to attach themselves automatically to that new device upon its plugin
Is that all correct?
 
I've done some work with trying to do the equivalent of a virtual disconnect and reconnect of the USB devices (including audio) and never been able to quite get it working cleanly across multiple operating systems. I wonder if to truly simulate it perfectly you need to pull the VBUS line low with an open-drain driver or something on the PCB.

On to your other questions, yes the teensy will appear as a USB audio device (just like an USB audio interface with audio input and output. I'm not sure I'd go as far as to say it declares it'self as a microphone and headphones specifically, but don't quote me on that.)

As a result, yes it can interfere with other applications, but that's they're programming. Some applications assume when a new audio device is suddenly connected, you intended to use it so it switches. This happens all the time for me on Aviate Audio Multiverse (Teensy based) engineering calls where I plug in the pedal and I lose my mic. Again, this isn't a Teensy issue, it's how the Zoom developers chose to behave with USB aidop connects.
 
I have a USB audio output at the end of my audio chain (as well as I2S to the SGTL5000)

once define in the design tool, and instantiated at the top of my code file, is there any way to disable that USB Audio at runtime, so that it would cease to be seen by a connected USB host as an Audio input?

Alternatively, could it be enabled at runtime?
You can simply disconnect or reconnect the patch cords to the USB output object, as is done in the following code fragments for an I2S input object:

// I2S Signal In AudioInputI2S audioLineIn; . . . // setEnabled // // Enable/disable module's LR input signals // void AudioInput::setEnabled(bool state) { if (state) { enabled = true; audioInToGainLeft.connect(audioLineIn, 0, gainLeft, 0); audioInToGainRight.connect(audioLineIn, 1, gainRight, 0); } else { enabled = false; audioInToGainLeft.disconnect(); audioInToGainRight.disconnect(); } }
 
You can simply disconnect or reconnect the patch cords to the USB output object, as is done in the following code fragments for an I2S input object:

// I2S Signal In AudioInputI2S audioLineIn; // Gain amplifiers set output gain AudioAmplifier gainLeft; AudioAmplifier gainRight; // Line In gain [0.0,1.0] float inputGain; const float inputGainDefault = 1.0; // Unity gain (0 dB) // Inter-module patch cords AudioConnection audioInToGainLeft; AudioConnection audioInToGainRight; . . . // setEnabled // // Enable/disable module's LR input signals // void AudioInput::setEnabled(bool state) { if (state) { enabled = true; audioInToGainLeft.connect(audioLineIn, 0, gainLeft, 0); audioInToGainRight.connect(audioLineIn, 1, gainRight, 0); } else { enabled = false; audioInToGainLeft.disconnect(); audioInToGainRight.disconnect(); } }
 
I've been tackling other issues since my last post, but this issue emerged again for a customer.
...with their iPad automatically assuming that my device was an audio output, simultaneously disabling the speakers of the iPad.
Swapping that back has proved difficult on the iPad user interface without unplugging my device

I know this can be solved by removing swapping the define from

USB_MIDI_AUDIO_SERIAL
to
USB_MIDI_SERIAL

...but that's a hard-coded, non-configurable change.

I'm willing to dig in to find the particular library file that enables audio in and audio out through USB and see if they can be separated. It's probably worth it for me to maintain that separate chunk of code to get the benefit of USB audio out without suffering the slings and arrows of audio in.

Can anyone point me at the files where that is defined? I'm happy to look at the standard Arduino code, but in the end, I'll have to find the same code in my PlatformIO set up.
 
Thanks I just posted in that thread to @Jigglypuff
@Jigglypuff were you able to create a USB audio interface that is recognized only as a microphone (input), and not as a speaker (output)?

And if so, what is the minimal change to do so?

I've looked at usb_audio.h and find this class declared:
class AudioInputUSB : public AudioStream
but I can't see anywhere that it is in instantiated in my project or in the base code

Also, with USB_MIDI_AUDIO_SERIAL defined at build time, I see the defines in
usb_desc.h
in the USB_MIDI_AUDIO_SERIAL section

I've tried making changes there that leave the audio out working but disable the audio in.

My challenge is that I do use audio out via USB and I don't use USB audio in for any purpose. That said, whenever I plug in the USB connection between the device and a computer or smart phone, the computer, smart phone, or an app may automatically select my device as one that receives audio. Zoom is such an app. Frustrating to provide customer support because as soon as they plug in the device, the audio goes to the device, to no good effect!

So, were you able to accomplish this? Can you tell me how?
 
Back
Top