CamillaDSP - Cross-platform IIR and FIR engine for crossovers, room correction etc.

I use CamillaDSP on a Rpi controlled from inside a bash script. I do so because of some further dynamic system/setup control and tweaking from inside this bash script. This works very well.

Some time ago I posted two solution snippets of my bash script which then was operative: One to auto-switch the capture_samplerate in order to match the samplerate coming from the audio stream. Meanwhile, there are other and nice solutions to perform this task. Another script snippet was to start the ressources demanding initialization of the system at a high CPU clock speed, and then reduce this speed for a steady-state playback once things have settled.

Recently I noticed that in a specific setup the AsyncSinc resampling from 44.1kHz to 96kHz was a bit more CPU intensive than resampling from 48kHz to 96kHz: 44->96 required a min CPU clock frequency of 800MHz to run stable, whereas 48->96 ran fine with lower 600MHz. This called for re-scripting everything together in order to auto-switch adaptively 800MHz or 600MHz steady-state CPU clock frequencies thus matching the requirements of 44kHz or 48kHz capture sample rates. Just for fun and for the joy of optimizing things.

First some relevant script parameters of the settings section
Bash:
# CPU throttling
cpu_freq_min_44=800000  # value in kHz
cpu_freq_min_48=600000  # value in kHz
cpu_freq_hi=0  # will be overwritten by the max. possible cpu freq assessed later on from the /sys/devices/... path
cpu_freq_hi_hold=5  # hold time of the hi cpu freq before switching to the lower steady-state clock freq
cpu_freq_sstate=0  # steady-state value in kHz to be applied by the cpu governor. Will be updated dynamically
cfs_pid=0  # PID of the deamonized cpu frequency set function

The first function 1. checks for the incoming sampling rate, 2. then eventually adapts the CDSP config file to it, 3. then updates the steady-state CPU clock frequency value to it
Bash:
function sw_rate_in_match() {
  echo "script: info - waiting for audio stream ..."
  while true; do
    # Check for the incoming sampling rate and eventually adapt the CDSP config file to it
    rate=$(arecord -D hw:$snd_cptr --dump-hw-params 2> >(grep -i "rate:") | cut -d ":" -f2 | tr -d ' ')
    if [ -n "$rate" ]; then
      echo "script: info - capture samplerate: $rate Hz"
      grep -R "capture_samplerate: $rate" $cdsp_cnfg &> /dev/null
      if [ $? -eq 1  ] ; then
        sed -i "/capture_samplerate/c\  capture_samplerate: \\$rate" $cdsp_cnfg
      fi
      break
    else
      sleep 0.1
    fi
  done
  # Update the CPU steady-state clock frequency values
  if [ $rate -eq 44100 ] ; then
    cpu_freq_sstate=$cpu_freq_min_44
  elif [ $rate -eq 48000 ] ; then
    cpu_freq_sstate=$cpu_freq_min_48
  else
    echo "script: ERROR in function sw_rate_in_match"
    exit
  fi
}

The second function does switch the CPU clock governors. From the main program, it will be called either in 'init', 'hi' or 'lo' mode.
Bash:
# Function CPU clock frequency setting #
function cpu_freq_set() {
  # Assess the actual cpu frequency
  if [ $1 = "init" ]; then
    # Assess max. cpu frequency
    cpu_freq_hi=$(sudo cat /sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_max_freq)
    # Set frequency "hi" to "lo" pending change flag to 0
    # Set CPU clock governors frequency imits and set CPU to performance
    sudo cpupower frequency-set --min $cpu_freq_sstate --max $cpu_freq_hi &> /dev/null
    sudo cpupower frequency-set --governor performance &> /dev/null
    f=$cpu_freq_hi
  else
    f=$(sudo cat /sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq)
    if [ $1 = "hi" ]; then
      # CPU is to be set to performance
      if [ f != $cpu_freq_hi ]; then
        sudo cpupower frequency-set --governor performance &> /dev/null
        f=$cpu_freq_hi
      fi
    elif [ $1 = "lo" ]; then
      # CPU is to be set to powersave - for steady-state audio processing
      if [ $f != $cpu_freq_sstate ]; then
        sleep $cpu_freq_hi_hold  # Delay for init of the audio pipe with max. ressources, then scale back
        sudo cpupower frequency-set --governor powersave &> /dev/null
        f=$cpu_freq_sstate
      fi
    fi
  fi
  # Info
  ((f /= 1000))
  echo "script: info - cpu frequency set to $f MHz"
}

Finally the main program with the loop. On sample frequencies mismatches, CamillaDSP crashes and thus enables a new loop.
Bash:
### Main program ###
# cpu governor limits and set max. CPU ressources
cpu_freq_set "init"
while true; do
  echo ""
  echo "script: info - main loop starting ..."
  # wait for the audio stream. Then assess the audio stream configuration, check for match with cdsp configuration and update the CPU clock freq. min value.
  sw_rate_in_match
  # At this point, eventually the CamillaDSP config and the value for the min. CPU clock frequency has been updated
  # The cpu governor is still set for max. cpu clock in order to have best possible ressources to init the playback.
  # With the next command run in the background, the cpu governor will be set to lo for steady-state audio after a delay of $cpu_freq_hi_hold seconds
  cpu_freq_set "lo" &
  # As the former command was deamonized by '&', the program continues without any delay.
  # Maybe the daemon must be killed later on, so we must assess his PID to do so
  cfs_pid=$!
  # At this point, the cpu governor is still set for max. cpu clock, but will fold back after $cpu_freq_hi_hold seconds to minimum speed while CamillaDSP running.
  # start audio processing at max. cpu clock ...
  camilladsp ... ... ... ... ... ... ...
  # Beyond this point, either CamillaDSP has been stopped by a sample rate change, or it has erroneously crashed.
  # CPU will be set to max. ressources again.
  # But first we must be sure that the foldback phantom is not still running in case of an abortive CamillaDSP start. Therefore we kill the phantom's PID.
  sudo kill -9 $cfs_pid &> /dev/null
  # Now we are sure that we can go full throttle without being suddenly braked down again by the erroneusly still active CPU control phantom.
  cpu_freq_set "hi"
done

This principle works very nicely. Nota bene: For the loop to work, [stop_on_rate_change: true] must be set in the CDSP config. These are scripts excerpts only, showing the bare meccano. My fully functional and complete bash.sh actually counts 280 lines.
 
Last edited:
Here's the config that causes the problem. It's doing a straightforward headphone crossfeed.
Could you run perf annotate on this so we see what instruction that gets slow? I have revived an old Intel machine I had forgotten about, an old Haswell i5 with Debian Stretch. When running on this one I can reproduce the first issue, but I don't see this new one with the crossfeed config. The OS is too old to run the binaries from github so I had to recompile, might be why things are different.

I'm would like to make a short example that shows the compiler bug, that can be compiled with codegen_units=1. That would make it possible to use compiler explorer (https://godbolt.org/) to see the optimization steps, and maybe with some luck figure out at what point things go wrong.
 
Last edited:
I have been playing with compiling the minimal example with more compiler versions. With codegen-units=1 I get something that looks good with rustc 1.70 and later. With 1.69 and earlier the codegen-units trick doesn't work and I get the problem with potential garbage in xmm4. Going to even older, 1.58 and earlier gives a different result that looks about as bad. I guess that the differences are just noise, and that the problem is caused by the same bug for all of them.
@spfenwick what rustc version(s) are you using?
 
Could you run perf annotate on this so we see what instruction that gets slow?
Here's perf report on the github version of 2.0.0a4 (running slowly)
1696974521763.png

And the perf annotate results for the same test:
1696974498672.png

For comparison here's perf annotate on my version of 2.0.0a4 with the sse2 registers zeroed out:
1696974608217.png

@spfenwick what rustc version(s) are you using?
Code:
$ rustc -V
rustc 1.72.0 (5680fa18f 2023-08-23)
 
Last edited:
  • Like
Reactions: 1 user
Still thinking about what to do about that compiler bug. It doesn't seem to be possible to make a complete fix without raising the cpu requirements to include sse 4.2.

Who is using CamillaDSP on linux with an older cpu that does not support sse 4.2?
Examples of such cpus, with approximate years:
  • Intel Atom N2700 & N2800, z2xxx and earlier (until 2013)
  • Intel Core 2 Duo and earlier (until 2008)
  • AMD Athlon II, Phenom II and earlier (until 2010)
 
Hello !

I'm setting up a raspberry pico 2W with camilladsp runnning in and with a allo miniboss dac as output. As input I use an USB gadget to act like an USB sound card.

Now I want to be able to use bluetooth as other input. I set up bluez-alsa to output to my dac, and it works fine.

Now I want camilladsp to retrieve both stream: usb & bluetooth. And it's seems not possible to use multiple capture device in the configuration of camilladsp.
What can I do ?


Regards,
Jeff
 
Still thinking about what to do about that compiler bug. It doesn't seem to be possible to make a complete fix without raising the cpu requirements to include sse 4.2.

Who is using CamillaDSP on linux with an older cpu that does not support sse 4.2?
Examples of such cpus, with approximate years:
  • Intel Atom N2700 & N2800, z2xxx and earlier (until 2013)
  • Intel Core 2 Duo and earlier (until 2008)
  • AMD Athlon II, Phenom II and earlier (until 2010)
Would it help and make sense to have two builds - one for older and another for newer Intel CPUs?
 
Would it help and make sense to have two builds - one for older and another for newer Intel CPUs?
Yes, there could be one build for sse4.2 that is bug-free, and one for sse2 that will likely run ok in most cases (but not guaranteed). It takes a bit of work to set that up though, so I don't want to do it if nobody needs a prebuilt binary for non-sse4.2 CPUs.
 
Hi,
I am trying to install camilladsp on a Radxa Rock 5b. I am no expert on Linux so I am struggling to install/make the snd-aloop module. It seems it do not exsist in the rockchip kernel I have installed (ubuntu 22.04). I can open the gui, but get some errors:

Camilla:
2023-10-13 14:57:17.761336 INFO [src/bin.rs:711] CamillaDSP version 1.0.3
2023-10-13 14:57:17.761463 INFO [src/bin.rs:712] Running on linux, aarch64
2023-10-13 14:57:17.774642 ERROR [src/bin.rs:362] Capture error: ALSA function 'snd_pcm_open' failed with error 'ENOENT: No such file or directory'
2023-10-13 14:57:17.774792 ERROR [src/processing.rs:50] Message channel error: receiving on a closed channel

Terminal:
paal@paal-desktop:~$ sudo modprobe snd-aloop
modprobe: FATAL: Module snd-aloop not found in directory /lib/modules/5.10.160-rockchip


Can you give me any guidance?
 
Would it help and make sense to have two builds - one for older and another for newer Intel CPUs?
Many rock-solid and still-going-strong Laptops are built around the Core2Duo processors, e.g. the widespread and still-in-use Thinkpad T500. And W10 still runs fine on them for avererage everyday tasks. And I think that the average windower is not as keen as an averager linuxer to compile things, and that the average windower is rather used to download and go ahead with a running solution. Therefore ... yes, maybe two builds.
 
Is there a reason the example camilladsp.service runs uses root as user?

I am very much a noob with permissions, but it seems like if the first time you start camilladsp is via the service running as root, it will create statefile.yml with root as an owner which it seems like cannot be written by the GUI. It is pretty easy to change these permissions but wondering if there is any reason to run camilladsp as root?

Michael
 
I am struggling to install/make the snd-aloop module. It seems it do not exsist in the rockchip kernel I have installed (ubuntu 22.04)
It's usually in a separate package. I think it's called linux-modules-extra on ubuntu.
Many rock-solid and still-going-strong Laptops are built around the Core2Duo processors, e.g. the widespread and still-in-use Thinkpad T500. And W10 still runs fine on them
Yeah it would be a bit sad to abandon the core2duos. Strangely the bug doesn't seem to appear on windows, so there they should still be fine. But I had an idea for a different workaround. I'll try that first, before spending time on setting up separate builds (and the documentation for that, probably would take more time than adding the actual build).
 
Has anyone had issues installing pycamilladsp and pycamilladsp-plot alpha2 on Ubuntu 22.04 (RPi)? I can install them without issue on Ubuntu 23.10 but when I attempt to install them on 22.04 they seem to be installed as UNKNOWN.

Code:
michael3@raspberrypi3:~/camilladsp/pycamilladsp-plot-2.0.0-alpha2$ sudo pip3 install .
Processing /home/michael3/camilladsp/pycamilladsp-plot-2.0.0-alpha2
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Installing backend dependencies ... done
  Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: UNKNOWN
  Building wheel for UNKNOWN (pyproject.toml) ... done
  Created wheel for UNKNOWN: filename=UNKNOWN-0.0.0-py3-none-any.whl size=13292 sha256=fdeb884429193e8c003f77738b5f938def5e8c1b0952f36e3fd9e3d8ca0725f0
  Stored in directory: /root/.cache/pip/wheels/5f/ac/0d/0a4eff23149653c6994ef5d806a980dac0a365b3ed4ca30f58
Successfully built UNKNOWN
Installing collected packages: UNKNOWN
Successfully installed UNKNOWN-0.0.0

I have no issues on alpha1.

Code:
michael3@raspberrypi3:~/camilladsp/pycamilladsp-2.0.0-alpha1$ sudo pip3 install .
Processing /home/michael3/camilladsp/pycamilladsp-2.0.0-alpha1
  Preparing metadata (setup.py) ... done
Requirement already satisfied: PyYAML in /usr/lib/python3/dist-packages (from camilladsp==2.0.0a1) (5.4.1)
Requirement already satisfied: websocket_client in /usr/lib/python3/dist-packages (from camilladsp==2.0.0a1) (1.2.3)
Building wheels for collected packages: camilladsp
  Building wheel for camilladsp (setup.py) ... done
  Created wheel for camilladsp: filename=camilladsp-2.0.0a1-py3-none-any.whl size=21555 sha256=dafd5d4dcf608ea352292d2e00c5979ac57ac3b5bf8e9847a06e564a2f43897d
  Stored in directory: /root/.cache/pip/wheels/04/90/f3/56b021e3675e0fe174941db6b512a956c2add60ccf4a6d5f41
Successfully built camilladsp
Installing collected packages: camilladsp
Successfully installed camilladsp-2.0.0a1

EDIT: If it helps here are the python3 and python3-pip versions for each.

22.04
python3-pip/jammy-updates,jammy-security,now 22.0.2+dfsg-1ubuntu0.3 all [installed]
python3/jammy-updates,jammy-security,now 3.10.6-1~22.04 arm64 [installed]

23.10
python3-pip/mantic,now 23.2+dfsg-1 all [installed]
python3/mantic,now 3.11.4-5 arm64 [installed]

Michael
 
Last edited: