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

Henrik and Pavel,
I'm exploring Using REW to CamillaDSP set up in Gadget Mode with the attached config.

There is a problem with CamillaDSP going into Inactive state, so I posted in the REW forums
https://www.avnirvana.com/threads/testing-rew-to-rpi-5-in-gadget-mode-running-camilladsp.14657/

Here is an extract from the post of the problem:
Moving on to Make a Measurement, output device "EXCL: Speakers (3- Source/Sink)" sample rate at 48kHz. The Check Level will play, CDSP going from Stalled to Running and sound is heard, then at the end of the 3 second burst CDSP goes INACTIVE with log:
2025-01-31 14:23:45.714920 INFO [src/alsadevice.rs:970] Capture device is stalled, processing is stalled
2025-01-31 14:23:57.893785 WARN [src/alsadevice.rs:113] PB: Prepare playback after buffer underrun
2025-01-31 14:24:01.644637 ERROR [src/bin.rs:354] Capture stopped due to external format change
2025-01-31 14:24:01.644632 INFO [src/alsadevice.rs:983] Capture stopped

I suspect that REW is sending something different at the end of the 3 second Measurement / Check Level burst as compared to Preferences/Soundcard Check Level.

In case I have made a fool of myself again, would you check the attached config and possibly look at the full post linked above and comment.
 

Attachments

Debug logs attached
Are they from the same run? They do not seem so:

Code:
grep "Gadget rate" cdsp.log
2025-02-01 22:08:07.650874 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-01 22:08:07.651822 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-01 22:08:07.653823 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-01 22:08:14.977750 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-01 22:08:29.086524 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-01 22:08:29.087479 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-01 22:08:29.089480 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-01 22:08:32.665473 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-01 22:08:32.672436 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-01 22:08:32.673425 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-01 22:08:32.675428 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(44100)

vs.
Code:
grep "Opening Render device Speakers (3- Source/Sink): rate:" csjsound-lib.log
11:24:24.9827508 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
11:24:25.1227927 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 48000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
11:25:11.909302 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
11:25:47.5475839 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
11:27:34.2660248 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144

Logs from different runs are of little value for troubleshooting this.
 
@HenrikEnquist : Please would it be possible to change this log https://github.com/HEnquist/camilla...e888c24c17182b63d051/src/socketserver.rs#L506 to trace? There are 19k "parsed command" lines out of the 19.5k lines of the debug log and analyzing the log requires removing the lines with grep -v first 🙂 Or ideally a way to avoid the socketserver logs alltogether with some parameter as they will pollute the trace logs when analyzing alsa performance in the same way. Thanks for considering.
 
Hello,

I had a situation in the past where if I had a configuration with 2 convolution filters in series it caused clipping. I reported it at the time.

Now I've come to a block in my development becuase I require muiltiple wav convolution filters in each channel. The symptoms are gain boost of around 350db as per the log! If I disable in the pipeline editor all the filters except 1 per channel, gain looks normal. If I add in one more filter per channel it clips, and gets worse as more filters are enabled. So I think I'm seeing an accumulative gain as more filters in the chain are added, In my particulqar case, these filters represent discrete peaking filters. But the problem I think is wider as per my previous problems. Any suggestions would be greatly appreciated.

Tony
 
If you do these in rePhase, there is a slider to set the overall attenuation in the generated filter - you can identify the highest gain in the passband and lower the total gain of the filter to compensate.

Or, its a good practise to not do + gain (above 0) but rather resort to attenuation (of the rest...) when doing EQ... REW certainly promotes this whit its interactive guidance in its EQ section.

//
 
Hello,

I had a situation in the past where if I had a configuration with 2 convolution filters in series it caused clipping. I reported it at the time.

Now I've come to a block in my development becuase I require muiltiple wav convolution filters in each channel. The symptoms are gain boost of around 350db as per the log! If I disable in the pipeline editor all the filters except 1 per channel, gain looks normal. If I add in one more filter per channel it clips, and gets worse as more filters are enabled. So I think I'm seeing an accumulative gain as more filters in the chain are added, In my particulqar case, these filters represent discrete peaking filters. But the problem I think is wider as per my previous problems. Any suggestions would be greatly appreciated.

Tony

Post your configuration and filters.

Michael
 
Yes I know, the interesting bits drown in the socketserver messages. I plan to make it possible to set a separate log level for the socketserver, just need to figure out how to do it 🙂
Thanks! Perhaps the most flexible standard solution is using some facility with logs (or a default facility if none is specified) and allowing to define individual log levels for each facility in a config parameter. That would allow e.g. setting trace e.g. only for alsa, while keeping the rest at info. Maybe there is a rust logging crate which supports this, it's quite common.
 
Are they from the same run? They do not seem so:
Yes, but I repeated the test -

CDSP sudo service camilladsp stop
CDSP edit camilladsp.service to add -l debug
CDSP sudo service camilladsp start - State:Starting

REW add -DcsjsoundLibLogLevel=debug
REW Open, get message about debug
REW Preferences, check level - CDSP State:Starting

CDSP Apply config to DSP - State:Stalled

REW Make a Measurement, check level - CDSP - State:Running (calibration signal heard) -
REW stops signal after 3 seconds, CDSP State: Inactive.

CDSP sudo service ... stop
REW Close.


Looking through CDSP log, at 2025-02-02 14:51:06.168271 it appears the rate changes.

Edit: After posting, I changed CDSP capture rate to 44100 and REW prefs to 44100 and it worked, CDSP toggles between Running and Stalled as expected. Will report to REW forum.
 

Attachments

Last edited:
Thanks - I shall study these.

//
I fired up picoreplayer on a Rpi and did some experimenting to see what might work for you. It would be possible to get my script to work but you'd still need another script or service to receive the remote control commands. I think it might be easiest to use mdsimon's excellent script here: https://github.com/mdsimon2/RPi-CamillaDSP/blob/main/flirc.py

This script runs in a loop (ie. continuously), monitoring for remote control inputs at the device listed on line 12: flirc=evdev.InputDevice('/dev/input/by-id/usb-flirc.tv_flirc-if01-event-kbd')
It then checks which button you've pressed, eg: if attrib.keycode == 'KEY_DOWN': and then sends the corresponding command to CDSP

I believe it would be possible to use either the FLIRC device + remote (https://flirc.tv/) or a remote that connects via bluetooth (eg https://www.sofabaton.com/products/x1s/) by this method. You will likely need to update the InputDevice path (and potentially the attrib.keycodes) in the script.

This repository (I assume you used this script to install CDSP?) has some details about how to run custom scripts that interface with CDSP on picoreplayer https://github.com/JWahle/piCoreCDSP#running-your-own-python-scripts
Outline of the steps is:
  1. Download python script (flirc.py) to main computer
  2. Ensure SSH enabled on PCP: [Main Page] > [Security] > [SSH]
  3. Use terminal software to verify you have SSH access - this will also be necessary for checking InputDevice path and general troubleshooting: ssh tc@pcp.local (Type 'exit' to leave SSH session)
  4. Use SSH file copy ('SCP') on main computer to copy flirc.py to your PCP, eg: scp flirc.py tc@pcp.local:~
  5. Use the [Tweaks]>[User commands] setting in PCP to load flirc.py at startup. Command to input eg: sudo -u tc sh -c 'source /usr/local/camillagui/environment/bin/activate; python3 /home/tc/flirc.py'
 
Edit: After posting, I changed CDSP capture rate to 44100 and REW prefs to 44100 and it worked, CDSP toggles between Running and Stalled as expected. Will report to REW forum.
I would say that there is no bug in rew. It may needlessly change the rate of the device, but it's setting it to a rate that you have configured the gadget device allow, so it's not doing anything bad so to speak. The promblem then is that you run CamillaDSP without any way to handle rate changes. You need either some way to let CamillaDSP restart with an appropriate config at gadget rate changes (check out camilladsp-controller or camilladsp-setrate for example), or limiting the gadget to a single rate.
 
I fired up picoreplayer on a Rpi and did some experimenting to see what might work for you.
You are too kind! I'm waiting for a pi5 but need to decide what type remote I would like - I think the small metallic Apple one is the one I prefer and it is IR 38khz - if I get an IR sensor and hook that up to the Pi per instruction (3 leads) - will this be something that could work? Is the little Flir USB blob something that I will need in any case or do the IR sensor replace this?

//
 
@Wirrunna :

Code:
grep "Opening Render device Speakers (3- Source/Sink): rate:" Stažené/csjsound-lib.log
03:48:43.4598839 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
03:48:43.5879966 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 48000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
03:48:53.8036758 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
03:49:12.2500903 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144
03:51:02.9351076 DEBUG [src\wasapi_impl.rs:309] Opening Render device Speakers (3- Source/Sink): rate: 96000, validbits: 32, frame_bytes: 8, channels: 2, buffer_bytes: 262144


Code:
grep "Gadget rate" Stažené/camilladsp.log
2025-02-02 14:51:02.574534 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-02 14:51:02.575472 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-02 14:51:02.578471 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-02 14:51:06.152299 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-02 14:51:06.165335 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(96000)
2025-02-02 14:51:06.166280 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(0)
2025-02-02 14:51:06.168271 DEBUG [src/alsadevice_utils.rs:529] Gadget rate: Some(44100)

As Henrik says, you cannot run CDSP with the gadget in this way. At 14:47 CDSP, when starting, tries to open the capture device at the configured rate of 96k. But the gadget device is not configured from the REW playback yet, and is switched to its basic rate, IMO 44.1k. Starting fails. Only after REW starts playback, the gadget capture device flips to 96k and CDSP can start up. After REW finishes wasapi exclusive plaback, IMO the windows mixer flips the USB audio device back to 44.1k which is probably the rate set in the windows mixer for this device - you can check. That's the last log "Gadget rate: Some(44100)" the gadget reports.

That's why using 44.1k only works for your setup, because REW uses the same rate as windows mixer, and the gadget ends up running only at one samplerate, allowing CDSP to open the device at 44.1k only too.

IMO the only unusual behavior is why REW tries to open the device at 48k, but that's probably the REW's internal check to confirm supported rates - we can ask John.

Nevertheless - you need a controller which aligns the gadget and CDSP operation - I would suggest to read the reasoning at https://github.com/pavhofman/gaudio_ctl. Then you can pick which controller you want to use. gaudio_ctl is general purpose, and will make cdsp process start/exit. Specialized solutions for CDSP - python-based https://github.com/HEnquist/camilladsp-controller and C-based https://github.com/marcoevang/camilladsp-setrate keep CDSP running and control it via its websockets API. That is better for lower startup delays.
 
Last edited:
Is the little Flir USB blob something that I will need in any case or do the IR sensor replace this?
The FLIRC usb dongle is an IR sensor + microcontroller, so it's either/or - not both the FLIRC dongle and separate IR sensor.

FLIRC:
  • No to minimal wiring/soldering required, depending on how you've got your pi housed.
  • GUI for configuration and learning Apple remote IR codes
  • In theory should work with minimal configuration on the pi itself, flirc.py pretty much good to go

IR sensor via pi's GPIO:
  • Cheaper than FLIRC
  • Potentially more wiring/soldering and mounting challenges for the IR sensor
  • Configuration / IR code learning via command line/text files
  • Likely possible to use the flirc.py script without significant modification if you can get this to create a /dev/input/event0 style device for flirc.py to use: https://www.lirc.org/html/lircd-uinput.html

If it was me I'd use the FLIRC dongle 🙂
 
Thanks!

Thing is that I will house the Pi in a bigger box and it will not be so easy to make that dongle listen to the outside world as I intend to make the box a Faraday cage. But a drilled hole on the front for the sensor would be ok.

Soldering connecting is no problem.. its the soft side of things that I'm not so sure about... but can probably be helped if I ask nicely 🙂

//
 
  • Like
Reactions: fb
Thing is that I will house the Pi in a bigger box and it will not be so easy to make that dongle listen to the outside world as I intend to make the box a Faraday cage. But a drilled hole on the front for the sensor would be ok.

Soldering connecting is no problem.. its the soft side of things that I'm not so sure about... but can probably be helped if I ask nicely 🙂
I am in the process of designing and building an 8-channel DAC with a built-in Raspberry Pi running CamillaDSP. I'll be using a VS1838 IR sensor, like this one:

1738501698846.png


Wiring it is as simple as it gets: +5V or +3.3V, GND and signal. I've used it several times in other projects, it is cheap (less than 1 usd), stable, and has a good reception angle. I will be using an Arduino Nano as standby circuit and controller to avoid keeping the Pi turned on all the time - so the IR will be wired to the Arduino - but the process of connecting it to the Pi is similar and fairly well documented.

If you decide to go down this path, I 'd be happy to help you with the software part. It's not that difficult.
 
Last edited:
  • Like
Reactions: PMental and fb
Thanks! Perhaps the most flexible standard solution is using some facility with logs
Done in branch "next31", that will become camilladsp v4.0. I simply added an option to enter a filter string that gets directly passed to the logging library. This way it's possible to set the log level individually for each module. You can for example have "trace" level for the Alsa backend, completely silence the socket server, and use "info" for the rest. See https://docs.rs/flexi_logger/latest/flexi_logger/struct.LogSpecification.html
 
  • Like
Reactions: phofman and fb