Linux USB-Audio Gadget (RPi4 OTG)

Hello,

I am interested in whether RPi can be used to process bit-perfect audio.
(Well, in my project I am trying to use this for datatransfer over audio - hence the want for the bit-perfectness).
So far I have the following results:
RPi Zero W - for some reason, I obtain some noise - some samples are shifted by +1 or -1
RPi Zero 2W - for some reason, "stuffing" bytes are inserted -by "stuffing" I mean, that the first byte in every four bytes is "80".
When feeding 24bit audio, these stuffing bytes are really stuffing, as I get "80""true_sample", but for 32bit audio the first byte gets overwritten by the stuffing byte.

Do you have any idea what could be causing this behavior?
I have tested this both on Windows host and on Linux host, the behavior stays the same.
(If you would like to reproduce it on Windows, do not use the Groove media player - it always somehow scrambles the audio).

(the kernel version I used is 5.19.0-rc1+)

Best
There are other protocols for USB data transmission, like a network protocol, why would you choose audio? Audio as a philosophical idea is a source stream into a target sink where a few mishaps are not that crucial. If you want reliability, look into other protocols.
 
RPi4B UAC2 gadget is bitperfect up to full USB2 isochronous bandwidth for one transaction ( = 1024 bytes x 1 packet x 8000 uframes per second).

What is your USB UAC2 packet size and bInterval?

Do you have the same problem on capture and playback?

Buffer underruns are possible, but these do not change the transferred data, but skip blocks of data completely.

It's possible your Zero W having just one core is not capable of handling large amounts of data. 2W with 4 cores less likely. Anyway as I said that causes blocks of data missing, not rewritten individual bytes or even bits.

If I were to make a guess, the problem is somewhere else in your chain. Please recheck thoroughly every node of your chain, at best by analyzing integrity of the data entering/leaving each node.
Thanks for your reply. I have checked what data gets send to the audiosink, and it is scrambled. So the errors happen before the audio is processed by the RPi. So I'll try to set-up at least the windows machine for the bitperfect audio playback, and we'll see, whether it will help.

Thanks once again.
 
Everything to set up a linux USB audio DSP gadget using a RPi3A+ along with Raspberry Pi OS 64Bit Lite and CamillaDSP ...

I have long been struggling for a stable configuration of a Raspberry RPi3A+ as an USB-in SPDIF-Out CamillaDSP Audio Gadget, along with the official off-the-shelf Raspberry OS distribution (I am reluctant to use pre-shrunk solutions). The following HowTo is a compilation of collected internet knowledge. Basically, it is a work under progress. The result is actually pleasantly stable at its current state. Following this HowTo will take about 30 to 60 minutes to set the USB gadget up and results in a system running about 100 processes.Comments are welcomed! I am happy to consider all feeback to edit it into a next and thus improved HowTo.

Ingredients:
Rpi3A+, Raspberry Pi OS 64Bit Lite, Hifiberry Digi2 Pro, CamillaDSP

Actuality:
Bullseye as for 01/23, Linux optionally 6.1.3)

Warning:
This is a kind of shortlist-barebone-HowTo which I more or less compiled for my personal use. It works. But some suggestions may be reduntant, or not be really elegant, maybe stupid, and some better solutions may exist. Some suggestions will even seem problematic in terms of the integrity of the linux system.

Content:
A. Update the basic Raspberry OS lite
B. Make the basic system as lean as it gets
C. Setup the OTG USB-in and SPDIF-out mode
D. CamillaDSP
E. Further optimize the runtime dynamic behavior

A: First, update the basic OS

apt

# apt update
# apt autoclean
# apt clean
# apt autoremove
# apt full-upgrade
# reboot now

rpi-update
eventually, for a more recent kernel (by the time 6.1.3):
# rpi-update next
# reboot now


B. First make the system even a bit leaner / lighter

B.1. Configuration files mods - Linux options

/etc/dhcpcd.conf

make dhcpcd startup some seconds faster
# vi /etc/dhcpcd.conf
noarp

/etc/fstab
do not write to the sd card, but into a temp file system residing in ram instead
# vi /etc/fstab
tmpfs /tmp tmpfs noatime,nodev,nosuid,size=25M 0 0
tmpfs /var/lock tmpfs noatime,nodev,nosuid,size=5M 0 0
tmpfs /var/log tmpfs noatime,nodev,nosuid,size=5M 0 0
tmpfs /var/run tmpfs noatime,nodev,nosuid,size=5M 0 0
tmpfs /var/tmp tmpfs noatime,nodev,nosuid,size=5M 0 0

/etc/systemd/journald.conf
minimize journaling
# vi /etc/systemd/journald.conf
Storage=none
RuntimeMaxUse=50M
SystemMaxUse=50M
Audit=no

B.2. Configuration files mods – Raspberry Pi configuration options

/boot/config.txt

avoid loading modules which are not useful – standard entries
# vi /boot/config.txt
hdmi_group=1
hdmi_drive=1
dtparam=i2c_arm=off
dtparam=i2s=off
dtparam=spi=off
dtparam=audio=off
camera_auto_detect=0
display_auto_detect=0
# dtoverlay=vc4-kms-v3d (comment this one out to disable an additional sound device otherwise occuring)
arm_64bit=1
disable_overscan=1

/boot/config.txt
avoid loading modules which are not useful – additional entries
# vi /boot/config.txt
audio_pwm_mode=1
disable_audio_dither=1
disable_poe_fan=1
disable_splash=1
dtoverlay=pi3-disable-bt
enable_uart=0
gpu_mem=16
hdmi_blanking=1
hdmi_force_mode=1
hdmi_mode=1

/etc/modprobe.d/blacklist
avoid loading modules which are not useful – additional entries
# vi /etc/modprobe.d/blacklist
install bluetooth /bin/false
install bmc2835_mmal_vchiq /bin/false
install btbcm /bin/false
install btqca /bin/false
install btsdio /bin/false
install btrtl /bin/false
install snd_bmc2835 /bin/false
install snd_soc_hdmi_codec /bin/false
install vc4 /bin/false
install videobuf2_bmc2835_v4l2 /bin/false
install videobuf2_common /bin/false
install videobuf2_memops /bin/false
install videobuf2_vmalloc /bin/false
install videobuf2_v4l2 /bin/false
install videodev /bin/false

B.3. Single commands mods (Linux options)

B.3.a. Keep as few programs as possible

apt

# apt remove [xyz]; apt_purge [xyz]
xyz such as ...
bluez

B.3.b. Run as few services as possible

systemctl

# systemctl mask [xyz]
xyz such as …
apt-daily.service
apt-daily.timer
apt-daily-upgrade.timer
avahi-daemon.service
console-setup.service
cron.service
dphys-swapfile.service
getty@tty1.service
keyboard-setup.service
man-db.timer
rng-tools-debian.service
rsyslog.service
systemd-journal-flush.service
systemd-journald.service
systemd-journald.socket
systemd-journald-audit.socket
systemd-journald-dev-log.socket
triggerhappy.service
triggerhappy.socket

Check the result by ...
# reboot now
$ systemctl | grep running
$ systemctl | grep active

B.4. Multi-step mods (Linux options)

B.4.a. Swapping - remove swapping

dphys-swapfile

# dphys-swapfile swapoff
# dphys-swapfile uninstall
# apt remove dphys-swapfile

B.4.b. Wifi – remove bloated wpa-supplicant, use iwd instead
# apt install iwd
# systemctl enable iwd.service
# vi /var/lib/iwd/[YourNetworkSID].psk
[Security]
Passphrase=[YourPassphrase]
# systemctl disable wpa_supplicant
# systemctl stop wpa_supplicant
# apt remove wpa_supplicant
# apt autoremove
# reboot

B.4.c. Disable the journaling on the ext4 file system
First insert the sd-card onto a file system of any linux host
And then ...
# tune2fs -O ^has_journal /dev/mmcblk0p2


C. And now, finally, setup the OTG USB-In and the SPDIF-Out Mode (using the hifiberry SPDIF board)

/boot/config.txt

# vi /boot/config.txt
dtoverlay=dwc2,dr_mode=peripheral
dtoverlay=hifiberry-digi-pro

/etc/modprobe.d/g_audio.conf
# vi /etc/modprobe.d/g_audio.conf
options g_audio c_chmask=3 p_chmask=3 c_srate=441000 c_ssize=2 p_ssize=2 iProduct=»Rpi3A+ _USB_in_SPDIF_out»

/etc/modules-load.d/g_audio.conf
# vi /etc/modules-load.d/g_audio.conf
g_audio

/etc/modules-load.d/dwc2.conf
# vi /etc/modules-load.d/dwc2.conf
dwc2

Check the result by ...
# reboot now
$ cat /proc/asound/cards


D: CamillaDSP forever ...

D1: Install CamillaDSP on your system

apt

install bsdtar
# apt install libarchive-tools

wget
Download the CamillaDSP tar
$ wget https://github.com/Henquist/camilladsp/releases/download/[v1.2.3]/camilladsp-linux-aarch64.tar.gz

bsdtar
Extract and install CamillaDSP
$ bsdtar -xf camilladsp-linux-aarch64.tar.gz
# mv camilladsp /usr/local/bin

D2: Set up the CamillaDSP config.yml to capture from the gadget USB_in, and to playback into the SPDIF_out

/home/[YourDirectory]/[CamillaDirectory]/[CamillaConfigFile.yml]

Make the values match with the settings in both
  • /etc/modprobe.d/g_audio.conf
  • /proc/asound/cards

$ vi /home/[YourDirectory]/[CamillaDirectory]/[CamillaConfigFile.yml]

devices
capture_samplerate: 44100

capture:
channels: 2
device: hw:CARD=UAC2Gadget, Dev=0
format: S16LE
type: Alsa
playback:
channels: 2
device: hw:CARD=sndrpihifiberry
format: S24LE
type: Alsa

filters

pipeline


D3. Autostart a CamillaDSP starter script at bootup

/usr/lib/systemd/system/[AnyName].service

# vi /usr/lib/systemd/system/[AnyName].service
[Unit]
Description=CamillaDSP Boot Starter Script
After=multi-user.target
[Service]
ExecStart=/home/[YourDirectory]/[YourStartScript]
Restart=always
RestartSec=1
User=root
Group=root
CPUSchedulingPolicy=fifo
CPUSchedulingPriority=10
[Install]
WantedBy=multi-user.target

and then, enable this service at bootup …
# systemctl enable [AnyName].service


E. Further optimize the runtime dynamic behavior inside of the CamillaDSP start script

E.1. CPUs isolation - run one single (audio) program per dedicated cpu.

The following example isolates CPU 2 and 3 and lets CPU 0 handle all IRQs

/boot/cmdline.txt
add the following content into the existing file

# vi /boot/cmdline.txt
… irqaffinity=0-1 nohz=on isolcpus=2-3 nohz_full=2-3 rcu_nocbs=2-3 ...

Check the result by ...
# reboot now
# cat /sys/devices/system/cpu/isolated

And then, when running programs from a script ...

[YourStartScript]
Assign specific programs to the isolated cpu by

sudo taskset -c 2 camilladsp …
sudo taskset -c 3 anyprogram …


E.2. Dynamically stop unused services within a script

[YourStartScript]


sudo systemctl stop [xyz]
xyz such as ...
dhcpcd


E.3. Throttle the CPU within a script

apt

# apt install cpufrequtils

[YourStartScript]

sudo cpufreq-set --freq nnn
sudo cpufreq-set --governor userspace --max nnn --min nnn


Check the result by …
# cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq
# cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor


That's it.
 
Everything to set up a linux USB audio DSP gadget using a RPi3A+ along with Raspberry Pi OS 64Bit Lite and CamillaDSP ...

I have long been struggling for a stable configuration of a Raspberry RPi3A+ as an USB-in SPDIF-Out CamillaDSP Audio Gadget, along with the official off-the-shelf Raspberry OS distribution (I am reluctant to use pre-shrunk solutions). The following HowTo is a compilation of collected internet knowledge. Basically, it is a work under progress. The result is actually pleasantly stable at its current state. Following this HowTo will take about 30 to 60 minutes to set the USB gadget up and results in a system running about 100 processes.Comments are welcomed! I am happy to consider all feeback to edit it into a next and thus improved HowTo.

Ingredients:
Rpi3A+, Raspberry Pi OS 64Bit Lite, Hifiberry Digi2 Pro, CamillaDSP

Actuality:
Bullseye as for 01/23, Linux optionally 6.1.3)

Warning:
This is a kind of shortlist-barebone-HowTo which I more or less compiled for my personal use. It works. But some suggestions may be reduntant, or not be really elegant, maybe stupid, and some better solutions may exist. Some suggestions will even seem problematic in terms of the integrity of the linux system.

Content:
A. Update the basic Raspberry OS lite
B. Make the basic system as lean as it gets
C. Setup the OTG USB-in and SPDIF-out mode
D. CamillaDSP
E. Further optimize the runtime dynamic behavior

A: First, update the basic OS

apt

# apt update
# apt autoclean
# apt clean
# apt autoremove
# apt full-upgrade
# reboot now

rpi-update
eventually, for a more recent kernel (by the time 6.1.3):
# rpi-update next
# reboot now


B. First make the system even a bit leaner / lighter

B.1. Configuration files mods - Linux options

/etc/dhcpcd.conf

make dhcpcd startup some seconds faster
# vi /etc/dhcpcd.conf
noarp

/etc/fstab
do not write to the sd card, but into a temp file system residing in ram instead
# vi /etc/fstab
tmpfs /tmp tmpfs noatime,nodev,nosuid,size=25M 0 0
tmpfs /var/lock tmpfs noatime,nodev,nosuid,size=5M 0 0
tmpfs /var/log tmpfs noatime,nodev,nosuid,size=5M 0 0
tmpfs /var/run tmpfs noatime,nodev,nosuid,size=5M 0 0
tmpfs /var/tmp tmpfs noatime,nodev,nosuid,size=5M 0 0

/etc/systemd/journald.conf
minimize journaling
# vi /etc/systemd/journald.conf
Storage=none
RuntimeMaxUse=50M
SystemMaxUse=50M
Audit=no

B.2. Configuration files mods – Raspberry Pi configuration options

/boot/config.txt

avoid loading modules which are not useful – standard entries
# vi /boot/config.txt
hdmi_group=1
hdmi_drive=1
dtparam=i2c_arm=off
dtparam=i2s=off
dtparam=spi=off
dtparam=audio=off
camera_auto_detect=0
display_auto_detect=0
# dtoverlay=vc4-kms-v3d (comment this one out to disable an additional sound device otherwise occuring)
arm_64bit=1
disable_overscan=1

/boot/config.txt
avoid loading modules which are not useful – additional entries
# vi /boot/config.txt
audio_pwm_mode=1
disable_audio_dither=1
disable_poe_fan=1
disable_splash=1
dtoverlay=pi3-disable-bt
enable_uart=0
gpu_mem=16
hdmi_blanking=1
hdmi_force_mode=1
hdmi_mode=1

/etc/modprobe.d/blacklist
avoid loading modules which are not useful – additional entries
# vi /etc/modprobe.d/blacklist
install bluetooth /bin/false
install bmc2835_mmal_vchiq /bin/false
install btbcm /bin/false
install btqca /bin/false
install btsdio /bin/false
install btrtl /bin/false
install snd_bmc2835 /bin/false
install snd_soc_hdmi_codec /bin/false
install vc4 /bin/false
install videobuf2_bmc2835_v4l2 /bin/false
install videobuf2_common /bin/false
install videobuf2_memops /bin/false
install videobuf2_vmalloc /bin/false
install videobuf2_v4l2 /bin/false
install videodev /bin/false

B.3. Single commands mods (Linux options)

B.3.a. Keep as few programs as possible

apt

# apt remove [xyz]; apt_purge [xyz]
xyz such as ...
bluez

B.3.b. Run as few services as possible

systemctl

# systemctl mask [xyz]
xyz such as …
apt-daily.service
apt-daily.timer
apt-daily-upgrade.timer
avahi-daemon.service
console-setup.service
cron.service
dphys-swapfile.service
getty@tty1.service
keyboard-setup.service
man-db.timer
rng-tools-debian.service
rsyslog.service
systemd-journal-flush.service
systemd-journald.service
systemd-journald.socket
systemd-journald-audit.socket
systemd-journald-dev-log.socket
triggerhappy.service
triggerhappy.socket

Check the result by ...
# reboot now
$ systemctl | grep running
$ systemctl | grep active

B.4. Multi-step mods (Linux options)

B.4.a. Swapping - remove swapping

dphys-swapfile

# dphys-swapfile swapoff
# dphys-swapfile uninstall
# apt remove dphys-swapfile

B.4.b. Wifi – remove bloated wpa-supplicant, use iwd instead
# apt install iwd
# systemctl enable iwd.service
# vi /var/lib/iwd/[YourNetworkSID].psk
[Security]
Passphrase=[YourPassphrase]
# systemctl disable wpa_supplicant
# systemctl stop wpa_supplicant
# apt remove wpa_supplicant
# apt autoremove
# reboot

B.4.c. Disable the journaling on the ext4 file system
First insert the sd-card onto a file system of any linux host
And then ...
# tune2fs -O ^has_journal /dev/mmcblk0p2


C. And now, finally, setup the OTG USB-In and the SPDIF-Out Mode (using the hifiberry SPDIF board)

/boot/config.txt

# vi /boot/config.txt
dtoverlay=dwc2,dr_mode=peripheral
dtoverlay=hifiberry-digi-pro

/etc/modprobe.d/g_audio.conf
# vi /etc/modprobe.d/g_audio.conf
options g_audio c_chmask=3 p_chmask=3 c_srate=441000 c_ssize=2 p_ssize=2 iProduct=»Rpi3A+ _USB_in_SPDIF_out»

/etc/modules-load.d/g_audio.conf
# vi /etc/modules-load.d/g_audio.conf
g_audio

/etc/modules-load.d/dwc2.conf
# vi /etc/modules-load.d/dwc2.conf
dwc2

Check the result by ...
# reboot now
$ cat /proc/asound/cards


D: CamillaDSP forever ...

D1: Install CamillaDSP on your system

apt

install bsdtar
# apt install libarchive-tools

wget
Download the CamillaDSP tar
$ wget https://github.com/Henquist/camilladsp/releases/download/[v1.2.3]/camilladsp-linux-aarch64.tar.gz

bsdtar
Extract and install CamillaDSP
$ bsdtar -xf camilladsp-linux-aarch64.tar.gz
# mv camilladsp /usr/local/bin

D2: Set up the CamillaDSP config.yml to capture from the gadget USB_in, and to playback into the SPDIF_out

/home/[YourDirectory]/[CamillaDirectory]/[CamillaConfigFile.yml]

Make the values match with the settings in both
  • /etc/modprobe.d/g_audio.conf
  • /proc/asound/cards

$ vi /home/[YourDirectory]/[CamillaDirectory]/[CamillaConfigFile.yml]

devices
capture_samplerate: 44100

capture:
channels: 2
device: hw:CARD=UAC2Gadget, Dev=0
format: S16LE
type: Alsa
playback:
channels: 2
device: hw:CARD=sndrpihifiberry
format: S24LE
type: Alsa

filters

pipeline


D3. Autostart a CamillaDSP starter script at bootup

/usr/lib/systemd/system/[AnyName].service

# vi /usr/lib/systemd/system/[AnyName].service
[Unit]
Description=CamillaDSP Boot Starter Script
After=multi-user.target
[Service]
ExecStart=/home/[YourDirectory]/[YourStartScript]
Restart=always
RestartSec=1
User=root
Group=root
CPUSchedulingPolicy=fifo
CPUSchedulingPriority=10
[Install]
WantedBy=multi-user.target

and then, enable this service at bootup …
# systemctl enable [AnyName].service


E. Further optimize the runtime dynamic behavior inside of the CamillaDSP start script

E.1. CPUs isolation - run one single (audio) program per dedicated cpu.

The following example isolates CPU 2 and 3 and lets CPU 0 handle all IRQs

/boot/cmdline.txt
add the following content into the existing file

# vi /boot/cmdline.txt
… irqaffinity=0-1 nohz=on isolcpus=2-3 nohz_full=2-3 rcu_nocbs=2-3 ...

Check the result by ...
# reboot now
# cat /sys/devices/system/cpu/isolated

And then, when running programs from a script ...

[YourStartScript]
Assign specific programs to the isolated cpu by

sudo taskset -c 2 camilladsp …
sudo taskset -c 3 anyprogram …


E.2. Dynamically stop unused services within a script

[YourStartScript]


sudo systemctl stop [xyz]
xyz such as ...
dhcpcd


E.3. Throttle the CPU within a script

apt

# apt install cpufrequtils

[YourStartScript]

sudo cpufreq-set --freq nnn
sudo cpufreq-set --governor userspace --max nnn --min nnn


Check the result by …
# cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_cur_freq
# cat /sys/devices/system/cpu/cpufreq/policy0/scaling_governor


That's it.
nice guide 🙂

i read that it may be beneficial to put for example USB IRQ`s on its own core, do you also know how to do this? (since i wanna try this myself)

you probably should take a look at DietPI, its basicly a more lightweight raspberry pi os by default
and im thinking right now of switching from moode audio to dietpi to make a own music streamer setup somewhat similar to your setup

i also think using the raspberry pi as usb soundcard is the way to go, specially if you wanna stream all your music from your PC to your PI streamer, it seems superior to all other alternatives (over ethernet = too much latency, over spdif/coax = you need addtional (good) hardware)

is it possible to run the raspberry pi in usb 1.1 mode? i think its max. 24bit 96khz (so we can use cheap full speed usb isolators between pc and raspberry pi)
 
Please what is the reasoning for isolating the CPUs? To avoid xruns and allow small latency CDSP is designed with three threads - capturing from a device, processing/DSP, playing into a device. All decent players are designed like that (mpd, mplayer, etc.). Constraining all three threads of the player to the same core severely limits this design, increasing the chances of timing issues.

On the other hand switching CPU frequency may be avoided to minimize xruns probability - I do not have any figures for RPi but on pandaboard the switching takes several ms of latency which is not negligible https://stackoverflow.com/questions...ime-different-from-cpuinfo-transition-latency .

The Hifiberry DAC (snd_rpi_hifiberry_dac) uses clock generated by RPi (https://github.com/raspberrypi/linu...aee/sound/soc/bcm/rpi-simple-soundcard.c#L316 -> https://github.com/raspberrypi/linu...ound/soc/bcm/rpi-simple-soundcard.c#L345-L350 -> https://elixir.bootlin.com/linux/v4.9/source/include/sound/soc-dai.h#L86 ). That means a VERY jiitery clock is feeding the DAC (measurement e.g. https://www.himmelbauer-it.at/comparing-the-i2s-capabilities-of-the-rpi-and-odroid-c1/, reason e.g. https://www.diyaudio.com/community/threads/avoiding-rpi-master-i2s-fractional-jitter.376583/ ) This ugly bitclock is feeding the PLL in the DAC which generates the master clock for the conversion - the only clock in the whole chain which actually matters.
 
Do you have any reasoning for that? Thanks.
just subjective ones but no objective reasons to be honest

there are many "audiophile" distros that also take advantage of this (underclocking/isolating cpus to specific software etc), AudioLinux, Snake Oil OS, GentooPlayer for example and many people claim they hear a difference

i was wondering myself because "bitperfect" should be bitperfect (and i guess some devs also proof this fact) but maybe its more about electrical noise going from the PC?

i specially heared myself the most difference with underclocking the RPI4 but also isolating cpu (and giving MPD its own core) makes some difference (but not as much as underclocking)

in the case of USB IRQ it could be beneficial in that sense that specially if a dac runs in "adaptive asynchrounos" mode it could be beneficial since the timing going out of the PC would be better/more accurate with having USB IRQ`s on its own core
not sure how it will be if the dac is in "pure asynchrounos" mode, atleast in theory it shouldnt make a difference
and my guess is many manufactors claim asynchrounos mode but it actually is adaptive asynchrounos mode which is from what i read still a little dependent on the source


atleast for me after trying stuff out and hearing a difference on things were it doesnt makes (objectively) sense (like usb cables, different usb hubs, pc underclocking) the best answer i have right now is "noise" (this does make alteast objectively a little sense, even if its in "inaudible measuring regions"
 
Last edited:
Please what is the reasoning for isolating the CPUs? To avoid xruns and allow small latency CDSP is designed with three threads - capturing from a device, processing/DSP, playing into a device. All decent players are designed like that (mpd, mplayer, etc.). Constraining all three threads of the player to the same core severely limits this design, increasing the chances of timing issues.
Your objection about the three threads, optionally shared amongst several cores (if I understand well), is new to me and is also surprizing me: Using $top I never observed the camilladsp process distributed amongst different cores, and also $ps -ely only shows one single camilladsp process. Saying this, I have to point out that my camilladsp configuration's cpu load is max. 80% on one single core @ 600MHz, thus not needing more or load-induced distributed processing. Therefore, running camilladsp on a single core seemed a reasonable option to me. But maybe I am also mis-/overinterpreting the $top / $ps readouts.

The (maybe naive) idea behind core isolation boiled down to
1st to keep as much data traffic as possible inside the 1st level cache
2nd avoiding other programs to interfere with the audio data processing on the same core.

On the other hand switching CPU frequency may be avoided to minimize xruns probability - I do not have any figures for RPi but on pandaboard the switching takes several ms of latency which is not negligible https://stackoverflow.com/questions...ime-different-from-cpuinfo-transition-latency .
On my described setup:
# cpufreq-set --governor=ondemand
# cpufreq-set --min=600 --max=1400
# cat /sys/devices/system/cpu/cpufreq/policy0/cpuinfo_transition_latency
4294967295
Quite an enigmatic value ....

The Hifiberry DAC (snd_rpi_hifiberry_dac) uses clock generated by RPi (https://github.com/raspberrypi/linu...aee/sound/soc/bcm/rpi-simple-soundcard.c#L316 -> https://github.com/raspberrypi/linu...ound/soc/bcm/rpi-simple-soundcard.c#L345-L350 -> https://elixir.bootlin.com/linux/v4.9/source/include/sound/soc-dai.h#L86 ). That means a VERY jiitery clock is feeding the DAC (measurement e.g. https://www.himmelbauer-it.at/comparing-the-i2s-capabilities-of-the-rpi-and-odroid-c1/, reason e.g. https://www.diyaudio.com/community/threads/avoiding-rpi-master-i2s-fractional-jitter.376583/ ) This ugly bitclock is feeding the PLL in the DAC which generates the master clock for the conversion - the only clock in the whole chain which actually matters.
Yes. I2s on the RPi seems far from perfect ... Instead, aboard the SPDIF-out-only Hifiberry Digi2 Pro there are two (as advertised dedicated) oscillators to clock the SPDIF signal. Hifiberry inc. tells us so, and hopefully it is true, and also hopefully these oscillators are low-enough-and-better-than-raspi jitter types. Hifiberry does not publish any schematics or further details about these oscillators.
The related links you posted relate to some hifiberry dac and amp products and may be relevant when using these.
 
If you want to see how process and threads are distributed across CPU cores then use the ps commands below. They can also be placed inside a watch command i.e., watch -n.5 "command" so you can observe every half sec how threads might be redistributed.

Below is what MPD -> CamillaDSP -> ALSA look like when playing a song file

Code:
pi@moode:~ $
pi@moode:~ $ ps H -q `pidof -s mpd` -o 'pid,tid,cls,rtprio,comm,pcpu,psr'
    PID     TID CLS RTPRIO COMMAND         %CPU PSR
  18144   18144  TS      - mpd              0.2   0
  18144   18145  TS      - io               0.0   3
  18144   18146  FF     40 rtio             0.1   0
  18144   18227  TS      - player           0.0   1
  18144   18228  TS      - decoder:flac     0.5   2
  18144   18229  FF     40 output:ALSA Def  0.0   2
  18144   18231  TS      - pcm-io           0.2   0
pi@moode:~ $
pi@moode:~ $ ps H -q `pidof -s camilladsp` -o 'pid,tid,cls,rtprio,comm,pcpu,psr'
    PID     TID CLS RTPRIO COMMAND         %CPU PSR
  18230   18230  TS      - camilladsp       0.0   0
  18230   18232  TS      - flexi_logger-as  0.0   2
  18230   18233  TS      - flexi_logger-fl  0.0   3
  18230   18236  TS      - camilladsp       0.0   0
  18230   18237  TS      - camilladsp       0.5   3
  18230   18238  TS      - AlsaPlayback     2.0   0
  18230   18239  TS      - FileCapture      1.4   1
pi@moode:~ $

The options for ps are in the man page
https://man7.org/linux/man-pages/man1/ps.1.html
 
If you want to see how process and threads are distributed across CPU cores then use the ps commands below ..
pi@moode:~ $ ps H -q pidof -s camilladsp -o 'pid,tid,cls,rtprio,comm,pcpu,psr'
Thank you for this one. Let't play with it a bit, then:

I ran two piped CamillaDSP processes for an experimental purpose (on a RPi 3A+):

Camilladsp PID 736: Audio Gadget Audio in (44.1/16_LE) -> Conversion 44.1/16 to 96/64_Float -> stdout (96/64_Float)
Camilladsp PID 735: stdin (64/96_Float) -> Convolving -> Conversion 96/64_Float to 96/24_LE -> Alsa_Out (96/24_LE)

PID TID CLS RTPRIO COMMAND %CPU PSR
736 736 FF 99 camilladsp 0.1 2
736 738 FF 99 flexi_logger-as 0.0 2
736 739 FF 99 flexi_logger-fl 0.0 2
736 743 FF 99 camilladsp 0.0 2
736 744 FF 99 camilladsp 0.4 2
736 745 FF 99 FilePlayback 5.3 2
736 746 FF 99 AlsaCapture 10.7 2


PID TID CLS RTPRIO COMMAND %CPU PSR
735 735 FF 99 camilladsp 0.0 3
735 737 FF 99 flexi_logger-as 0.0 3
735 740 FF 99 flexi_logger-fl 0.0 3
735 747 FF 99 camilladsp 0.0 3
735 748 FF 99 camilladsp 75.0 3
735 749 FF 99 AlsaPlayback 6.0 3
735 750 FF 99 FileCapture 5.3 3


I would not have expected that capturing data from the audio gadget frontend at 44.1/16_LE is this ressource heavy at 10.7% CPU. Compared to stdin/-out at both 96/64_Float is almost half as CPU expensive at a tenfold data flow. By the way, the CamillaDSP SR-/Format conversion comes almost for free at 0.5%.

So, gadget-to-stdin/-out has an exorbitant cost ratio of 18:1 per transferred data unit. AlsaPlayback-to stdin/out ratio is a lot cheaper at about 3:1, and Gadget-to-AlsaPlayback is still much more expensive at 6:1.

Does anyone know why it is this expensive to capture data from the gadget frontend?
 
Last edited:
How to set up a lean linux audio DSP UAC2 Rpi3A+ gadget - Take II

Everything to set up a linux USB audio DSP gadget using a RPi3A+ along with Raspberry Pi OS 64Bit Lite and CamillaDSP ...

Meanwhile, some work has been done ... and I listen music from an improved gadget. Thank you phofman and TimCurtis for your input. In order not to spam this thread, the upgraded HowTo describing the setup of the actual version might be downloaded as a file. The gadget itself isn't donloadable, unfortunately.
 

Attachments

Last edited:
  • Like
Reactions: Naturlyd
Bad news: After today's (2023/03/09) system update/upgrade, my RaspiOS (Kernel 5.15.84-v8+) did not work any longer as an audio gadget: There was a dw2 kernel module loaded, but no more gadget present in the /proc/asound/cards file. No idea what might be behind this fail.

Workaround:
I then did set all apt packages lists to next debian version bookworm (instead of bullseye). After having updated the packages to bookwork, then I updated the kernel also. This solved the acual problem at the price of potentially jeopardized further updates.

# vi /etc/apt/sources.list -->> (replace all "bullseye" to "bookworm")
# vi /etc/apt/sources.list.d/raspi.list -->> (replace all "bullseye" to "bookworm")
# apt update
# apt full-upgrade
# rpi-update master
# reboot now

After this, kernel version has changed to 6.1.14-8+. And the gadget is functional again.

What the heck ?????
 
Last edited:
Too bad then for the Rpi community wanting to set up a decent gadet:

First, Rpis still are not available.
Second, if you are lucky to own a Pi, and then taking the regular Rpi-OS off the shelf, it's most recent custom Kernel is still not fit for gadgetting ...

What a pity. Or, what a shame.
 
Well, the RaspiOS is tied to debian stable (11 bullseye currently). It is not a rolling-update distro, and keeps major kernel version for its lifetime (5.10 in upstream debian, the RPi's stable kernel is quite a bit newer). After debian releases the new stable this year (12 bookworm), RPi people will do so as well (very likely again with a newer kernel than the upstream debian). The kernel has received LOTS of new features/drivers/improvements since 5.15, the UAC2 gadget function being just a tiny part.

Also the USB gadget subsystem includes many other functions apart of UAC2, some of which already work OK in 5.15.
 
Thank you for this hint!

Also the USB gadget subsystem includes many other functions apart of UAC2, some of which already work OK in 5.15.

Where ist the best place to get the most concise and most up-to-date informations about all these changes? Is it
https://www.kernel.org/doc/html/v6.2/driver-api/usb/gadget.html ?

The 3rd line of this link is somewhat irritating however, and maybe misleading also. Because the link refers to 6.2, but the text reads ...
... "Date: 20. August 2004" ... ???