tinyusb icon indicating copy to clipboard operation
tinyusb copied to clipboard

Audio class enhancements

Open HiFiPhile opened this issue 7 months ago • 7 comments

I'd like to make some major changes to UAC2 class:

  • Remove support FIFO

The UAC code is pretty complex and difficult for new comers to contribute. An obvious way to simplify is to remove support FIFO as the only use is channel muxing/demuxing, which can be (should be IMO) done in application layer. At first it was planned to allow decoding formats other than TYPE I - PCM but never gets implemented.

  • Move transfer into ISR with new driver->xfer_isr

WIP: https://github.com/HiFiPhile/tinyusb/tree/xfer_isr

ISO transfer has a high timing requirements, currently all transfers are processed in the same queue, even with a preemptive OS or run TUSB inside ISR ISO transfers are still blocked by other transfers, causing audio distortion.

(Mostly for HS) there are some USB hosts that I've tested schedule the transfer poorly, instead of traiting ISO transfer with the highest priority (1st transfer after SOF) the interval between 2 transfers varies between 50us-200us. With a i7-1195G7 notebook I even saw 20us packet interval ! This behavior further reduce the processing time.

Without traiting ISO transfer separately in ISR the only way is differing processing other transfers (what I do currently) which scales poorly.

What do you think ? @PanRe @hathach @kf6gpe @gmikitiuk

HiFiPhile avatar May 25 '25 11:05 HiFiPhile

Nice to hear from you! I don't mind - simplicity is better than too many features I guess. I implemented them with the idea that users might need them as I did. Please go ahead!

PanRe avatar May 25 '25 15:05 PanRe

In general I like the idea, due to strict timing requirements, keeping isochronous in ISR would make sense.

Fortunately the application I've been developing had almost no other transfers in play so putting tinyUSB on highest prio task in the system was enough to keep the audio running smooth.

What I came across is that with multi-channel(up to 32ch 32bit) probably host is not capable of filling the transfers properly anymore as I've seen discontinuity in audio data without any under/over run on the application side(also no isochronous errors in the peripheral). Unfortunately I do not have usb analyzer to confirm my theory. It's hard to detect such cases when host is not keeping up(unless I've missed something).

PS. removing FIFO would also mean it would be user responsibility to calculate/fill feedback endpoint?

gmikitiuk avatar May 25 '25 17:05 gmikitiuk

PS. removing FIFO would also mean it would be user responsibility to calculate/fill feedback endpoint?

The main FIFO won't be changed, support FIFO refers to the code guarded by #define CFG_TUD_AUDIO_ENABLE_ENCODING & #define CFG_TUD_AUDIO_ENABLE_DECODING

HiFiPhile avatar May 25 '25 18:05 HiFiPhile

That would be great, I also think the audio driver is a bit complicated at the moment. The example's descritpor can also be simplified by using app-level struct like uvc https://github.com/hathach/tinyusb/blob/master/examples/device/video_capture/src/usb_descriptors.c#L174 . I think both audio and video are too complicated for pre-defined macros, maybe we can have macro with simplest form. I plan to do the same with audio examples but haven't manage the time yet. And yes, isochronous can use SOF/isr to meet the timing requirement.

If the changes is too large, and you can't manage the time to get it done in one/two time. We can add an audio_device_v2.c or something with audiod2 while keeping the existing driver intact, and can update it incrementally.

hathach avatar May 29 '25 07:05 hathach

It turns remove support FIFO is pretty straight forward.

The example's descriptor can also be simplified by using app-level struct like uvc

Using struct is cleaner although mixing classes is more complicate.

Actually it's a little hard to set #define CFG_TUD_AUDIO_FUNC_1_DESC_LEN in tusb_config.h due to struct dependency loop. Otherwise in order to figure out the descriptor length in the driver, bInterfaceCount of IAD need to be passed into audiod_open()

HiFiPhile avatar May 29 '25 13:05 HiFiPhile

Hi, developer of Pico-ASHA here.

I know it's a little off-topic, but I was wondering if there would be an opportunity to provide basic UAC1 support? Many applications don't require anything more than basic (at max) 24 bit 96 KHz stereo audio, so UAC2 is a bit overkill. For example, Pico-ASHA only requires 16-bit 16KHz stereo audio.

The downsides of UAC2 is compatibility. While UAC2 works on modern Windows/Mac/Linux systems, the chances of it working elsewhere are fairly slim. For example, I tried Pico-ASHA with my Google TV (AKA Android TV) the other day, and it was not happy. It turns out Android only officially supports UAC1. Now, granted, I could be using TinyUSB incorrectly, but Pico-ASHA does work with Linux and Windows at least.

I started having a read of the UAC1 standard, but my head started hurting pretty quickly - I just don't know enough about USB and TinyUSB to implement such support myself.

shermp avatar May 30 '25 00:05 shermp

I know it's a little off-topic, but I was wondering if there would be an opportunity to provide basic UAC1 support?

There are already request to support UAC1, mainly because feedback compatibility issue between Windows and OS X. However UAC1 and UAC2 descriptors and controls are pretty different, it will be a mess to support both of them in one driver.

HiFiPhile avatar Jun 02 '25 17:06 HiFiPhile

@mastupristi Hi, PR is up in #3150

HiFiPhile avatar Jun 17 '25 14:06 HiFiPhile

Finished

HiFiPhile avatar Sep 27 '25 20:09 HiFiPhile

@shermp Hi, good news for you, my UAC1 support is in a good state: https://github.com/HiFiPhile/tinyusb/tree/uac1, it supports v1 & v2 at the same time. audio_test_multi_rate and uac2_speaker_fb examples have been updated with dynamic switching based on actual operating speed (FS=UAC1, HS=UAC2)

However with uac2_speaker_fb example I'm unable to getting UAC1 feedback work on Windows, enumeration goes well but the device ended with Error 10: the i/o device is configured incorrectly or the configuration parameters to the driver are incorrect. I had to remove feedback endpoint from the descriptor.

HiFiPhile avatar Sep 29 '25 21:09 HiFiPhile

@shermp Hi, good news for you, my UAC1 support is in a good state: https://github.com/HiFiPhile/tinyusb/tree/uac1, it supports v1 & v2 at the same time. audio_test_multi_rate and uac2_speaker_fb examples have been updated with dynamic switching based on actual operating speed (FS=UAC1, HS=UAC2)

However with uac2_speaker_fb example I'm unable to getting UAC1 feedback work on Windows, enumeration goes well but the device ended with Error 10: the i/o device is configured incorrectly or the configuration parameters to the driver are incorrect. I had to remove feedback endpoint from the descriptor.

Wow, that's great to see! I'll be sure to check it out if/when it gets merged into TinyUSB.

shermp avatar Sep 29 '25 23:09 shermp

@shermp Hi, good news for you, my UAC1 support is in a good state: https://github.com/HiFiPhile/tinyusb/tree/uac1, it supports v1 & v2 at the same time. audio_test_multi_rate and uac2_speaker_fb examples have been updated with dynamic switching based on actual operating speed (FS=UAC1, HS=UAC2)

However with uac2_speaker_fb example I'm unable to getting UAC1 feedback work on Windows, enumeration goes well but the device ended with Error 10: the i/o device is configured incorrectly or the configuration parameters to the driver are incorrect. I had to remove feedback endpoint from the descriptor.

Yooo, that's crazy 👏

abonv avatar Sep 30 '25 07:09 abonv

UAC1 PR is up ! https://github.com/hathach/tinyusb/pull/3270

HiFiPhile avatar Oct 01 '25 20:10 HiFiPhile