[alsa-devel] Options for ASYNC feedback source in USB-audio gadget (USB OTG)?
Hi,
The existing usb-audio v.2 gadget defines its EP OUT as asynchronous https://github.com/torvalds/linux/blob/master/drivers/usb/gadget/function/f_... , but does not define any feedback IN EP (which is against USB audio class 2.0 specs). Windows 10 USB audio class 2 driver requires presence of the feedback EP. By changing the EP OUT to adaptive (which in fact it is), we could fix the driver issue and windows plays through such device (RPi4) correctly now (linux/OSX already worked OK before). We will post a patch soon.
RPi can now be used as an "intelligent" USB soundcard, allowing further processing in linux on RPi, before outputting to some final sound device.
However, there are two clock domains involved - the host USB controller sending stream to the USB gadget, and the output soundcard of the gadget. While adaptive resampling is possible (jackd, PA do that), IMO the correct solution is going back to ASYNC EP OUT in the audio gadget and implementing a proper feedback EP.
But the feedback EP needs input data. The whole chain behind the virtual capture alsa device defined by the gadget driver is clocked by the playback soundcard. May I ask for your opinions on possible options for
1) gathering the feedback data from the playback chain 2) passing the gathered samplerate-diff data to the gadget module for the feedback EP to send to the USB host
A general solution would be very useful, at best without using alsa-lib defined PCM devices (e.g. Java still supports only hardware devices (hw:X), not PCM devices defined by alsa-lib).
I very much appreciate your suggestions and help.
Best regards,
Pavel.
On Wed, Aug 28, 2019 at 1:17 PM Pavel Hofman pavhofman@gmail.com wrote:
But the feedback EP needs input data. The whole chain behind the virtual capture alsa device defined by the gadget driver is clocked by the playback soundcard. May I ask for your opinions on possible options for
- gathering the feedback data from the playback chain
- passing the gathered samplerate-diff data to the gadget module for
the feedback EP to send to the USB host
IMO some common time frame must be used. E.g. kernel time in nanoseconds.
How about something like this:
1) the core PCM part of alsa driver would keep relative samplerate and present such value in proc/sysfs to userspace. the calculation something like: copied X sample frames in Y kernel nanosecs (for the last e.g. approx. 30 secs ), with nominal samplerate 48kHz. The value would be (10^9 * X frames/Y nanosecs) / 48000 Hz samplerate = e.g. 1.00001
2) the usb gadget code also creates/uses alsa driver, thus measuring/displaying to userspace the same value, e.g. 1.00002 - USB data incoming slightly faster than being consumed by the soundcard
3) the usb gadget would accept some feedback value via procfs/sysfs
4) a userspace daemon could monitor the relative samplerates of the output and of the usb gadget (both values are relative to the same kernel nanosecs clock), could calculate the required adjustment and send proper value to the gadget feedback (in some format). Default async feedback would be "no change", unless received required value from userspace.
Monitoring the average throughput (samplerate relative to kernel clock) could be enabled with a module param for alsa drivers, default off.
The reason for dividing the "kernel-time samplerate" with nominal samplerate is the chain can be resampling (48kHz -> 192kHz), but the relative "deviation" should be the same for any samplerate.
Thanks a lot for any suggestions and comments.
Pavel.
On Wed, Aug 28, 2019 at 5:17 PM Pavel Hofman pavhofman@gmail.com wrote:
IMO some common time frame must be used. E.g. kernel time in nanoseconds.
How about something like this:
- the core PCM part of alsa driver would keep relative samplerate and
present such value in proc/sysfs to userspace. the calculation something like: copied X sample frames in Y kernel nanosecs (for the last e.g. approx. 30 secs ), with nominal samplerate 48kHz. The value would be (10^9 * X frames/Y nanosecs) / 48000 Hz samplerate = e.g. 1.00001
Perhaps the relative throughput could be calculated in alsa-lib when talking to the driver? It has the same information available. Turned-on by some environment var, regular output to some /tmp file named after the corresponding hw card. Or does please alsa-lib have some existing debug output, similar to /proc/asound, apart of stderr?
I very much appreciate any comments. IMO this would be a very useful improvement, there are lots of RPi projects which would benefit from properly working USB-audio connectivity.
Thanks,
Pavel.
participants (1)
-
Pavel Hofman