• Welcome to ASR. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

RPi + CamillaDSP Tutorial

IIUC largely down to Geoffrey Bennett at linuxmusicians, crowdfunding for the small models, and Focusrite providing the larger ones. I guess you know about the GUI already. This part of the driver is for the software controlled bits of the user interface and the mixer - last I looked the audio transfer uses the generic UAC2 audio driver.
https://linuxmusicians.com/viewtopic.php?t=26173
https://linuxmusicians.com/viewtopic.php?t=27505
https://linuxmusicians.com/viewtopic.php?t=26217
Yes that's the author. I installed the FCP driver, because Raspberry OS is currently at kernel 6.12 and the FCP says that support for my model ships with 6.14. At the moment I don't have any GUI-Linuxes, so I installed only the driver. Again that was before I realized what the real problem was, so I cannot tell if installing it made a difference in my Raspberry.
 
IMO design a chain where all frequency sections of one channel go through the same latencies (or through minimal ones). Preferrably not only of one channel, but of all channels.

Linux is not a hard real time OS. It cannot start playback on USB at sub-millis precision.

IMO the logical chain would be source/sources -> CDSP -> Focusrite -> analog to all the channels/subchannels. CDSP does not have to run on RPi with only one I2S I/O port, there are devices with many various inputs - like the Wiims do.
 
Huge thanks to @HenrikEnquist and @mdsimon2 for the great DSP software and setup guide / example configs respectively.

I am using an UltraLitemk5 and most everything is working well, however I do have some questions.
  1. When I use the configs ultralitemk5_toslink_48c_48p.yml and ultralitemk5_analog_48c_48p.yml, CDSP shows input on the analog channels OR on TOSLINK (12/13), but never both. Considering the capture and playback devices section of the configs are the exact same (only the mixers are different), what actually changes which inputs can be received? Clock source is set manually through the front panel, so I don't think it's that. When running a TOSLINK config only 12/13 show input in CDSP, when running an analog config I can see levels on 2/3. In both cases the display of the ultralite shows levels on both analog and digital input.
  2. Is it possible to mix both USB interface (e.g. streaming with raspotify or librespot to the ultralite and using the loopback) and TOSLINK (from TV or HDMI audio extractor) in a single config? I understand clock source may be an issue here.
  3. Has anyone successfully forwarded their ultralite network to their local network? I took a quick shot at this project but couldn't quite get it working. Maybe this is a question for another thread.
 
At least I can confirm that Focusrite Scarlett 18i16 (4th gen) works very well with CamillaDSP on Raspberry Pi 4B through USB loopback. CamillaDSP can input sound stream from any of the inputs and route them back to any of the outputs at 24 bit 96 kHz format. I haven't tested other formats, Scarlett supports up to 192 kHz sample rate, but I cannot use them because I need to match what comes from the SHD. In addition to that, there are some useful features on the Scarlett itself, like the volume knob on the front panel that can be either disabled or enabled. The Scarlett has a selection to use internal, SPDIF or ADAT clock, which is essential for this application (select SPDIF). And I love the red case color and signal/volume indicators around the dials.

I'm still testing spots and other settings for null filling for the new subs, so I cannot fully commit on to the timing issue yet. They are >50 kg each, not something I want to heave around every day :)

Thanks for all your help so far.
 
Has anyone successfully forwarded their ultralite network to their local network? I took a quick shot at this project but couldn't quite get it working. Maybe this is a question for another thread.
There's some discussion of it starting here - either forwarding the port or using nginx as a reverse proxy. IIRC you can host the CueMix5 content on nginx too, so you can use it from any machine with a web browser on your network.
 
Bash:
iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 1280 -j DNAT --to-destination 169.254.247.84:1280
iptables -t nat -A POSTROUTING -d 169.254.247.84/32 -p tcp -m tcp --dport 1280 -j MASQUERADE
 
Bash:
iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 1280 -j DNAT --to-destination 169.254.247.84:1280
iptables -t nat -A POSTROUTING -d 169.254.247.84/32 -p tcp -m tcp --dport 1280 -j MASQUERADE
This looks like setting up port forwarding on a linux machine, assuming that eth0 is your linux machine's interface on the local network and 169.254.247.84 is the IP address of the ultralite. It would normally get added to one of the machine's init scripts.
 
When I use the configs ultralitemk5_toslink_48c_48p.yml and ultralitemk5_analog_48c_48p.yml, CDSP shows input on the analog channels OR on TOSLINK (12/13), but never both. Considering the capture and playback devices section of the configs are the exact same (only the mixers are different), what actually changes which inputs can be received? Clock source is set manually through the front panel, so I don't think it's that. When running a TOSLINK config only 12/13 show input in CDSP, when running an analog config I can see levels on 2/3. In both cases the display of the ultralite shows levels on both analog and digital input.

You can modify the mixer to route both analog and TOSLINK inputs to outputs via CamillaDSP. As you allude to, in order for clocking to work correctly you need to have the clock set to optical.

Is it possible to mix both USB interface (e.g. streaming with raspotify or librespot to the ultralite and using the loopback) and TOSLINK (from TV or HDMI audio extractor) in a single config? I understand clock source may be an issue here.

A streaming configuration using an ALSA loopback as a capture device and an optical input configuration uses the Mk5 as a capture device, therefore there is no easy way to use both in a single configuration.

It may be possible to make an ALSA multi device configuration (https://github.com/HEnquist/camilladsp-config) but I don't see how you would ever achieve clock sync, and I think you will run in to buffer over / under runs.

Has anyone successfully forwarded their ultralite network to their local network? I took a quick shot at this project but couldn't quite get it working. Maybe this is a question for another thread.

As mentioned by others I use nginx and there are instructions in the tutorial on how to set it up (https://github.com/mdsimon2/RPi-CamillaDSP?tab=readme-ov-file#nginx).

Michael
 
A quick question about the web interface: I have multiple eq profiles but switching between them using the shortcuts/compact view does not save the newly selected profile in statefile.yml, so the selection does not survive a Camilla restart. The only way I have found to update the statefile is to set the profile active in the files tab.

Is there some setting I am missing?
 
For latency the SHD will add 25 ms latency IIRC. Fortunately a synchronous SPDIF input setup should work will with relatively low chunk sizes. To minimize latency I would start with the chunk size values in my tutorial but set target level equal to chunk size rather than 3 x chunk size. If that works I would halve chunk size and target level until you run in to issues. I am not familiar with Focusrite but I would expect most interfaces to be able to achieve ~10 ms latency in CamillaDSP in a synchronous setup.
I got 96000 as "samplerate". Under "Buffers" I've set "chunksize" to 64, which works often but not always, or 128 which works always, and "queuelimit" as 1. With this I get less than 10 ms latency, which is easily compensated with the mains. You speak of target level, but if you are refering to "target_level" under "Rate adjust", I have had that as default and "no" for "enable_rate_adjust". I believe the default "target_level" is good for low latency when using rate adjust if "Buffers" is set to as low as possible, right?

I have got a new problem, this started today, but was not there last time. I get audible "snaps" about once every second during playback from the bass section. I use 100 Hz sine or bass-range pink noise for testing. The snaps sounds the same when I had the Scarlett using internal clock, but I checked that it should be using SPDIF clock now. I reset most latency-related settings but no effect. What makes it more mystical is that only the upper bass speakers snap, not the subwoofers. Right now the only filters in my pipeline are 10 Hz HPF for all channels and one Linkwitz-Transform for the sub mono channel, so not heavily used.

This is how it looks like among pink noise when recorded with a mic:
1758992412917.png


My pipeline while testing. The upper bass pipelines are shorter than lower bass pipelines, but that doesn't matter, right?
1758992892344.png


My log is flooded with all kinds of messages, mostly because I tried different settings in order to recognize the cause. None made any difference.
Code:
2025-09-27 18:50:43.640483 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:43.648478 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:43.656491 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:43.664485 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:43.672482 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:43.680483 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:43.688483 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:50:56.392355 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:50:56.697429 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:50:56.698893 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:52:28.784455 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:52:29.090379 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:52:29.091845 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:01.672342 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:55:01.977275 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:55:18.220378 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:55:18.667047 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:55:21.958460 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:22.086829 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:22.600956 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:22.724105 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:23.022996 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:23.154006 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 18:55:28.072551 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:55:28.518103 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:55:49.444584 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:55:49.889483 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:56:14.320116 ERROR [src/processing.rs:132] Message channel error: receiving on a closed channel
2025-09-27 18:56:14.320309 INFO  [src/bin.rs:373] Playback finished
2025-09-27 18:56:51.987359 WARN  [src/processing.rs:97] Failed to build thread pool, error: The global thread pool has already been initialized.
2025-09-27 18:56:52.343955 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:57:17.672658 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 18:58:22.339640 INFO  [src/alsadevice.rs:976] Capture device is stalled, processing is stalled
2025-09-27 18:58:22.444174 ERROR [src/processing.rs:132] Message channel error: receiving on a closed channel
2025-09-27 18:58:22.444535 INFO  [src/bin.rs:373] Playback finished
2025-09-27 19:01:18.044679 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 19:03:11.977540 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 19:03:16.767501 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.769491 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.771493 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.775493 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.779494 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.783494 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.791494 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.795493 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.799530 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.801019 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:03:16.803096 WARN  [src/alsadevice.rs:207] PB: write underrun, trying to recover. Error: ALSA function 'snd_pcm_writei' failed with error 'Broken pipe (32)'
2025-09-27 19:03:16.811161 WARN  [src/alsadevice.rs:242] Prepare capture device
2025-09-27 19:03:16.812382 INFO  [src/alsadevice.rs:561] PB: device stalled
2025-09-27 19:03:16.831416 INFO  [src/alsadevice.rs:976] Capture device is stalled, processing is stalled
2025-09-27 19:03:16.831602 ERROR [src/bin.rs:314] Capture error: ALSA function 'snd_pcm_start' failed with error 'Broken pipe (32)'
2025-09-27 19:03:31.577624 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 19:13:51.219324 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 19:42:44.912509 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 19:42:55.885251 INFO  [src/alsadevice.rs:117] PB: Starting playback from Prepared state
2025-09-27 20:14:13.315306 WARN  [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-09-27 20:14:13.324177 WARN  [src/alsadevice.rs:242] Prepare capture device
2025-09-27 20:14:13.344426 INFO  [src/alsadevice.rs:976] Capture device is stalled, processing is stalled
2025-09-27 20:14:13.344642 ERROR [src/bin.rs:314] Capture error: ALSA function 'snd_pcm_start' failed with error 'Broken pipe (32)'

If it's a clocking issue with the Scarlett, I'll immediately go for another miniDSP product and forget about this experimentary project. But is there a way to know what causes this? Any debug tools on Linux/CDSP that could indicate problems?
 
A quick question about the web interface: I have multiple eq profiles but switching between them using the shortcuts/compact view does not save the newly selected profile in statefile.yml, so the selection does not survive a Camilla restart. The only way I have found to update the statefile is to set the profile active in the files tab.

Is there some setting I am missing?

Not to my knowledge, that is just how the compact view works.

Michael
 
Yes, target_level under rate adjust. Default should be target level equal to chunk size so that should be the same as I what I told you.

If you previously did not have any issues until you reduced chunk size, I would say your chunk size is too low and should be increased.

Michael
OK thanks.

It shouldn't be a chunk size problem. I reverted most settings to default and chunk size to 4096 and also my pipeline is a bare minimum (12-in-4-out mixer). I get:
PC -> USB -> SHD -> SPDIF -> Scarlett -> USB -> CDSP -> USB -> Scarlett -> Analog 1-4, interference in each channel.
PC -> USB -> SHD -> SPDIF -> Scarlett internal routing -> Analog 1-2, no interference.
PC -> USB -> Scarlett USB in and routing -> Analog 1-2, no interference.
CDSP local wave file -> USB -> Scarlett -> Analog 1-2, no interference.

By interference I mean a "snap" (from a subwoofer) or "click" sound about once every second, sometimes skips. Its loudness is "loudish" compared to how loud the test signal is. Today I've tested with 100 Hz and 45 Hz sines as test signal. When I experimented with way too low chunk size I also got a crackling sound, but this is not that. If only I knew how to debug from Linux.. This could be a Focusrite Linux driver problem, I might need to consult a different forum.
I need to rest, busy weekend...
 
PC -> USB -> SHD -> SPDIF -> Scarlett -> USB -> CDSP -> USB -> Scarlett -> Analog 1-4, interference in each channel.
Is the Scarlett output clocked by the recovered incoming SPDIF clock? If not, rate adjust + async resampling would be required.
 
Not to my knowledge, that is just how the compact view works.

Michael
Thank you Michael. @HenrikEnquist is this something that can be changed? Intuitively, it seems to me that switching EQ with Shortcuts/Quick Config should do the same as marking the config active in the files tab as well as applying to the running DSP.
 
Is the Scarlett output clocked by the recovered incoming SPDIF clock? If not, rate adjust + async resampling would be required.
When I connect Scarlett USB to PC and check with Scarlett software, it says it's clocking by SPDIF. But I have no way to confirm that it's the same story when connected to the CDSP, although I have no reason to think it isn't. I'll try the rate adjust and resampler anyway if it makes a difference. I tried them earlier without success, but not together.
 
it says it's clocking by SPDIF
I do not know what that actually means in reality. Is there any explanation in user manual for your soundcard?

Rate adjust + async (!) resampler will make no harm, if not required - just a bit more CPU.
 
Shouldn't it be in alsamixer as 'Clock Source'?
Yes! It was "Internal", I somehow managed to change it to "SPDIF", the snapping immediately stopped! Thanks!

I do not know why it changed to Internal, when it was supposed to be SPDIF and it was SPDIF for sure I connected to and checked with a PC. I rebooted both RPi and Scarlett and it still is SPDIF, but the trust is gone. There is also the samplerate setting and one Scarlett specific coax vs. optical setting, both of which have been OK the whole time, but are not visible in alsamixer. Well I'll take my chances for now.
 
Last edited:
I do not know what that actually means in reality. Is there any explanation in user manual for your soundcard?

Rate adjust + async (!) resampler will make no harm, if not required - just a bit more CPU.
I got it solved for, but I'll answer just for the record and future generations.

Quotes from the manual:
Sync Status and using your Scarlett with ADAT and S/PDIF
The Sync Status icon (lock icon) on the front panel lights green when your Scarlett 18i16 is 'locked' or 'synchronised' to a clock source.

The Sync Status indicator is most useful when you're trying to expand the channel count using your Scarlett 18i16 with other equipment connected to your Scarlett 18i16's digital inputs or outputs; the ADAT or S/PDIF IO.
This was indeed green.
Important
To pass audio, the Sync Status indicator must light green. You can do this by making your Scarlett 18i16clock leader (Internal clock) or clock follower (ADAT or S/PDIF clock) with a valid clock leader connected.

When you're using the digital inputs your Scarlett 18i16 and the other audio devices need to have their internal clocks synchronised, using clock signals, so their audio is recorded in time.

Tip
If your digital audio devices aren't synchronised correctly, you'll hear audible glitches,
or the audio won't pass at all.
I got clitches.
There are a few principles when you're trying to synchronise multiple digital audio devices:
• The clock signal can be embedded into the audio signal, down the same cables (e.g.
S/PDIF, or ADAT).
• Clock signals are always one-way, you can't send and receive clock signals using one
ADAT or S/PDIF cable.
• There are Clock Leaders and Clock Followers.
Devices 'follow' other devices' clock signals. One device in your setup must be the clock
leader, the other devices must be followers and receive the clock signal from the clock
leader.
• Every device with digital I/O will have an internal clock and should have the option to be
a clock leader or a clock follower.
It was supposed to be "clock follower", but wasn't. The Scarlett has capability to sync clock signal by using it's coax and optical SPDIF/ADAT in+out ports, by using the other port for clock, with devices that support this procedure (like other Focusrite stuff). This is a pro or "prosumer" market device, so clocking should be one of the basics. I identified to interference as most probable clock issues, but could not confirm.

USB status icon:
USB LED - Lights green when your computer recognises your Scarlett,
and white if it is disconnected from your computer (in standalone mode).
It was green always when I looked.
 
Back
Top Bottom