• 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

I’m not sure. It very rarely stops working but it does every few weeks or so. I installed this one closely following your tutorial on github, I don’t think I modded anything

Interesting. What sort of setup are you running? While I do testing of all the configurations, the only ones I run for long periods of time are AES input Okto and TOSLINK input MOTU UL Mk5 configurations, both using rather simple IIR at constant 48 kHz.

Michael
 
Anyone successfully using HTTP POST to control CamillaDSP? I've been testing from my CDSP host, for example:

curl -X POST -H "Content-Type: application/json" --data '{"SetVolume": {"main": -33.0}}' http://localhost:1234/

or

curl -X POST -H "Content-Type: application/json" --data '{"Reload": null}' http://localhost:1234/

but all I ever get back is:

curl: (52) Empty reply from server
so clearly I must be missing something in the format of the command?
 
Last edited:
Anyone successfully using HTTP POST to control CamillaDSP?
It's not possible. HTTP and websocket are different protocols. You have to use a tool that supports websocket. There are several, but I haven't tried them so can't make any recommendations. Could you use python and the pycamilladsp library?
 
It's not possible. HTTP and websocket are different protocols.
Any chance HTTP support could get added as a control mechanism? My Sofabaton X1S remote doesn't support websocket.

Could you use python and the pycamilladsp library?
I already am but was hoping to simplify things. I currently use Home Assistant as a middle man for my remote.
 
Instead of CamillaDSP itself, you could use the API from CamillaDSP GUI.
Here you can see all available endpoints: routes.py

To get status informations, you could call this URL for instance: http://<host>:<port>/api/status
There are also endpoints for getting and setting the volume:
GET http://<host>:<port>/api/getparam/volume
POST http://<host>:<port>/api/setparam/volume
 
Any chance HTTP support could get added as a control mechanism?
It's really built around the websocket server library now. Adding http would require a completely separate implementation, I'm not very keen on that.
 
What's the rest of the syntax for this? Like if I wanted to set the volume to -32?
You need to set body param to the desired value:
Code:
curl --request POST \
  --url http://<host>:<port>/api/setparam/volume \
  --header 'content-type: text/plain' \
  --data -20

You can find more details for setparam here: views.py
Or you could check my home assistant integration for CamillaDSP for a real live example.
 
You could start by checking if you get the same slow wake up with the basic alsa tools like arecord and alsaloop.
I'm Sorry to keep you waiting, but I've had a really busy week.

I also tested combinations of settings and found out that I have had a wrong output format in Windows audio settings. Matching the setting with what is configured on CamillaDSP will improve wake-up time dramatically. I was previously testing how low latency I can get by reducing chunksize and increasing sampling format to 96 kHz. My Windows was still set on 48 kHz, which added latency to an unknown part of the audio chain. It doesn't matter much which sample rate I use as long as it's identical on both sending and receiving end. With this I can hear almost all of the Windows test sound and other random notice sounds I get when working. Bit depth format didn't have any perceivable effect. I'm using 32-bit because that's the only option Windows is showing me.

Changing capture device and playback device "device" selection had little to no effect, but I wonder if there is a preferred option to use. My current options are as follows and I have selected the ones that starts with "hw:".
Bash:
$ arecord -L
null
    Discard all samples (playback) or generate zero samples (capture)
hw:CARD=UAC2Gadget,DEV=0
    UAC2_Gadget, UAC2 PCM
    Direct hardware device without any conversions
plughw:CARD=UAC2Gadget,DEV=0
    UAC2_Gadget, UAC2 PCM
    Hardware device with all software conversions
default:CARD=UAC2Gadget
    UAC2_Gadget, UAC2 PCM
    Default Audio Device
sysdefault:CARD=UAC2Gadget
    UAC2_Gadget, UAC2 PCM
    Default Audio Device
dsnoop:CARD=UAC2Gadget,DEV=0
    UAC2_Gadget, UAC2 PCM
    Direct sample snooping device
Bash:
$ aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
hw:CARD=sndrpihifiberry,DEV=0
    snd_rpi_hifiberry_dac, HifiBerry DAC HiFi pcm5102a-hifi-0
    Direct hardware device without any conversions
plughw:CARD=sndrpihifiberry,DEV=0
    snd_rpi_hifiberry_dac, HifiBerry DAC HiFi pcm5102a-hifi-0
    Hardware device with all software conversions
default:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dac, HifiBerry DAC HiFi pcm5102a-hifi-0
    Default Audio Device
sysdefault:CARD=sndrpihifiberry
    snd_rpi_hifiberry_dac, HifiBerry DAC HiFi pcm5102a-hifi-0
    Default Audio Device
dmix:CARD=sndrpihifiberry,DEV=0
    snd_rpi_hifiberry_dac, HifiBerry DAC HiFi pcm5102a-hifi-0
    Direct sample mixing device

I still do get a lot of log warnings, below.
2025-08-29 17:52:47.177157 INFO [src/alsadevice.rs:798] Capture device supports rate adjust
2025-08-29 17:52:47.345535 INFO [src/alsadevice.rs:976] Capture device is stalled, processing is stalled
2025-08-29 17:52:51.643371 INFO [src/alsadevice.rs:117] PB: Starting playback from Prepared state
I also noticed that CamillaGUI will often display a varying sample rate in "Capt. samplerate" when there is a samplerate mismatch with Windows. It sometimes displays anything between 16k to 96k and sometimes blank.

By the way, as far as I know, DSP filters need to be calculated specific to an audio format and sample rate. That is, a filter (coefficients/biquads) that are made for 48 kHz filter will not work as expected with any other sample rate. CamillaDSP can change samplerate almost on the fly when chaning settings. How does it manage filter? Is it recalculating filters when settings are changed?

Whenever camilladsp.service is runnning on my RPi, speaker-test and alsaloop will display error: "Device or resource busy".
$ speaker-test --device default:CARD=sndrpihifiberry --test pink --period 1000000 --channels 2 --rate 96000 --format S32_LE

speaker-test 1.2.8

Playback device is default:CARD=sndrpihifiberry
Stream parameters are 96000Hz, S32_LE, 2 channels
Using 16 octaves of pink noise
Playback open error: -16,Device or resource busy

For reference here is the config that I'm now using.
YAML:
description: 'Audiophonics DAC HAT to W4 speakers.

  Filters to optimize the W4 performance.'
devices:
  adjust_period: null
  capture:
    channels: 2
    device: hw:CARD=UAC2Gadget,DEV=0
    format: S32LE
    labels: null
    link_mute_control: null
    link_volume_control: null
    stop_on_inactive: null
    type: Alsa
  capture_samplerate: 96000
  chunksize: 2048
  enable_rate_adjust: true
  multithreaded: null
  playback:
    channels: 2
    device: hw:CARD=sndrpihifiberry,DEV=0
    format: S32LE
    type: Alsa
  queuelimit: null
  rate_measure_interval: null
  resampler: null
  samplerate: 96000
  silence_threshold: -75
  silence_timeout: 10
  stop_on_rate_change: null
  target_level: null
  volume_limit: null
  volume_ramp_time: 50
  worker_threads: null
filters:
  LPF1k:
    description: null
    parameters:
      freq: 1000
      q: 0.5
      type: Lowpass
    type: Biquad
  W4-fix1:
    description: null
    parameters:
      freq: 7500
      gain: 8
      q: 2
      type: Peaking
    type: Biquad
  W4-fix2:
    description: null
    parameters:
      freq: 13000
      gain: 6
      q: 2
      type: Peaking
    type: Biquad
  W4-fix3:
    description: null
    parameters:
      freq: 1000
      gain: 2
      q: 0.25
      type: Peaking
    type: Biquad
  W4-global-HPF1:
    description: null
    parameters:
      freq: 20
      type: HighpassFO
    type: Biquad
  W4-global-HPF2:
    description: null
    parameters:
      freq: 25
      order: 4
      type: LinkwitzRileyHighpass
    type: BiquadCombo
  W4-testing:
    description: null
    parameters:
      freq: 5000
      gain: 0
      q: 0.5
      type: Peaking
    type: Biquad
mixers:
  W4-mixer:
    channels:
      in: 2
      out: 2
    description: null
    labels: null
    mapping:
    - dest: 0
      mute: false
      sources:
      - channel: 0
        gain: -10
        inverted: false
        mute: false
        scale: dB
    - dest: 1
      mute: false
      sources:
      - channel: 1
        gain: -10
        inverted: false
        mute: false
        scale: dB
pipeline:
- bypassed: null
  description: null
  name: W4-mixer
  type: Mixer
- bypassed: null
  channels: null
  description: null
  names:
  - W4-global-HPF2
  - W4-fix1
  - W4-fix2
  - W4-fix3
  type: Filter
processors: {}
title: Audiophonics-W4
 
@Jukka: I got lost in the thread - how do you link the USB gadget with CDSP?
I mostly resolved the start-up delay issue, but if you are still interested, USB gadget mode should be described in this post: https://www.audiosciencereview.com/...ds/rpi-camilladsp-tutorial.29656/post-1976186 under the bolded USB Gadget mode. That was on my RPi 4B, but I think I followed the same steps on this Zero 2 W that I now use on this setup. There is one exception though, RPi now uses /boot/firmware/config.txt instead of /boot/config.txt. That's now so long ago that I cannot be sure if that's all it took. In that post I linked the web pages that I used to make it work, so they probably contain info that I forgot to add.

I still got one issue with it. It will advertise itself to Windows by the name "Source/Sink". I have not been able to change this text. In /etc/modprobe.d/usb_g_audio.conf I have values for example options g_audio c_srate=44100,48000,88200,96000,176400,192000 c_ssize=4 c_chmask=3 p_chmask=0 iManufacturer="Raspberry" iProduct="CamillaDSP" but no effect. They are displayed in Linux, but not in Windows:
Bash:
$ grep -H '' /sys/module/g_audio/parameters/*
/sys/module/g_audio/parameters/bcdDevice:0
/sys/module/g_audio/parameters/c_chmask:3
/sys/module/g_audio/parameters/c_hs_bint:0
/sys/module/g_audio/parameters/c_srate:44100,48000,88200,96000,176400,192000
/sys/module/g_audio/parameters/c_ssize:4
/sys/module/g_audio/parameters/idProduct:0
/sys/module/g_audio/parameters/idVendor:0
/sys/module/g_audio/parameters/iManufacturer:Raspberry
/sys/module/g_audio/parameters/iProduct:CamillaDSP
/sys/module/g_audio/parameters/iSerialNumber:(null)
/sys/module/g_audio/parameters/p_chmask:0
/sys/module/g_audio/parameters/p_hs_bint:0
/sys/module/g_audio/parameters/p_srate:48000
/sys/module/g_audio/parameters/p_ssize:2
Can you help?
 
Interesting. What sort of setup are you running? While I do testing of all the configurations, the only ones I run for long periods of time are AES input Okto and TOSLINK input MOTU UL Mk5 configurations, both using rather simple IIR at constant 48 kHz.

Michael
I got nothing werid here. I use a SMSL to toslink interface and then connect the interface to toslink of motu UL5, the motu is connected to raspi4b. The filters are simple IIR filters(lx521.4+2xsub).

Here's my config:
 

Attachments

I got nothing werid here. I use a SMSL to toslink interface and then connect the interface to toslink of motu UL5, the motu is connected to raspi4b. The filters are simple IIR filters(lx521.4+2xsub).

Here's my config:

Target level less than chunk size is a bit odd. I’d increase target level to match chunk size and see if that solves it. 256 may be a bit low on chunk size, if increasing the target level doesn’t solve your issue I’d increase chunk size and target level to 512, current default configs use 512 as chunk size for 96 kHz.

Michael
 
You need to set body param to the desired value:
Code:
curl --request POST \
  --url http://<host>:<port>/api/setparam/volume \
  --header 'content-type: text/plain' \
  --data -20

You can find more details for setparam here: views.py
Ok got it thanks.

I figured out how to load a different config like this:
Code:
curl --request POST \
  --url http://10.1.0.63:5005/api/setparam/configname \
  --header 'content-type: text/plain' \
  --data /home/dsp/camilladsp/configs/_dm7_opt2_48c_48p.yml
But then how do I make it active?

Or you could check my home assistant integration for CamillaDSP for a real live example.
I'd like to avoid using HA as a middleman for this if I can. Keep my setup as simple as possible that way.
 
I still got one issue with it. It will advertise itself to Windows by the name "Source/Sink". I have not been able to change this text. In /etc/modprobe.d/usb_g_audio.conf
The usb gadget composite devices are officially configured via configfs , there are many tutorials online for configfs, a script e.g. in https://www.diyaudio.com/community/attachments/rpi_usb_audio_gadet-pdf.1158959/ , properties for the UAC2 function are https://github.com/torvalds/linux/blob/master/Documentation/ABI/testing/configfs-usb-gadget-uac2 . The g_audio module is a hard-coded constructor of a gadget composite device with single function f_uac2 and hard-coded limited subset of parameters. Many of the function configuration params are not cloned to module params of the g_audio module. The subsystem maintainer specifically keeps the params set limited as the module is deprecated and rejects proposals for new module params - configfs is the supported and recommended method for creating usb gadgets. IMO that is a correct approach.
 
I figured out how to load a different config like this:
Code:
curl --request POST \
  --url http://10.1.0.63:5005/api/setparam/configname \
  --header 'content-type: text/plain' \
  --data /home/dsp/camilladsp/configs/_dm7_opt2_48c_48p.yml
But then how do I make it active?
I've been playing with this more. According to routes.py I should be able to set the config via api/setactiveconfigfile:
Code:
curl --request POST \
  --url http://10.1.0.63:5005/api/setactiveconfigfile \
  --header 'content-type: text/plain' \
  --data /home/dsp/camilladsp/configs/_dm7_opt2_48c_48p.yml
but that just gives me an error:
500 Internal Server Error

Server got itself in trouble%
 
I've been playing with this more. According to routes.py I should be able to set the config via api/setactiveconfigfile:
Code:
curl --request POST \
  --url http://10.1.0.63:5005/api/setactiveconfigfile \
  --header 'content-type: text/plain' \
  --data /home/dsp/camilladsp/configs/_dm7_opt2_48c_48p.yml
but that just gives me an error:
The setactiveconfigfile API endpoint wants a JSON structure like this:
Code:
{ "name": "<path-to-config-file>/<filename>" }

Then you would also need to set a different content-type: application/json

Unfortunately I think there is no documentation for the backend API. But you can check the behaviour in views.py
 
Back
Top Bottom