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

I just started messing with CamillaDSP with MoodeAudio and an 8ch HDMI extractor (Very nice so far). I also have in my posession, the DAC8x and I'm waiting for my Pi 5 to arrive in the mail. I'm looking forward to trying this out. Are you doing streaming only or have you incorporated some sort of ADC (or digital)
input?
I have both streaming and analog input, analog into a Motu M4 connected via usb to the RPi 5 running CamillaDSP.
I will document it all when it I have the attached "RaspberryPi Official 7" Touchscreen Display" working a bit better, but basically I used the RPi Imager to create a 64bit RPi OS Lite SD card, added the Overlay for /boot/firmware/config.txt: dtoverlay=hifiberry-dac8x
then followed Michael's excellent tutorial (https://www.audiosciencereview.com/forum/index.php?threads/rpi4-camilladsp-tutorial.29656/) to install CamillaDSP.

The DAC8X showed up in the CamillaDSP devices tab
Device selection.jpg


Here is the Device after selection
Input and output Devices.jpg


I have attached a zip file of configs and associated coeffs. The DAC8X configs are labelled, there are a streamer with input filters and EQ for Klipschorn speakers and analog with no filters. There is also config.txt.

My intention is to get the RPi and touch screen working as a stand alone DSP.
CamillaDSP Pi.JPG


The CamillaDSP is working fine, the touchscreen doesn't work properly - no touch - on the RPi 5 .
 

Attachments

  • configs.zip
    698.5 KB · Views: 15
Sweet. I had a quick look at Camilla a couple of years ago but I found it a bit overwhelming, but took another stab at it last weekend and I actually got 8ch crossover working surprisingly easy, so I look forward to getting the inputs working g this weekend if I find some time to play.

Any issues with sync between the two devices? Audible glitches or dropouts?
 
@DarpMalone If you are using separate devices for input and output, you need to think about clocking. In my current setup, ADC and DAC are clocked separately, so I use the Async resampling in CamillaDSP. This is fine for me as I'm not a fanatical audiophile, but some people don't like it. If I don't have this enabled, I get buffer underrun every 45 mins due to clock drift,
 
I use Windows and ultralite mk5. I don't use a raspberry pi, and I think CamillaDSP should work as Windows alone.

1.png
I've followed ASR's tutorial, but I'm stuck. I've tried hw:Ultralitemk5, hw:Ultralite-mk5, Ultralitemk5, Ultralite-mk5 as the device name, but I get a capture error as shown in the image above. The step by step guide also says "Here let's assume we already figured out all the Loopbacks etc and already know the devices to use." which is not helpful.
EqualizerAPO is obviously the easy way to go for Windows-only user, but MOTU doesn't support multichannel WDM so I can't perform multiway crossover with it.

Any help would be so much grateful.

Edit: I read about clearing the device field and using it as default, so I tried it, but this time I get the following error.
2.png
 
Last edited:
@Wirrunna : IIUC your setup uses a USB soundcard on capture and an I2S device on playback. You have rate-adjust enabled, and it correctly measures the clock difference (at 1.0075). Yet your resampler is synchronous which will eventually result in xruns. IMO the asynchronous resampler is required in your setup.

CDSP v.2 changed buffer size to 4x chunksize. Optimal target level would be 75% of the buffer filled, i.e. 3 chunk sizes. Due to https://github.com/HEnquist/camilladsp/issues/335 only 2 chunksizes max can be set in the target level parameter, yet your config sets only 1 chunksize (target-level=2048). IMO setting target-level to 4096 (with the async resampler, of course) would make the setup more robust. In the upcoming CDSP v.3 (which has the max value of the parameter raised to full buffer size) I would recommend to set the target level to 3 x 2048 = 6144. To minimize latency, if needed you could lower the chunksize e.g. to 1024 in CDSP3.
 
  • Like
Reactions: 1 user
1.png
I've followed ASR's tutorial, but I'm stuck. I've tried hw:Ultralitemk5, hw:Ultralite-mk5, Ultralitemk5, Ultralite-mk5 as the device name, but I get a capture error as shown in the image above.
That parameter needs to be a device name, as recognized by the respective audio backend. hw:xxx is naming of linux alsa. You need to use WASAPI naming. IIRC if you run camilladsp with parameter -v (verbose), it will list all available devices including their string names to use in the config file.

The step by step guide also says "Here let's assume we already figured out all the Loopbacks etc and already know the devices to use." which is not helpful.
Well, software audio loopback is not simple on any OS. Linux has a built-in loopback device, very flexible, and most tutorials focus on that one. Windows has third-party loopback softwares - see https://www.google.com/search?client=firefox-b-lm&q=audio+loopback+software+for+windows . Each gets setup differently, likely each has issues.

BTW Henrik did a very good job describing one of the possible setups in https://github.com/HEnquist/camilladsp/blob/master/backend_wasapi.md . It's part of the official documentation, linked from the homepage https://github.com/HEnquist/camilladsp/tree/master?tab=readme-ov-file#windows
 
Thanks @phofman !
I'm planning to use my ultralite's loopback, so software loopback won't be a problem.
I found that it actually works if I type in the channel name that the audio interface provides like S/PDIF OUT 1-2(Ultralite-mk5). That's a good start.
However, this method only allows me to utilize two of the stereo input/output channels, for example Line Out 1-2,Line Out 3-4, Line Out 5-6, etc. And it doesn't appear to allow me to input multiple playback devices.
What I was hoping for was to recognize the entire device at once and use all 16 inputs and 18 outputs at once, and apparently the tutorials using the Raspberry Pi do this in the form of hw:Ultralitemk5. Your link also shows 2 channel application.. so I'm stuck again 😢
 
However, this method only allows me to utilize two of the stereo input/output channels, for example Line Out 1-2,Line Out 3-4, Line Out 5-6, etc. And it doesn't appear to allow me to input multiple playback devices.
See e.g. https://www.diyaudio.com/community/...-interfaces-are-actually-multichannel.395126/
What I was hoping for was to recognize the entire device at once and use all 16 inputs and 18 outputs at once, and apparently the tutorials using the Raspberry Pi do this in the form of hw:Ultralitemk5.
See https://www.diyaudio.com/community/...re-actually-multichannel.395126/#post-7252339 . Your device is multichannel, therefore it works as multichannel in linux. But your device vendor decided to split it into multiple pairs by its windows driver. You paid (big) money to Motu, they should be the ones receiving your complaint :)
so I'm stuck again
I am afraid that's quite typical on windows where you are stuck with choices done by the vendors. Sorry for being honest, it's just the way it is.
 
@Wirrunna : IIUC your setup uses a USB soundcard on capture and an I2S device on playback. You have rate-adjust enabled, and it correctly measures the clock difference (at 1.0075). Yet your resampler is synchronous which will eventually result in xruns. IMO the asynchronous resampler is required in your setup.

CDSP v.2 changed buffer size to 4x chunksize. Optimal target level would be 75% of the buffer filled, i.e. 3 chunk sizes. Due to https://github.com/HEnquist/camilladsp/issues/335 only 2 chunksizes max can be set in the target level parameter, yet your config sets only 1 chunksize (target-level=2048). IMO setting target-level to 4096 (with the async resampler, of course) would make the setup more robust. In the upcoming CDSP v.3 (which has the max value of the parameter raised to full buffer size) I would recommend to set the target level to 3 x 2048 = 6144. To minimize latency, if needed you could lower the chunksize e.g. to 1024 in CDSP3.
Pavel, I welcome your constructive feedback. I will apply the changes immediately. In my defense I am a 76 year old long retired IBM 360/370 assembler programmer who is still learning, but with CamillaDSP and advice from people like you I have made my Klipschorns (patented in the year I was born - 1947) sound superb and coherent - no longer the smeared sounds from the wildly different length horns.
The only latency I try to minimize is the TV sound that comes in as analog so to get not too noticeable lip-sync delay. My main source is streamed from my Squeezebox server. Thank you again.

Edit : Pavel, I dashed that reply off without thinking - that config was a "proof of concept" that the DAC8X could output from an analog input, however your suggestions are still gold. If you have time, could you have a look at the KHorn configs that are fed from Squeezelite running on the same RPi. They are in the zip file.
 
Last edited:
If you have time, could you have a look at the KHorn configs that are fed from Squeezelite running on the same RPi.
I do not see any issues in the alsa section of DAC8X_KHorn Sqz.yml, just I would recommend to raise the target level to the two chunksizes mentioned, to give the feedback control more headroom.

This is what CDSP does in the alsa backend (v.2 has buffer_size = 4 x chunksize = 4 x io_size):

1713516564437.png


The playback thread receives AudioMessages from the DSP Processing thread which always bring chunksize of fresh audio frames to play. These samples are written to the soundcard buffer. The playback thread measures average fill of the buffer - displayed in the GUI. This average level is compared to the target level and a feedback controller (async resampling or capture rate control) tries to keep the average level as close to the target level as possible.

Every incoming AudioMessage fills the buffer with chunksize of samples - the jumps in the diagram. The soundcard continuously consumes the samples from the buffer - the declining lines on the diagram. When the line hits zero, a buffer underrun/xrun occurs.

Now what happens if the target-level is equal to chunksize. The average buffer fill fluctuates between 0 and 1 chunksize, getting dangerously close to the zero. Whereas is you set the target level higher (and the change in v. 2 to 4 chunksizes does help to make it more granular), the timing has more headroom to avoid the underflow. IMO the safest level is around 75% of the buffer - 3 chunksizes. That way the average buffer level fluctuates around the 3 chunks, safely from the zero.

If you care about latency, you can play with smaller chunksizes (+ correspondingly lowered target level). The powerful RPi5 may be OK with chunksize 512 or maybe even 256.