SuperPlayer - The DSP_Engine (CamillaDSP) samplerate switching & ESP32 remote control

Ohh.... okay...

Try to follow my guide here : Link!

Depending on the DAC you use which is the playback device aka' "sound_out", try to adjust the "sound_out" format.
This can be tricky, as it's depending on the DAC hardware!

E.g. i use this for a little Chineese streamer i have
device: "sound_out"
format: S24LE3

There are a lot of options for output setting see here : Link!

View attachment 1077228

Jesper.
Hi Jesper! What do I use and how to edit ( cdsp_template.yml ) the file we must edit to our need's (filter's, EQ's, gain, volume etc...)

Stig Erik
 
The GUI is up to v1.0.1 now. Is there any chance of a new tcz file coming?

Also, I can't get the camilladsp.log file to work (CDSP in not running). I tried editing the camillagui.yml file to point to the /mnt/mmcblk0p2... location with no luck. The GUI seems to work fine. I have device settings from a working RPi/Ubuntu server install with same playback device (MOTU M4).
devices_pcp.png
 
Last edited:
Hi there @chuckt62 and happy newyear...

EDIT:: Regarding the issue you have with the .log file, i never tested that, so it's a bit hard to help here :)

I did not test this, but did you try to just install the new backend https://github.com/HEnquist/camillagui-backend
Eventhrough that pycamilladsp-plot is now version v1.0.2 and the one here is v1.0.1 it might just work ?

I do not know if i will update this repo. anymore as i see an demand for the 64bit piCorePlayer dist. - I donno if i ever will ?
If you could just try to upgrade the backend and report back here, if or depending how that goes i might create a pycamilladsp-plot-v1.0.2.tcz

Good luck!

Jesper.
 
Hey...
how are you running camilldsp at startup?
It depends if you use the python or the alsa plugin.
The py-cdsp way, it's started "piped" directly to camilladsp through an init script (/usr/local/etc/init.d/squeezelite-cdsp) - Camilladsp is started from this script also.
Camilladsp is handled by the scripple alsa-cdsp plugin when using the "native" way.

It's my gamechanger which handles which of them are started.

/opt/bootlocal.sh ::
# SuperPlayer ------
sudo SuperPlayer-GameChanger py-cdsp > /dev/null 2>&1
#sudo SuperPlayer-GameChanger alsa-cdsp > /dev/null 2>&1
camillagui > /dev/null 2>&1 &
# SuperPlayer ------

Hope this helps.

Jesper
 
I'm using the alsa_cdsp version of your plugin. I've got a script running that will let you modify the filters in the CamillaDSP gui and then automatically generate a template. But the template only gets translated and applied to the active config when the sample rate changes.
What I want to know is: is there a way to force the samplerate changer to do its stuff (make the necessary substitutions in the template and store that as the active config, then restart camilladsp)? I could do this by restarting squeezelite with sudo SuperPlayer-GameChanger alsa-cdsp, but is there a more elegant method?
 
Hi @charlesky

I don't think there is a more elegant way of doing this, than the way you allready do now. -Just need a faster way doing it !
When you execute the sudo SuperPlayer-GameChanger alsa-cdsp, everything is restarted for the native alsa-cdsp way of doing this stuff.

I never did any experiementation with an fast restart, but you can properly do something through the Camilladsp commands.
Maybee try to reload the config through Camilladsp's interface.
You can look at the python script which are loaded when using the py-cdsp way of doing the samplerate changes and maybee use part of it for your'e own script?
The py-cdsp is located in /usr/local/bin

Good luck.
Jesper.
 
Thanks. Yes, that shows how to do it and get camilladsp to reload its config through the websocket. It looks like the easiest route is through python, since that's installed already. I still need to do some more testing, but will write it all up when I'm done in case anyone wants to try it.
 
  • Like
Reactions: 1 user
Well, it looks like it's working (as in, nothing crashed and burned because I made a typo or forgot a tiny-yet-crucial detail).

My aim was to be able to edit the camilladsp config in the gui and then load the changed config into camilladsp and automatically apply it to the template file so it will survive a change in sample rate.

I'm using the alsa_cdsp version of the plugin, but have coded the script so it should work with the python version as well.

My asound.conf is this:
Code:
#    --- sound_out is the real hardware card ---
#    --- SuperPlayer default ---
pcm.sound_out {
type hw
card 0
device 0
}

ctl.sound_out {
type hw
card 0
}

#   --- CamillaDSP with Seashell's alsa-plugin ---
# Howto here : https://github.com/scripple/alsa_cdsp
pcm.camilladsp {
    type cdsp
      cpath "/usr/local/bin/camilladsp"
      config_in "/home/tc/camilladsp/alsa_cdsp_template.yml"
      config_out "/home/tc/camilladsp/camilladsp.yml"
      cargs [
        -o "/home/tc/camilladsp/camilladsp.log"
        -l warn
        -p "1234"
      ]
      channels 2
      rates = [
        44100
        48000
        88200
        96000
        176400
        192000
        352800
        384000
      ]
      extra_samples 0
}

To get the active config mechanism working in camillagui, create a symbolic link in the camilladsp folder. For alsa_cdsp:
ln -s ~/camilladsp/camilladsp.yml ~/camilladsp/camilladsp_active.yml
For py_cdsp:
ln -s ~/camilladsp/cdsp_template_active.yml ~/camilladsp/camilladsp_active.yml

Now enter
nano /mnt/mmcblk0p2/tce/Camilla_Extensions/camillagui/config/camillagui.yml
clear everything and paste in the following. For alsa_cdsp:
Code:
---
camilla_host: "127.0.0.1"
camilla_port: 1234
port: 5000
config_dir: "~/camilladsp/configs"
coeff_dir: "~/camilladsp/coeffs"
default_config: "~/camilladsp/camilladsp.yml"
active_config: "~/camilladsp/camilladsp_active.yml"
active_config_txt: "~/camilladsp/active_config.txt"
log_file: "~/camilladsp/camilladsp.log"
update_config_symlink: true
on_set_active_config: /home/tc/camilladsp/processTemplate.sh alsacdsp {}
on_get_active_config: null
supported_capture_types: null
supported_playback_types: null
for py_cdsp:
Code:
---
camilla_host: "127.0.0.1"
camilla_port: 1234
port: 5000
config_dir: "~/camilladsp/configs"
coeff_dir: "~/camilladsp/coeffs"
default_config: "~/camilladsp/cdsp_template_active.yml"
active_config: "~/camilladsp/camilladsp_active.yml"
active_config_txt: "~/camilladsp/active_config.txt"
log_file: "~/camilladsp/camilladsp.log"
update_config_symlink: true
on_set_active_config: /home/tc/camilladsp/processTemplate.sh pycdsp {}
on_get_active_config: null
supported_capture_types: null
supported_playback_types: null
Note: This just sets the default config to whatever you're currently using. You may want to change the default_config line to use the path of a baseline config in your configs folder.

Now enter
nano ~/camilladsp/processTemplate.sh
and paste in the following:
Code:
#!/bin/sh

switch="$1"
newConfig="$2"

if [ -z "$newConfig" -o ! -f "$newConfig" ]
then
    exit 1
fi

case "$switch" in
    alsacdsp)
        ReplaceSR="\$samplerate\$"
        ReplaceFormat="\$format\$"
        ReplaceChannels="\$channels\$"
        ReplaceES="\$extrasamples\$"
        ReplaceChunk=""
        Template="/home/tc/camilladsp/alsa_cdsp_template.yml"
        Active="/home/tc/camilladsp/camilladsp.yml"
        ;;
    pycdsp)
        ReplaceSR="<<sample_rate>>"
        ReplaceChunk="<<chunk_size>>"
        ReplaceFormat=""
        ReplaceChannels=""
        ReplaceES=""
        Template="/home/tc/camilladsp/cdsp_template.yml"
        Active="/home/tc/camilladsp/cdsp_template_active.yml"
        ;;
    *)
        exit 1
        ;;
esac

tmpfile="/home/tc/camilladsp/tmpConfig.yml"

cp "$newConfig" "$tmpfile"

sed -i -r "s/samplerate: [[:digit:]]+/samplerate: $ReplaceSR/g" "$tmpfile"

if [ ! -z $ReplaceFormat ]
then
    sed -i -r "s/format: [A-Z0-9]+/format: $ReplaceFormat/g" "$tmpfile"
fi

if [ ! -z $ReplaceChannels ]
then
    sed -i -r "s/channels: [[:digit:]]+/channels: $ReplaceChannels/g" "$tmpfile"
fi

if [ ! -z $ReplaceES ]
then
    sed -i -r "s/extra_samples: [[:digit:]]+/extra_samples: $ReplaceES/g" "$tmpfile"
fi

if [ ! -z $ReplaceChunk ]
then
    sed -i -r "s/chunksize: [[:digit:]]+/chunksize: $ReplaceChunk/g" "$tmpfile"
fi

cp "$tmpfile" "$Template"
rm -f "$tmpfile"

# Now set the new config as active in camilladsp. Port number is set in reloadCamilla.py to the default for camillagui
cp "$newConfig" "$Active"
python3.8 /home/tc/camilladsp/reloadCamilla.py "$Active"

pcp bu
Save and exit.
Then enter
nano ~/camilladsp/restartCamilla.py
and paste in the following:
Code:
#!/usr/local/bin/python3

import sys
from websocket import create_connection

ws_port = "1234"

send_cfg = '{"SetConfigName": "' + sys.argv[1] + '"}'
# print (send_cfg)
ws = create_connection("ws://127.0.0.1:" + ws_port)
ws.send(send_cfg)
ws.recv()
ws.send('"Reload"')
ws.recv()
ws.close()
Save and exit again.

Set these files as executable:
Code:
chmod a+x processTempate.sh
chmod a+x reloadCamilla.py

Last and by no means least, back everything up so it doesn't all vanish:
pcp bu

Now reboot piCorePlayer.

Open CamillaGui via http://<ip address of yourRPi>:5000
It should load with the current config being run by camilladsp. Create a new config in the Files tab, make some changes in the gui and save them to the new file via the floppy-disk icon (for anyone under 30: the one in the middle :) ), then click on the 'A' icon at the left. Your changes should now be saved and loaded into camilladsp in a way that will survive changes in samplerate.

I've tested this (though only on the alsa_cdsp version) and it all seems to work. But please test it and check if I've messed anything up. I recommend making a backup image of your pCP first (Main tab of pCP web page->Additional functions->SD Card Image) and storing it somewhere safe so you can reflash if anything goes wrong.

[Edit] I started out writing this as a shell script and the Python script is a late addition made when I realised it's the easiest way to communicate with the camilladsp process. I should probably rewrite the whole thing as a single Python script to make it easier, but I want to test it more extensively first.
 
Last edited:
  • Like
Reactions: 1 users
Ok, here's the updated version which actually works properly - my first attempt wasn't triggering the alsacdsp callback, so camilla ended up running at the wrong samplerate.
I ended up having to use sudo :confused::cry::cry::confused: to restart squeezelite. Sadly that was the only way I could find to trigger the callback.

The aim is to be able to edit the camilladsp config in the gui and then load the changed config into camilladsp and automatically apply it to the template file so it will survive a change in sample rate.

I'm using the alsa_cdsp version of the plugin, but have coded the script so it should work with the python version as well.

My asound.conf is this:
Code:
#    --- sound_out is the real hardware card ---
#    --- SuperPlayer default ---
pcm.sound_out {
type hw
card 0
device 0
}

ctl.sound_out {
type hw
card 0
}

#   --- CamillaDSP with Seashell's alsa-plugin ---
# Howto here : https://github.com/scripple/alsa_cdsp
pcm.camilladsp {
    type cdsp
      cpath "/usr/local/bin/camilladsp"
      config_in "/home/tc/camilladsp/alsa_cdsp_template.yml"
      config_out "/home/tc/camilladsp/camilladsp.yml"
      cargs [
        -o "/home/tc/camilladsp/camilladsp.log"
        -l error
        -p "1234"
      ]
      channels 2
      rates = [
        44100
        48000
        88200
        96000
        176400
        192000
        352800
        384000
      ]
      extra_samples 0
}

To get the active config mechanism working in camillagui, create a symbolic link in the camilladsp folder. For alsa_cdsp:
ln -s ~/camilladsp/camilladsp.yml ~/camilladsp/camilladsp_active.yml
For py_cdsp:
ln -s ~/camilladsp/cdsp_template_active.yml ~/camilladsp/camilladsp_active.yml

Now enter
nano /mnt/mmcblk0p2/tce/Camilla_Extensions/camillagui/config/camillagui.yml
clear everything and paste in the following. For alsa_cdsp:
Code:
---
camilla_host: "127.0.0.1"
camilla_port: 1234
port: 5000
config_dir: "~/camilladsp/configs"
coeff_dir: "~/camilladsp/coeffs"
default_config: "~/camilladsp/camilladsp.yml"
active_config: "~/camilladsp/camilladsp_active.yml"
active_config_txt: "~/camilladsp/active_config.txt"
log_file: "~/camilladsp/camilladsp.log"
update_config_symlink: true
on_set_active_config: /home/tc/camilladsp/processTemplate.sh alsacdsp {}
on_get_active_config: null
supported_capture_types: null
supported_playback_types: null
for py_cdsp:
Code:
---
camilla_host: "127.0.0.1"
camilla_port: 1234
port: 5000
config_dir: "~/camilladsp/configs"
coeff_dir: "~/camilladsp/coeffs"
default_config: "~/camilladsp/cdsp_template_active.yml"
active_config: "~/camilladsp/camilladsp_active.yml"
active_config_txt: "~/camilladsp/active_config.txt"
log_file: "~/camilladsp/camilladsp.log"
update_config_symlink: true
on_set_active_config: /home/tc/camilladsp/processTemplate.sh pycdsp {}
on_get_active_config: null
supported_capture_types: null
supported_playback_types: null
Note: This just sets the default config to whatever you're currently using. You may want to change the default_config line to use the path of a baseline config in your configs folder.

Now enter
nano ~/camilladsp/processTemplate.sh
and paste in the following:
Code:
#!/bin/sh

switch="$1"
newConfig="$2"

if [ -z "$newConfig" -o ! -f "$newConfig" ]
then
    echo "processTemplate.sh called with incorrect config file $newConfig"  >> /home/tc/camilladsp/camilladsp.log
    exit 1
fi

case "$switch" in
    alsacdsp)
        ReplaceSR="\$samplerate\$"
        ReplaceFormat="\$format\$"
        ReplaceChannels="\$channels\$"
        ReplaceES="\$extrasamples\$"
        ReplaceChunk=""
        Template="/home/tc/camilladsp/alsa_cdsp_template.yml"
        Active="/home/tc/camilladsp/camilladsp.yml"
        ;;
    pycdsp)
        ReplaceSR="<<sample_rate>>"
        ReplaceChunk="<<chunk_size>>"
        ReplaceFormat=""
        ReplaceChannels=""
        ReplaceES=""
        Template="/home/tc/camilladsp/cdsp_template.yml"
        Active="/home/tc/camilladsp/cdsp_template_active.yml"
        ;;
    *)
        echo "processTemplate.sh can't recognise switch $switch"  >> /home/tc/camilladsp/camilladsp.log
        exit 1
        ;;
esac

tmpfile="/home/tc/camilladsp/tmpConfig.yml"

# tr hack to do multi-line search in sed
# This is necessary because we ONLY want to tokenise the capture format, and not the output format.
# Because of this, the capture section of the config file MUST be ordered as so:
#  capture:
#    ...
#    filename: /dev/stdin
#    format: S32LE [or whatever]
#    ...
# This is the default when creating a new blank config and setting capture to File and filename to /dev/stdin
if [ ! -z $ReplaceFormat ]
then
    cat "$newConfig" | tr '\n' '\r' | sed -r -e "s/filename: \/dev\/stdin\r\s+format: [A-Z0-9]+/filename: \/dev\/stdin\r    format: $ReplaceFormat/g" | tr '\r' '\n' > "$tmpfile"
fi

sed -i -r "s/[^_]samplerate: [[:digit:]]+/ samplerate: $ReplaceSR/g" "$tmpfile"

if [ ! -z $ReplaceChannels ]
then
    sed -i -r "s/channels: [[:digit:]]+/channels: $ReplaceChannels/g" "$tmpfile"
fi

if [ ! -z $ReplaceES ]
then
    sed -i -r "s/extra_samples: [[:digit:]]+/extra_samples: $ReplaceES/g" "$tmpfile"
fi

if [ ! -z $ReplaceChunk ]
then
    sed -i -r "s/chunksize: [[:digit:]]+/chunksize: $ReplaceChunk/g" "$tmpfile"
fi

cp "$tmpfile" "$Template"
rm -f "$tmpfile"

# Now set the new config as active in camilladsp and restart squeezelite.
# Sadly, this requires sudo, but I can't see any other way to trigger the hw_params callback for alsacdsp.

cp "$newConfig" "$Active" # possibly not needed as it will be rebuilt on the restart.

case "$switch" in
    alsacdsp)
        sudo /usr/local/etc/init.d/squeezelite restart >> /home/tc/camilladsp/camilladsp.log 2>&1
        ;;
    pycdsp)
        sudo /usr/local/etc/init.d/squeezelite-cdsp restart >> /home/tc/camilladsp/camilladsp.log 2>&1
        ;;
esac

pcp bu
Save and exit.

Set this file as executable:
chmod a+x ~/camilladsp/processTempate.sh

Last and by no means least, back everything up so it doesn't all vanish:
pcp bu

Now reboot piCorePlayer.

Important Note:
If using alsacdsp, then the capture section of your config file must look like this:
Code:
devices:
  ...
  capture:
    ...
    filename: /dev/stdin
    format: [whatever]
    ...
This is the default when creating a new blank config in camillagui and setting capture device to File and filename to /dev/stdin, so this shouldn't be a problem. It's a hack, but it's the only way I could work out to make sure only the capture format is tokenised.

The script writes messages to ~/camilladsp/camilladsp.log rather than litter the directory with its own separate log file. But if you want these to get through you'll need to enable writing to this file with
sudo chmod a+w ~/camilladsp/camilladsp.log

Open CamillaGui via http://<ip address of yourRPi>:5000
It should load with the current config being run by camilladsp. Create a new config in the Files tab, make some changes in the gui and save them to the new file via the floppy-disk icon (for anyone under 30: the one in the middle :) ), then click on the 'A' icon at the left. Your changes should now be saved and loaded into camilladsp in a way that will survive changes in samplerate.

I've tested this (though only on the alsa_cdsp version) and it all seems to work. But please test it and check if I've messed anything up. I recommend making a backup image of your pCP first (Main tab of pCP web page->Additional functions->SD Card Image) and storing it somewhere safe so you can reflash if anything goes wrong.

As I said, I'm running the alsacdsp version. It would be helpful if anyone running pycdsp could test it out and see if it works (I'm pretty sure it should) - that would save me having to switch everything around to test.

Feel free to use this any way you want. If you want to incorporate it into the repository (with any modifications you want) that would be cool.
 
Last edited:
Hey,
does the last v8 release also work with with pCP 8.1?

I want to give it a try to bring FIR phase correction to my Hypex speakers, add the missing tone controls as three presets do not cover the variety of productions I listen to and move room correction from the internal Hypex filters to the Raspberry, so to free the internally available filters and use them for the crossover instead.

Btw, someone build a remote based on a cheap AliExpress-able ZigBee turning knob that can volume and tone control:
https://www.audiosciencereview.com/...r-raspberry-pi-help-needed-with-python.40320/
 
I've been playing around with impulse response convolution and discovered a quirk in CamillaGUI that needs to be worked around. Even if you specify the absolute path to the impulse response in your config file, the GUI will translate that to a relative path (relative to the location of the config when you load it in) and if you edit the config in the GUI and then save, the saved file will contain that relative path.

This means that, if you're using my script to allow you to edit configs in the GUI and then automatically generate a template file, you must locate both the template and final config files in the same directory as the root configs that you want to be able to edit (i.e. ~camilladsp/configs). Failure to do this will result in camilladsp crashing with a 'file not found' error.

This is easily done if using the modded alsa module. Move the relevant files (camilladsp.yml and alsa_cdsp_template.yml) to ~camilladsp/configs, recreate the active_config link ln -s ~/camilladsp/configs/camilladsp.yml ~/camilladsp/configs/camilladsp_active.yml, and make the following changes:

/etc/asound.conf:
Code:
#    --- sound_out is the real hardware card ---
#    --- SuperPlayer default ---
pcm.sound_out {
type hw
card 0
device 0
}

ctl.sound_out {
type hw
card 0
}

#   --- CamillaDSP with Seashell's alsa-plugin ---
# Howto here : https://github.com/scripple/alsa_cdsp
pcm.camilladsp {
    type cdsp
      cpath "/usr/local/bin/camilladsp"
      config_in "/home/tc/camilladsp/configs/alsa_cdsp_template.yml"
      config_out "/home/tc/camilladsp/configs/camilladsp.yml"
      cargs [
        -o "/home/tc/camilladsp/camilladsp.log"
        -l error
        -p "1234"
      ]
      channels 2
      rates = [
        44100
        48000
        88200
        96000
        176400
        192000
        352800
        384000
      ]
      extra_samples 0
}

The case statement near the top of ~camilladsp/processTemplate.sh needs the following change:
Code:
case "$switch" in
    alsacdsp)
        ReplaceSR="\$samplerate\$"
        ReplaceFormat="\$format\$"
        ReplaceChannels="\$channels\$"
        ReplaceES="\$extrasamples\$"
        ReplaceChunk=""
        Template="/home/tc/camilladsp/configs/alsa_cdsp_template.yml"
        Active="/home/tc/camilladsp/configs/camilladsp.yml"
        ;;

Finally, edit /mnt/mmcblk0p2/tce/Camilla_Extensions/camillagui/config/camillagui.yml and replace the following lines:
Code:
default_config: "~/camilladsp/configs/camilladsp.yml"
active_config: "~/camilladsp/configs/camilladsp_active.yml"

Unfortunately, it looks like the python script method has the location of the template and active configs hardcoded into the python script buried in the .tcz, which means that changing them would require unsquashing the .tcz, making the changes to the script and then resquashing it and rebooting. It would be possible to get around this by adding some extra regexp logic to processTemplate.sh in order to modify any relative paths in the config file. If anyone's actually using my script with the python method let me know and I'll look into making such a change.

Final note: Moving the template and active config files to the configs directory means that they will show up in the 'Files' section in CamillaGUI. It is best that you do not attempt to edit these files directly, as they're both automatically generated. Just leave them alone and pretend they aren't there. ;)
Also: this whole thing is only an issue if you're using impulse-response convolution, in which the config file has to contain the paths to the IR files. If you're just using parametric ('Biquad') filters then you don't need to bother.
 
Last edited:
I installed Superplayer-Gamechanger and CamillaGUI on a Raspberry Pi 3 running piCorePlayer 8.2.0 32-bit. The audio output device is a DAC hat based on AK4493.
I cannot get camilladsp to work, as it always remains in the INACTIVE state. I have tried with a python script to read the current configuration (get_config()), it is always None, while the previous configuration (get_previous_config()) seems fine. The function get_stop_reason() returns StopReason.PLAYBACKERROR.

Note: I installed superplayer and camillagui on a Raspberry Pi 4 with piCorePlayer 8.2.0 32-bit with an external USB DAC, and everything works as expected.

I need some help. thank you.
 
Sounds like camilladsp isn’t seeing your DAC. Can you post the output of aplay -l and the contents of /etc/asound.conf.

Output of aplay -l
Code:
**** List of PLAYBACK Hardware Devices ****
card 0: Headphones [bcm2835 Headphones], device 0: bcm2835 Headphones [bcm2835 Headphones]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 1: sndrpirpidac [snd_rpi_rpi_dac], device 0: RPi-DAC HiFi pcm1794a-codec-0 [RPi-DAC HiFi pcm1794a-codec-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

/etc/asound.conf
Code:
#    --- sound_out is the real hardware card ---
#    --- SuperPlayer default ---
pcm.sound_out {
   type hw
   card sndrpirpidac
   device 0
}

ctl.sound_out {
   type hw
   card sndrpirpidac
}


Note that the standard squeezeplay works perfectly setting sndrpipidac as output device.