Hi list,
I’m having difficulties getting some USB audio 2.0 chips (TE8802L and CM6631A) to work reliably with FreeBSD. My setup worked perfectly for years using a Texas Instruments PCM2704(/5/6/7)-based asynchronous USB->SPDIF converter (16bit/32, 44.1 and 48kHz). I recently switched to a TEAC AI-501DA digital amplifier, which supports asynchronous 24bit/192kHz via USB through the TE8802L converter chip, but although the hardware was recognized immediately, at any sample rate the sound was garbled, no sysctl setting was of any help. There are no gaps in the music but everything sounds extremely metallic, pitches are all messed up as if the data sample rate doesn’t match the output rate.
As a way out I bought a cheap CM6631A (other USB->SPDIF chip) based convertor board from eBay, to feed the TEAC receiver SPDIF over coax, but the distorted sound was just the same. I tried it on different hardware, different cables etc., but the problem really seems to be with how the FreeBSD uaudio drivers interact with these chips (Mac OSX plays the music just fine, up to 192kHz).
I did some debugging on the CM6631A converter as this one gave me direct access to the SPDIF signal (the TE8802L is embedded in the TEAC, I can only judge it by listening). The information that follows all relates to the CM6631A:
My computer is a small ALIX 3D2 (AMD Geode) board running FreeBSD 10.2 as a read-only system. Sound is outputted either from audio/musicpd (OSS) or shairport-sync (ALSA->OSS), but for testing I mostly used multimedia/mplayer. I use the USB-SPDIF converters in bitperfect mode and without vchans, as there never is more than one audio source and I don’t use mixing or volume control. The hardware *should* just support any input from 16 to 24 bit and from 8000 Hz to 192kHz sample rate.
I had the impression that not using vchans helps for now in getting to the root of the problem.
Dmesg and sysctl settings are printed below.
Interestingly, when hooking up an oscilloscope to the spdif output, I noticed that the converter (CM6631A) always outputs a 48kHz signal, no matter what sample rate is rooted to the chip. Picture here: https://www.dropbox.com/s/ugb9jurqv4d7ywv/48kHz.JPG?dl=0
Thus when I play 32kHz, 44.1 kHz or 96 kHz files, FreeBSD tells me that these sample rates are correctly sent to the converter (monitored with
I played around with the usual sysctl settings, most notably
but without succes, the observed spdif output remains at 48kHz.
While playing with the sysctl’s, I did notice the variable
which returns reasonable values (a few bits/second too much or too many), but always around 48000, even when playing 44.1kHz files. But when playing a 32kHz file, dev.pcm.0.feedback_rate jumps between either 48000 and 24000 (!), and nothing in between. Playing a 96kHz file gives a feedback value around 96000 (but with garbled sound), but playing a 88.2kHz file also gives 96000 (and garbled sound). It seems that this feedback value only goes in steps of 24000.
For comparison, the TE8802L (of which I can’t monitor the spdif output) seems a bit more flexible but also gives dev.pcm.0.feedback_rate values which jump +/- 8000 around the desired value, with resulting garbled sound output.
I’m not sure what the variable is supposed to return but something doesn’t seem correct here.
The desired behaviour would be that music files are sent in their native bit format and sample rate to the converter, with the chips autodetecting the sample rate for the spdif clock (re)generation. This is what FreeBSD does very well with my old PCM2704 converter: when playing a 44.1kHz file after a 48kHz one I can see the clock frequency of the spdif signal getting adjusted on the oscilloscope screen. (by the way, the PCM2704 always returns 0 for dev.pcm.0.feedback_rate).
It should be possible to have these newer chips working at different sample rates, here is the spdif signal of the CM6631A playing 96kHz and 192kHz files just fine on OSX, as verified with the oscilloscope:
https://www.dropbox.com/s/rrk7qe0it3i83nt/96kHz.JPG?dl=0
https://www.dropbox.com/s/9ie19gq4nanjwth/192kHz.JPG?dl=0
To make a long story short, is there something wrong with how the supported sample rates are being detected on FreeBSD?
Thanks!
Tiemen
uname -a:
/etc/sysctl.conf settings:
dmesg output when attaching CM6631A chip:
trying to play a (16bit/44.1kHz) CD audio file through mplayer gives:
... but stops complaining when forcing it in 32bit mode at the same 44.1kHz (sound still garbled), through mplayer's
Finally some usbconfig output (this is the CM6631A):
I’m having difficulties getting some USB audio 2.0 chips (TE8802L and CM6631A) to work reliably with FreeBSD. My setup worked perfectly for years using a Texas Instruments PCM2704(/5/6/7)-based asynchronous USB->SPDIF converter (16bit/32, 44.1 and 48kHz). I recently switched to a TEAC AI-501DA digital amplifier, which supports asynchronous 24bit/192kHz via USB through the TE8802L converter chip, but although the hardware was recognized immediately, at any sample rate the sound was garbled, no sysctl setting was of any help. There are no gaps in the music but everything sounds extremely metallic, pitches are all messed up as if the data sample rate doesn’t match the output rate.
As a way out I bought a cheap CM6631A (other USB->SPDIF chip) based convertor board from eBay, to feed the TEAC receiver SPDIF over coax, but the distorted sound was just the same. I tried it on different hardware, different cables etc., but the problem really seems to be with how the FreeBSD uaudio drivers interact with these chips (Mac OSX plays the music just fine, up to 192kHz).
I did some debugging on the CM6631A converter as this one gave me direct access to the SPDIF signal (the TE8802L is embedded in the TEAC, I can only judge it by listening). The information that follows all relates to the CM6631A:
My computer is a small ALIX 3D2 (AMD Geode) board running FreeBSD 10.2 as a read-only system. Sound is outputted either from audio/musicpd (OSS) or shairport-sync (ALSA->OSS), but for testing I mostly used multimedia/mplayer. I use the USB-SPDIF converters in bitperfect mode and without vchans, as there never is more than one audio source and I don’t use mixing or volume control. The hardware *should* just support any input from 16 to 24 bit and from 8000 Hz to 192kHz sample rate.
I had the impression that not using vchans helps for now in getting to the root of the problem.
Dmesg and sysctl settings are printed below.
Interestingly, when hooking up an oscilloscope to the spdif output, I noticed that the converter (CM6631A) always outputs a 48kHz signal, no matter what sample rate is rooted to the chip. Picture here: https://www.dropbox.com/s/ugb9jurqv4d7ywv/48kHz.JPG?dl=0
Thus when I play 32kHz, 44.1 kHz or 96 kHz files, FreeBSD tells me that these sample rates are correctly sent to the converter (monitored with
cat /dev/sndstat
with verbosity 2), but the oscilloscope just keeps showing 48kHz. Not surprisingly the music sounds fine when a 48kHz file is played, all other rates result in garbled output.I played around with the usual sysctl settings, most notably
Code:
hw.usb.uaudio.default_rate
hw.snd.report_soft_formats
While playing with the sysctl’s, I did notice the variable
Code:
dev.pcm.0.feedback_rate
which returns reasonable values (a few bits/second too much or too many), but always around 48000, even when playing 44.1kHz files. But when playing a 32kHz file, dev.pcm.0.feedback_rate jumps between either 48000 and 24000 (!), and nothing in between. Playing a 96kHz file gives a feedback value around 96000 (but with garbled sound), but playing a 88.2kHz file also gives 96000 (and garbled sound). It seems that this feedback value only goes in steps of 24000.
For comparison, the TE8802L (of which I can’t monitor the spdif output) seems a bit more flexible but also gives dev.pcm.0.feedback_rate values which jump +/- 8000 around the desired value, with resulting garbled sound output.
I’m not sure what the variable is supposed to return but something doesn’t seem correct here.
The desired behaviour would be that music files are sent in their native bit format and sample rate to the converter, with the chips autodetecting the sample rate for the spdif clock (re)generation. This is what FreeBSD does very well with my old PCM2704 converter: when playing a 44.1kHz file after a 48kHz one I can see the clock frequency of the spdif signal getting adjusted on the oscilloscope screen. (by the way, the PCM2704 always returns 0 for dev.pcm.0.feedback_rate).
It should be possible to have these newer chips working at different sample rates, here is the spdif signal of the CM6631A playing 96kHz and 192kHz files just fine on OSX, as verified with the oscilloscope:
https://www.dropbox.com/s/rrk7qe0it3i83nt/96kHz.JPG?dl=0
https://www.dropbox.com/s/9ie19gq4nanjwth/192kHz.JPG?dl=0
To make a long story short, is there something wrong with how the supported sample rates are being detected on FreeBSD?
Thanks!
Tiemen
uname -a:
Code:
FreeBSD zolder.X.X 10.2-RELEASE FreeBSD 10.2-RELEASE #0 r286666: Wed Aug 12 19:31:38 UTC 2015 root@releng1.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC i386
/etc/sysctl.conf settings:
Code:
dev.pcm.0.bitperfect=1
hw.snd.maxautovchans=0
dev.pcm.0.play.vchans=0
hw.snd.verbose=2
dmesg output when attaching CM6631A chip:
Code:
ugen1.2: <C-Media Electronics Inc.> at usbus1
uaudio0: <C-Media Electronics Inc. USB2.0 High-Speed True HD Audio, class 239/2, rev 2.00/2.08, addr 2> on usbus1
uaudio0: Play: 384000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 352800 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 192000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 176400 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 96000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 88200 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 88000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 80000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 72000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 64000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 56000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 48000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 44100 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 40000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 32000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 24000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 22050 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 16000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 11025 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 8000 Hz, 2 ch, 32-bit S-LE PCM format, 2x8ms buffer.
uaudio0: No recording.
uaudio0: No MIDI sequencer.
pcm0: <USB audio> on uaudio0
uaudio0: HID volume keys found.
cat /dev/sndstat
output when playing a 32bit/96kHz file (resulting in garbled sound):
Code:
FreeBSD Audio Driver (32bit 2009061500/i386)
Installed devices:
pcm0: <USB audio> at ? kld snd_uaudio (1p:0v/0r:0v) default
snddev flags=0x200003e7<SIMPLEX,AUTOVCHAN,SOFTPCMVOL,BUSY,MPSAFE,REGISTERED,BITPERFECT,VPC,PRIO_WR>
[pcm0:play:dsp0.p0]: spd 96000, fmt 0x00201000, flags 0x2000010c, 0x00000001, pid 2494 (mplayer)
interrupts 1387, underruns 0, feed 1386, ready 109512 [b:12288/6144/2|bs:131072/4096/32]
channel flags=0x2000010c<RUNNING,TRIGGERED,BUSY,BITPERFECT>
{userland} -> feeder_root(0x00201000) -> {hardware}
trying to play a (16bit/44.1kHz) CD audio file through mplayer gives:
Code:
[AO OSS] Can't set audio device /dev/dsp to s16le output, trying s16le...
... but stops complaining when forcing it in 32bit mode at the same 44.1kHz (sound still garbled), through mplayer's
-format s32le
flag; cat /dev/sndstat
then gives:
Code:
FreeBSD Audio Driver (32bit 2009061500/i386)
Installed devices:
pcm0: <USB audio> at ? kld snd_uaudio (1p:0v/0r:0v) default
snddev flags=0x200003e7<SIMPLEX,AUTOVCHAN,SOFTPCMVOL,BUSY,MPSAFE,REGISTERED,BITPERFECT,VPC,PRIO_WR>
[pcm0:play:dsp0.p0]: spd 44100, fmt 0x00201000, flags 0x2000010c, 0x00000001, pid 2513 (mplayer)
interrupts 452, underruns 0, feed 451, ready 127056 [b:5648/2824/2|bs:131072/4096/32]
channel flags=0x2000010c<RUNNING,TRIGGERED,BUSY,BITPERFECT>
{userland} -> feeder_root(0x00201000) -> {hardware}
Finally some usbconfig output (this is the CM6631A):
usbconfig -d ugen1.2 dump_device_desc dump_curr_config_desc
Code:
ugen1.2: <USB2.0 High-Speed True HD Audio C-Media Electronics Inc.> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (100mA)
bLength = 0x0012
bDescriptorType = 0x0001
bcdUSB = 0x0200
bDeviceClass = 0x00ef <Miscellaneous device>
bDeviceSubClass = 0x0002
bDeviceProtocol = 0x0001
bMaxPacketSize0 = 0x0040
idVendor = 0x0d8c
idProduct = 0x0004
bcdDevice = 0x0208
iManufacturer = 0x0001 <C-Media Electronics Inc.>
iProduct = 0x0002 <USB2.0 High-Speed True HD Audio>
iSerialNumber = 0x0000 <no string>
bNumConfigurations = 0x0001
Configuration index 0
bLength = 0x0009
bDescriptorType = 0x0002
wTotalLength = 0x012a
bNumInterfaces = 0x0003
bConfigurationValue = 0x0001
iConfiguration = 0x0000 <no string>
bmAttributes = 0x00c0
bMaxPower = 0x0032
Additional Descriptor
bLength = 0x08
bDescriptorType = 0x0b
bDescriptorSubType = 0x00
RAW dump:
0x00 | 0x08, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x20, 0x00
Interface 0
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0000
bAlternateSetting = 0x0000
bNumEndpoints = 0x0001
bInterfaceClass = 0x0001 <Audio device>
bInterfaceSubClass = 0x0001
bInterfaceProtocol = 0x0020
iInterface = 0x0000 <no string>
Additional Descriptor
bLength = 0x09
bDescriptorType = 0x24
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x09, 0x24, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x01,
0x08 | 0x00
Additional Descriptor
bLength = 0x11
bDescriptorType = 0x24
bDescriptorSubType = 0x02
RAW dump:
0x00 | 0x11, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x12,
0x08 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x10 | 0x00
Additional Descriptor
bLength = 0x0c
bDescriptorType = 0x24
bDescriptorSubType = 0x03
RAW dump:
0x00 | 0x0c, 0x24, 0x03, 0x07, 0x01, 0x03, 0x00, 0x0d,
0x08 | 0x12, 0x04, 0x00, 0x00
Additional Descriptor
bLength = 0x12
bDescriptorType = 0x24
bDescriptorSubType = 0x06
RAW dump:
0x00 | 0x12, 0x24, 0x06, 0x0d, 0x01, 0x03, 0x00, 0x00,
0x08 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10 | 0x00, 0x00
Additional Descriptor
bLength = 0x08
bDescriptorType = 0x24
bDescriptorSubType = 0x0a
RAW dump:
0x00 | 0x08, 0x24, 0x0a, 0x12, 0x03, 0x07, 0x00, 0x00
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x008f <IN>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0006
bInterval = 0x0004
bRefresh = 0x0000
bSynchAddress = 0x0000
Interface 1
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0001
bAlternateSetting = 0x0000
bNumEndpoints = 0x0000
bInterfaceClass = 0x0001 <Audio device>
bInterfaceSubClass = 0x0002
bInterfaceProtocol = 0x0020
iInterface = 0x0004 <Speaker>
Interface 1 Alt 1
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0001
bAlternateSetting = 0x0001
bNumEndpoints = 0x0002
bInterfaceClass = 0x0001 <Audio device>
bInterfaceSubClass = 0x0002
bInterfaceProtocol = 0x0020
iInterface = 0x0000 <no string>
Additional Descriptor
bLength = 0x10
bDescriptorType = 0x24
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x10, 0x24, 0x01, 0x01, 0x05, 0x01, 0x01, 0x00,
0x08 | 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00
Additional Descriptor
bLength = 0x06
bDescriptorType = 0x24
bDescriptorSubType = 0x02
RAW dump:
0x00 | 0x06, 0x24, 0x02, 0x01, 0x02, 0x10
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0005 <OUT>
bmAttributes = 0x0005 <ASYNC-ISOCHRONOUS>
wMaxPacketSize = 0x00c8
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Additional Descriptor
bLength = 0x08
bDescriptorType = 0x25
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x08, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0085 <IN>
bmAttributes = 0x0011 <ISOCHRONOUS>
wMaxPacketSize = 0x0004
bInterval = 0x0004
bRefresh = 0x0000
bSynchAddress = 0x0000
Interface 1 Alt 2
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0001
bAlternateSetting = 0x0002
bNumEndpoints = 0x0002
bInterfaceClass = 0x0001 <Audio device>
bInterfaceSubClass = 0x0002
bInterfaceProtocol = 0x0020
iInterface = 0x0000 <no string>
Additional Descriptor
bLength = 0x10
bDescriptorType = 0x24
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x10, 0x24, 0x01, 0x01, 0x05, 0x01, 0x01, 0x00,
0x08 | 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00
Additional Descriptor
bLength = 0x06
bDescriptorType = 0x24
bDescriptorSubType = 0x02
RAW dump:
0x00 | 0x06, 0x24, 0x02, 0x01, 0x03, 0x18
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0005 <OUT>
bmAttributes = 0x0005 <ASYNC-ISOCHRONOUS>
wMaxPacketSize = 0x012c
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Additional Descriptor
bLength = 0x08
bDescriptorType = 0x25
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x08, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0085 <IN>
bmAttributes = 0x0011 <ISOCHRONOUS>
wMaxPacketSize = 0x0004
bInterval = 0x0004
bRefresh = 0x0000
bSynchAddress = 0x0000
Interface 1 Alt 3
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0001
bAlternateSetting = 0x0003
bNumEndpoints = 0x0002
bInterfaceClass = 0x0001 <Audio device>
bInterfaceSubClass = 0x0002
bInterfaceProtocol = 0x0020
iInterface = 0x0000 <no string>
Additional Descriptor
bLength = 0x10
bDescriptorType = 0x24
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x10, 0x24, 0x01, 0x01, 0x05, 0x01, 0x01, 0x00,
0x08 | 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00
Additional Descriptor
bLength = 0x06
bDescriptorType = 0x24
bDescriptorSubType = 0x02
RAW dump:
0x00 | 0x06, 0x24, 0x02, 0x01, 0x04, 0x20
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0005 <OUT>
bmAttributes = 0x0005 <ASYNC-ISOCHRONOUS>
wMaxPacketSize = 0x0190
bInterval = 0x0001
bRefresh = 0x0000
bSynchAddress = 0x0000
Additional Descriptor
bLength = 0x08
bDescriptorType = 0x25
bDescriptorSubType = 0x01
RAW dump:
0x00 | 0x08, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
Endpoint 1
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0085 <IN>
bmAttributes = 0x0011 <ISOCHRONOUS>
wMaxPacketSize = 0x0004
bInterval = 0x0004
bRefresh = 0x0000
bSynchAddress = 0x0000
Additional Descriptor
bLength = 0x08
bDescriptorType = 0x0b
bDescriptorSubType = 0x02
RAW dump:
0x00 | 0x08, 0x0b, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00
Interface 2
bLength = 0x0009
bDescriptorType = 0x0004
bInterfaceNumber = 0x0002
bAlternateSetting = 0x0000
bNumEndpoints = 0x0001
bInterfaceClass = 0x0003 <HID device>
bInterfaceSubClass = 0x0000
bInterfaceProtocol = 0x0000
iInterface = 0x0000 <no string>
Additional Descriptor
bLength = 0x09
bDescriptorType = 0x21
bDescriptorSubType = 0x00
RAW dump:
0x00 | 0x09, 0x21, 0x00, 0x01, 0x00, 0x01, 0x22, 0x32,
0x08 | 0x00
Endpoint 0
bLength = 0x0007
bDescriptorType = 0x0005
bEndpointAddress = 0x0084 <IN>
bmAttributes = 0x0003 <INTERRUPT>
wMaxPacketSize = 0x0010
bInterval = 0x0004
bRefresh = 0x0000
bSynchAddress = 0x0000