* [BUG] snd-usb-audio: distorted/"robotic" playback on NUX NAI-24 (3703:2000) - audio frame split across isochronous packet boundary
@ 2026-09-01 23:23 Lucas Fuentes
0 siblings, 0 replies; only message in thread
From: Lucas Fuentes @ 2026-09-01 23:23 UTC (permalink / raw)
To: alsa-devel
Summary
-------
Playback through the NUX NAI-24 USB audio interface (idVendor 0x3703,
idProduct 0x2000) is consistently distorted ("robotic"/metallic, as if
channels were slipping out of phase with each other) on Linux, at the raw
ALSA level (bypassing PipeWire entirely). The same device, same firmware,
same cable, same PC works correctly on Windows, and the machine's onboard
audio output works correctly under the same Linux install - isolating the
problem to how snd-usb-audio drives this specific device.
A usbmon capture during a speaker-test sine tone shows the driver
submitting isochronous OUT packets of 100 and 116 bytes. At 48 kHz over a
high-speed endpoint (8000 microframes/sec), 48000 / 8000 = 6 exactly, so
every packet should be a clean multiple of the 16-byte audio frame (4
channels x 4 bytes/sample): 96, 112, 128 bytes, etc., possibly with
occasional +/-1-frame jitter from real device clock drift. Instead, every
observed packet carries exactly 4 extra bytes (100 = 96 + 4, 116 = 112 + 4)
- one lone channel sample beyond the last complete 4-channel frame. That
means a single audio frame is being split across two isochronous packets on
every transition, which would misalign channel-to-time-slot mapping
progressively as the stream plays - consistent with the distorted/"robotic"
sound reported.
Environment
-----------
- Kernel: 7.1.8-arch1-3 (Arch Linux / Omarchy)
- systemd: 261.2-1-arch
- Audio stack: PipeWire 1.6.8 + WirePlumber (bug reproduces with these
stopped, directly against hw:0,0 via speaker-test/aplay, so this is not a
PipeWire/WirePlumber issue)
- Device: NUX NAI-24 USB audio interface
- idVendor 0x3703, idProduct 0x2000, bcdDevice 1.01
- USB Audio Class 2.0, High Speed (480 Mbps)
- Playback: Interface 2, Altset 1 - 4 channels, PCM, Format Type I,
bSubslotSize 4, bBitResolution 32
- Playback data endpoint: 0x01 OUT, Isochronous, Asynchronous,
wMaxPacketSize 0x0190 (400 bytes), bInterval 1
- Feedback endpoint: 0x81 IN, Isochronous, Usage=Feedback,
wMaxPacketSize 0x0004 (4 bytes), bInterval 4 (1 ms), format 16.16 (per
/proc/asound/card0/stream0)
Steps to reproduce
-------------------
systemctl --user stop pipewire.socket pipewire-pulse.socket pipewire wireplumber pipewire-pulse
speaker-test -D hw:0,0 -c 4 -F S32_LE -r 48000 -t sine -f 440
Listening on the interface's main outs (channels 1/2): the tone is
distorted/"robotic" instead of a clean sine wave.
What has been ruled out
------------------------
- Not PipeWire/WirePlumber config: reproduces identically against raw ALSA
hw:0,0, PipeWire fully stopped.
- Not xruns/underruns: no xrun messages in journalctl --user -u pipewire
during playback; pw-metadata clock settings match the device's negotiated
rate (clock.rate 48000, device "Momentary freq" 48000 Hz).
- Not USB autosuspend: /sys/bus/usb/devices/1-3/power/control is "on"
(autosuspend disabled).
- Not the ALSA alsa-card-profile "Surround 4.0" channel-map upmix:
switching the card profile to pro-audio (raw AUX channels, no surround
mapping) makes no difference.
- Not firmware/hardware: identical device and firmware work correctly on
Windows on the same machine, and the machine's onboard audio (separate
HDA codec) plays cleanly under the same Linux install.
- Not fixed by known snd_usb_audio module quirks tried so far:
- implicit_fb=1 lowlatency=0
- quirk_flags=3703:2000:0x4 (QUIRK_FLAG_ALIGN_TRANSFER)
- quirk_flags=3703:2000:0x2000C (QUIRK_FLAG_ALIGN_TRANSFER |
QUIRK_FLAG_TX_LENGTH | QUIRK_FLAG_GENERIC_IMPLICIT_FB)
usbmon evidence
----------------
Captured via:
sudo modprobe usbmon
sudo cat /sys/kernel/debug/usb/usbmon/1u > nai24_usbmon.log
Playback endpoint (Zo:1:002:1), steady state, showing 116-byte packets
uniformly in one URB and a 100/116 mix in another (5 of 8 iso descriptors
shown per line; usbmon truncates the display list but the total length
field confirms the sum for all 8):
ffff8b8324ba6e00 599731139 S Zo:1:002:1 -115:1:5360 8 -18:0:100 -18:100:116 -18:216:116 -18:332:116 -18:448:116 912 = 60000000 80f18964 ...
ffff8b830fea9c00 599733144 S Zo:1:002:1 -115:1:5376 8 -18:0:116 -18:116:116 -18:232:116 -18:348:116 -18:464:116 928 = 70000000 00b65963 ...
- 912 / 8 = 114 bytes/packet average (mixed 100 + 116 x 7)
- 928 / 8 = 116 bytes/packet (all eight packets 116 bytes)
Neither 100 nor 116 is a multiple of 16 (the 4-channel x 32-bit frame
size). Expected clean values would be 96 or 112.
Feedback endpoint (Zi:1:002:1), polled every ~1 ms, consistently returning
the same 4-byte value:
ffff8b8262d73500 599730261 C Zi:1:002:1 0:8:5360:0 1 0:0:4 4 = 48ec0600
ffff8b8265f79900 599731259 C Zi:1:002:1 0:8:5368:0 1 0:0:4 4 = 48ec0600
Suspected root cause
----------------------
The packet-size arithmetic used by snd-usb-audio for this stream (4
channels, 32-bit subslot, 48 kHz, async + explicit feedback) appears to be
off by exactly one subslot (4 bytes) per packet boundary, splitting a
4-channel audio frame across two isochronous packets instead of keeping
frames intact. This would cause a slow, continuous channel-to-time-slot
drift, which is consistent with the "robotic"/metallic distortion reported
(as opposed to clicks/dropouts, which would point to plain xruns).
Happy to provide the full lsusb -v dump, a longer usbmon capture, or test
further kernel patches/quirk combinations against the hardware - I have the
device in hand.
Regards,
Lucas
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-08 18:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 23:23 [BUG] snd-usb-audio: distorted/"robotic" playback on NUX NAI-24 (3703:2000) - audio frame split across isochronous packet boundary Lucas Fuentes
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).