Sound
Running at 192㎑ with a downclocked 96㎑ output for Sennheiser RS220 optical SP/DIF
The Intel hd audio on the Asus p9d ws board, has an Analogue 8-channel device and a Digital 2-channel alsa device, so clock the analogue at
the maximum rate, move the SPDIF over to the Analogue, thus duplication of the Green "front" jack and have the hardware downclock it to 96㎑. The digital can be left for experiments with non-audio data over sp-dif
Use hda-verb to issue instructions to Realtek ALC892
- hda-verb /dev/snd/hwC2D0 0 PARAMETERS VENDOR
- value = 0x10ec0892 # as in realtek ALC892 codec
- hda-verb /dev/snd/hwC2D0 0 PARAMETERS NODE_COUNT
- find out how many nodes come off the root 0x00ff00ff (first node index, second node count) = 0x1001, one node
- hda-verb /dev/snd/hwC2D0 1 PARAMETERS FUNCTION_TYPE
- Find out the function of node 1, 0x101 = audio
- hda-verb /dev/snd/hwC2D0 1 PARAMETERS NODE_COUNT
- find out how many nodes come off the one at index 1, 0x20025, meaning nodes from 2 to 38 inclusive
- Typical default is feeding off sub pcm 3: for ac3 output
- hda-verb /dev/snd/`basename /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*` 0x6 0x706 0x60
- However I need uncompressed audio, so set the SPDIF output to copy the green rear jack
- The 0x50 could be substituted for 0x52 or 0x54 or 0x56 to get grey black and orange jacks
- However I need uncompressed audio, so set the SPDIF output to copy the green rear jack
- hda-verb /dev/snd/`basename /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*` 0x6 0x706 0x50
- The default output 48000Hz, 24-bit, dual channel, is 0x31
- hda-verb /dev/snd/`basename /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*` 0x6 GET_STREAM_FORMAT 0
- Dual channel, 24-bit 96000Hz output
- hda-verb /dev/snd/`basename /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*` 0x6 SET_STREAM_FORMAT 0x831
- Dual channel, 32-bit 96000Hz output, the best mode supported by Sennheiser RS220
- hda-verb /dev/snd/`basename /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*` 0x6 SET_STREAM_FORMAT 0x841
- 192000Hz output, Sennheiser RS220 does not support this so get silence, but it can be put back to 96000Hz
- hda-verb /dev/snd/`basename /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*` 0x6 SET_STREAM_FORMAT 0x1831
It is also useful to mention programmability of VREFOUT, that is the electrical backfeed of between 2 and 4 volts present on the pc microphone jack, intended to power a preamplifier in a pc microphone, and said to be able to sink upto 5 milliamp of current.
I ended up with a systemd unit to automate that
- [Unit]
- Description=setup PCH hda
- [Service]
- ExecStart=/bin/sh -c '\
- hda-verb /dev/snd/$(basename /sys/*/*0000:00/0000:00:1b.0/*/*/hw*) 0x6 SET_CHANNEL_STREAMID 0x50\
- hda-verb /dev/snd/$(basename /sys/*/*/0000:00:1b.0/*/*/hw*) 0x6 SET_STREAM_FORMAT 0x841\
- '
- [Install]
- WantedBy=sound.target
Manually re-programming the verbs each time alsa programs re-open the device got tedious, so try the patch= feature
- [codec]
- 0x10ec0892 0x10438573 0x0
- [verb]
- 0x6 0x706 0x50
- 0x6 0x200 0x841
The patch= did not seem to work so modify the systemd unit to manipulate init_verbs at startup, and hda-verb can still be used to examine or reprogram it.
- [Service]
- ExecStart=/bin/sh -c '\
- exec 1>`echo /sys/devices/pci0000:00/0000:00:1b.0/sound/card*/hw*/init_verbs`;\
- echo "0x06 0x706 0x0050";\
- echo "0x06 0x200 0x0841";\
- exec 1>&-;\
- '
Most often a computer has multiple soundcards with independent clocks sources.
They drift with respect to each other, so trying to group them all in a single jack instance fails.
In some cases this can even apply to multiple devices on the same mainboard or PCB, there may be multple crystals
providing clocking.
The Resolution found is to run separate jackd instances, creating a plesiochronous bridge between the synchronous jackd islands.
We define a environment based pcm in ~/.asoundrc to allow separate jackd instances to be steered to their soundcard by environment variable. I have called it jds as short for "jack default server"
This can call hw: pcms set in the environment or others defined in asoundrc if useful to shuffle audio channels to put them in order.
- pcm.jds { @func getenv vars [ JACK_DEFAULT_SERVER ] default "defaults.pcm.card" }
- ctl.jds {
- @args.CTL {
- type string
- default {
- @func getenv vars [ JACK_DEFAULT_SERVER ] default "defaults.ctl.card"
- }
- }
- @func refer
- name {
- @func concat
- strings [ "ctl." $CTL ]
- }
- }
Edit ~/.jackdrc so that it uses the environment
- /usr/bin/jackd -dalsa -djds -r192000 -p1024 -n2
If using qjackctl that can be made to call jds as the input and output alsa device and then
different jacks will use their respective alsa hardware.
Define a sub-pcm for the p9d ws onboard...
For the best analogue sound quality use the fastest rate, however toslink attached equipment may not cope with that so downsample if needed,
Upon first attempt a p9d pcm is defined to handle analogue and digital
- pcm.p9d {
- type asym
- playback.pcm {
- type multi
- slaves {
- analogue.pcm "surround71:PCH"
- analogue.channels 8
- digital.pcm {
- type rate
- slave {
- pcm "iec958:PCH,AES0=0x04,AES1=0x82,AES2=0x00,AES3=0x0a"
- rate 96000
- # fast
- converter "samplerate_order"
- }
- digital.channels 2
- }
- bindings.0.slave digital
- bindings.0.channel 0
- bindings.1.slave digital
- bindings.1.channel 1
- bindings.2.slave analogue
- bindings.2.channel 0
- bindings.3.slave analogue
- bindings.3.channel 1
- bindings.4.slave analogue
- bindings.4.channel 2
- bindings.5.slave analogue
- bindings.5.channel 3
- bindings.6.slave analogue
- bindings.6.channel 4
- bindings.7.slave analogue
- bindings.7.channel 5
- bindings.8.slave analogue
- bindings.8.channel 6
- bindings.9.slave analogue
- bindings.9.channel 7
- master 1
- }
- capture.pcm {
- type multi
- slaves {
- analogue.pcm "hw:PCH,0"
- analogue.channels 2
- analogue2.pcm "hw:PCH,2"
- analogue2.channels 2
- }
- bindings.0.slave analogue
- bindings.0.channel 0
- bindings.1.slave analogue
- bindings.1.channel 1
- bindings.2.slave analogue2
- bindings.2.channel 0
- bindings.3.slave analogue2
- bindings.3.channel 1
- master 0
- }
- }
... and an m-audio m2496 pci card. Here shuffle the digital outputs to the beginning for ease of use.
- pcm.sp2dif {
- type asym
- # playback.pcm "hw:0"
- playback.pcm {
- slave.pcm "hw:CARD=M2496,DEV=0,SUBDEV=0"
- type route
- ttable {
- 0.8= 1
- 1.9= 1
- 2.0= 1
- 3.1= 1
- 4.2= 1
- 5.3= 1
- 6.4= 1
- 7.5= 1
- 8.6= 1
- 9.7= 1
- }
- }
- capture.pcm "hw:CARD=M2496,DEV=0,SUBDEV=0"
- }
- # http://www.alsa-project.org/main/index.php/Asoundrc
- # test with alsamixer -Dsp2dif
- ctl.sp2dif {
- @func refer
- name "ctl.hw:M2496"
- }
Lets now startup some jackd. The use of promiscuous mode is useful as then jackd does not include uid in files used to communicate with jack clients.
This may enable clients to run in other user accounts in future, for 2019 that does not work well and pulseaudio can be opened up in this way instead.
- export JACK_PROMISCUOUS_SERVER=
- env JACK_DEFAULT_SERVER=p9d `<~/.jackdrc`
- env JACK_DEFAULT_SERVER=sp2dif `<~/.jackdrc`
Suppose alsaplayer connects to the p9d jackd, since subsequenct jackd attached to a running pulseaudio misbehaved, next best things is to loopback the sound between the clocking islands:
At the time of exploring this pulseaudio does not also cope well with being linked to multiple jack instances,
so it is probably best to link it to a primary jackd2 that provides clocking, then bridge audio between jacks with jack-record
- alsa3 ()
- {
- JACK_DEFAULT_SERVER=p9d jack-record -f 0x030006 -n 2 -p alsaplayer-`pidof alsaplayer`:out_%d /dev/stdout | pv | JACK_DEFAULT_SERVER=sp2dif JACK_PLAY_CONNECT_TO=system:playback_%d jack-play /dev/stdin
- }
It is possible to swap p9d with sp2dif in the examples if the latter sounds better.
p9d errors
- ERROR: ALSA: could not complete playback of 1024 frames: error = -32
- Mon Aug 8 21:05:48 2022: ERROR: ALSA: could not complete read of 1024 frames: error = -32
- Mon Aug 8 21:05:48 2022: ERROR: JackAudioDriver::ProcessSync: read error, stopping...
Subsequently it is discovered that PCH pcms drift or something despite being on the same card.
Therefore, instead of using various alsa plugins with PCH, try to make the hardware do it.
Enjoy music with sound effects
Debian used to package jack-rack, that has been dropped though it can be still be compiled from source.
Debian also carries jconvolver for an even more realistic virtual concert experience,
however not all the impulse response files ship with it, probably for copyright reasons.
- First one was quite easy, author's page
- porihall, redirected. The files have a copyright restriction so could apply to derived works such as audio rendered via jconvolver with them.
- The "spacenet" was eventually found by good chance at york
Users may replace /var/local/union with the actual path of unpacked downloads.
- #!/bin/sh
- N=/var/local/union/http/kokkinizita.linuxaudio.org/linuxaudio/downloads/jconvolver-reverbs.tar.bz2/reverbs
- R=/var/local/union/http/legacy.spa.aalto.fi/projects/poririrs/wavs/porihall
- S=/usr/share/jconvolver/config-files/demo-reverbs/street
- C=$(readlink -f $1)
- < $C sed -s '
- s_/audio/reverbs/spacenet_/net/stat/mirror/https/webfiles.york.ac.uk/OPENAIR/IRs_g;
- s+HM2_000_WXYZ_48k.amb+hamilton-mausoleum/b-format/hm2_000_bformat_48k.wav+g;
- s+Lyd3_000_WXYZ_48k.amb+st-andrews-church/b-format/lyd3_000_bformat_48k.wav+g;
- s+MH3_000_WXYZ_48k.amb+maes-howe/b-format/mh3_000_bformat_48k.wav+g;
- s+Minster1_000_WXYZ_48k.amb+york-minster/b-format/minster1_bformat_48k.wav+g;
- s_/home/fons/acoustics/impresp/xtc_/usr/share/jconvolver/config-files/xtalk-cancel_g;
- s_/audio/reverbs/porihall_'$R'_g;
- s_/audio/reverbs_'$N'_g;
- s_street_'$S'_g;
- ' | jconvolver -s "${JACK_DEFAULT_SERVER}" /dev/stdin
Jackd for OpenAL (Such as ut2004)
Two files in the home directory allow openal applications like unreal tournament 2004
to be used with jack, and so with ALSA cards that do not really have their own mixer.
cat >> ~/.openalrc << EOF
(define devices '(alsa native))
(define alsa-device "plug:SLAVE=jack")
EOF
cat >> ~/.asoundrc << EOF
pcm.jack {
type jack
playback_ports {
0 alsa_pcm:playback_1
1 alsa_pcm:playback_2
}
capture_ports {
0 alsa_pcm:capture_1
1 alsa_pcm:capture_2
}
}
EOF
Use Jack / ALSA for festival output
(Parameter.set 'Audio_Method 'Audio_Command)
(Parameter.set 'Audio_Required_Format 'riff)
(Parameter.set 'Audio_Command "aplay -q -D plug:SLAVE=jack $FILE")
Goes in /etc/festival.scm
#!/bin/sh
mkfifo ~/.ut2004/System/speech
while true
do
cat ~/.ut2004/System/speech | while read
do
echo -ne "(SayText \""
echo -n $REPLY | sed 's/\\/\\\\/g
s/\"/\\"/g'
echo -e ".\")"
done
done | festival
This can now be used to provide a speech device
instead of the other
method involving a speechd for ut2004