# Digital audio output at fixed sample rate only



## sugarshark (Apr 11, 2013)

Hi folks,

I'm trying to set up a new server for use as both a file server and music player. I am connecting a USB S/PDIF transport (Audiophilleo2) as the audio device, which feeds the signal to an external DAC (NAD M51). The OS is FreeBSD 9.1-RELEASE, `uname -a`:

```
FreeBSD bsdtest 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec  4 09:23:10 UTC 2012     root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  amd64
```

What I'm aiming for is for the OS to pass a "bitperfect" signal to the DAC. I don't want any kernel level mixing, resampling or anything else modifying it.

The result I'm seeing is that the audio signal going to the DAC is at a fixed sample rate regardless of the input file. This is not right; if the audio is "bit perfect" the sample rate sent to the DAC will reflect that of the file. Using this same hardware on Linux and Windows, it will correctly pass through the signal (and DAC shows 44.1, 88.2 kHz sync accordingly).

After doing a lot of reading in the man pages (particularly sound), I have set the following values in /etc/sysctl.conf:

```
dev.pcm.0.play.vchans=0
dev.pcm.0.rec.vchans=0
dev.pcm.0.bitperfect=1
```

I also configured the mixer to be at 100:100 volume:

```
Mixer vol      is currently set to 100:100
Mixer pcm      is currently set to 100:100
```

Based on the output of `sysctl -a | egrep "pcm|uaudio"`, these values seem set correctly:

```
device  snd_cmi
device  snd_csa
device  snd_emu10kx
device  snd_es137x
device  snd_hda
device  snd_ich
device  snd_uaudio
device  snd_via8233
hw.snd.vpc_reset: 0
hw.snd.vpc_0db: 45
hw.snd.vpc_autoreset: 1
hw.snd.latency_profile: 1
hw.snd.latency: 5
hw.snd.report_soft_matrix: 1
hw.snd.report_soft_formats: 1
hw.snd.compat_linux_mmap: 0
hw.snd.feeder_eq_exact_rate: 0
hw.snd.feeder_eq_presets: PEQ:16000,0.2500,62,0.2500:-9,9,1.0:44100,48000,88200,96000,176400,192000
hw.snd.feeder_rate_quality: 1
hw.snd.feeder_rate_round: 25
hw.snd.feeder_rate_max: 2016000
hw.snd.feeder_rate_min: 1
hw.snd.feeder_rate_polyphase_max: 183040
hw.snd.feeder_rate_presets: 100:8:0.85 100:36:0.92 100:164:0.97
hw.snd.vpc_mixer_bypass: 1
hw.snd.verbose: 0
hw.snd.maxautovchans: 16
hw.snd.default_unit: 0
hw.snd.version: 2009061500/amd64
hw.snd.default_auto: 1
hw.usb.uaudio.default_channels: 0
hw.usb.uaudio.default_bits: 32
hw.usb.uaudio.default_rate: 0
hw.usb.uaudio.debug: 0
dev.uaudio.0.%desc: Audiophilleo audiophilleo2 v1.16 SN01114, class 0/0, rev 2.00/1.16, addr 2
dev.uaudio.0.%driver: uaudio
dev.uaudio.0.%location: bus=1 hubaddr=5 port=1 devaddr=2 interface=0
dev.uaudio.0.%pnpinfo: vendor=0x8605 product=0x5023 devclass=0x00 devsubclass=0x00 sernum=" 01114" release=0x0116 mode=host intclass=0x01 intsubclass=0x01 intprotocol=0x00
dev.uaudio.0.%parent: uhub1
dev.pcm.0.%desc: USB audio
dev.pcm.0.%driver: pcm
dev.pcm.0.%parent: uaudio0
dev.pcm.0.play.vchans: 0
dev.pcm.0.buffersize: 0
dev.pcm.0.bitperfect: 1
```

When VLC plays audio files, the DAC is always set to a fixed sample rate of 960000.

Based on further reading (example), I tried setting some values in /boot/loader.conf:

```
#hw.usb.uaudio.default_bits=16
#hw.usb.uaudio.default_rate=48000
```

After setting the hw.usb.uaudio values, the DAC syncs at a fixed value of 48000. So it seems like the problem is with the uaudio configuration?

I have a range of audio files in different formats (44.1/16, 48/16, 88/24), so it is not feasible to use a single fixed value. Is it possible to just pass the digital audio stream straight through this device at its native sample rate?

Any help is greatly appreciated, I'm really starting to hit the wall here.


----------



## laufdi (Apr 11, 2013)

*D*o `sysctl dev.pcm` and see whether you can set play.vchans=1 and vchanmode, vchanrate, vchanformat for your device, or vchans=0?

I am trying to use the M-Audio Audiophile USB, but it seems not possible.


----------



## sugarshark (Apr 13, 2013)

laufdi,

Initially I had some problems with it not changing values at runtime, but I made those config values "stick" by adding them to /etc/sysctl.conf as per my original post.

From what I read in the documentation, the appropriate settings to use with an external DAC (where you want bitperfect mode) should be:

```
dev.pcm.%d.bitperfect=1
hw.snd.maxautovchans=0
```

I base that on the following:


> dev.pcm.%d.bitperfect
> Enable or disable bitperfect mode.  When enabled, channels will
> skip all dsp processing, such as channel matrixing, rate convert-
> ing and equalizing.  The pure sound stream will be fed directly
> ...



I have been experimenting with different values today, and have made no progress. In fact now I am not getting any sound output at all, despite seemingly having the same settings as before.

I'd love to see a FreeBSD guide to setting up bit perfect mode for S/PDIF transport. Having a FreeBSD machine as the front end to a nice audio system makes a lot of sense for a few reasons, but it is useless if you can't stream the audio properly.


----------



## mav@ (Apr 17, 2013)

Bit-perfect mode assumes that the device is able to handle all sample-rates of the content. I am not an expert in USB audio. I am working mostly on HDA, and there FreeBSD can handle any rates supported by hardware from 8KHzx8x1 up to 192KHzx24x7.1. My guess is that the USB audio driver may not recognize hardware capabilities properly, limiting the set of frequencies.


----------



## laufdi (Apr 17, 2013)

I bought a cheap "TerraTec Aureon Dual USB" which has a digital out. It works with bitperfect=1 but I cannot change samplerate or vchans. By chance it runs at 44100 (9.1-RELEASE). On my other system (9.1-STABLE) where I had stopped devd (for other reasons), it was detected at 48000 and I couldn't change that. Don't want to try that again now as I have this running.


----------



## laufdi (Aug 13, 2013)

I now have another card with a TE7022L chip. On one machine I can run this with 
	
	



```
dev.pcm.6.play.vchanmode=2
```
 (adaptive) and it really sets the sample rate according to what I play. On the other machine it won't react to sample rate changes but stays at 44100. There I have 

```
hw.usb.uaudio.default_channels: 0
hw.usb.uaudio.default_bits: 16
hw.usb.uaudio.default_rate: 44100
```
which are set in /etc/sysctl.conf. But on the first I have no hw.usb.uaudio whatsoever, why?

```
# sysctl hw.usb.uaudio
sysctl: unknown oid 'hw.usb.uaudio'
```
Both machines are 9.2-BETA2.


----------



## wblock@ (Aug 13, 2013)

sugarshark said:
			
		

> laufdi,
> 
> Initially I had some problems with it not changing values at runtime, but I made those config values "stick" by adding them to /etc/sysctl.conf as per my original post.
> 
> ...



%d should be replaced with a device number.  On my system, these go from 0 to 4.


----------



## laufdi (Aug 14, 2013)

Why don't I have hw.usb.uaudio? Where does it come from? snd_uaudio.ko is loaded, of course.


----------



## chanhonman (Sep 4, 2014)

Here it is how it works for me.

Setting bitperfect and turning off VCHAN as mentioned in snd() man page. 

```
~$cat /etc/sysctl.conf 
# $FreeBSD: release/10.0.0/etc/sysctl.conf 112200 2003-03-13 18:43:50Z mux $
#
hw.snd.default_unit=4
dev.pcm.4.bitperfect=1
dev.pcm.4.play.vchans=0
dev.pcm.4.rec.vchans=0
```
Resultant dev.pcm.4 looks like this.

```
~$sysctl dev.pcm.4
dev.pcm.4.%desc: USB audio
dev.pcm.4.%driver: pcm
dev.pcm.4.%parent: uaudio0
dev.pcm.4.play.vchans: 0
dev.pcm.4.rec.vchans: 0
dev.pcm.4.buffersize: 0
dev.pcm.4.bitperfect: 1
```
I use mplayer. Initially it did not play anything. After looking at my USB DAC, I find that my NuForce DAC only accepts se24le input. 

```
$grep uaudio /var/run/dmesg.boot 
uaudio0: <NuForce DAC 2> on usbus0
uaudio0: Play: 96000 Hz, 2 ch, 24-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 48000 Hz, 2 ch, 24-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 44100 Hz, 2 ch, 24-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 32000 Hz, 2 ch, 24-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 16000 Hz, 2 ch, 24-bit S-LE PCM format, 2x8ms buffer.
uaudio0: Play: 8000 Hz, 2 ch, 24-bit S-LE PCM format, 2x8ms buffer.
```
After appending '-format s24le' to mplayer I can get "sort of" bitperfect audio. (Sample format always converted to s24le by mplayer but sampling rate is kept unchanged)

I couldn't figure out how to force VLC to use s24le output so I stick with mplayer now.


----------



## piercedwater (May 1, 2022)

I was doing some digging on bitperfect with OSS and I came up with something to add....

setting: hw.snd.maxautovchans=4 (from 16) and dev.pcm.1.bitperfect=1 

Gives my ears sounds I have never heard before.


----------

