Sample rate switcher for CamillaDSP

I have just uploaded camilladsp-setrate v2.2.1.
This version fixes the issue reported by @TerryForsythe. I also took on board the hints from @phofman and @gordoste.
In the "Final notes" section of the README.md file I provided information about the maximum size of the configuration file camilladsp-setrate can handle and how to increase that size.

https://github.com/marcoevang/camilladsp-setrate
 
  • Like
Reactions: TerryForsythe
I am working on a new camilladsp-setrate feature and need to know the maximum sampling rate supported by the playback device.
I found a solution by invoking the function snd_pcm_hw_params_any, but this solution requires the playback device to be not busy. Unfortunately, the device is usually already in use by camilladsp, so the solution does not actually work.

Do you have any suggestions on how to find out the maximum sample rate supported by an audio device that is already being used by another process?
The solution should assume the use of the alsa sound system.
 
  • Like
Reactions: TerryForsythe
Do you have any suggestions on how to find out the maximum sample rate supported by an audio device that is already being used by another process?
I have looked for this too, to make it easy to pick supported sample rate and format in the gui. Unfortunately I have not found any general solution via the Alsa api. Some drivers present info in various files in /proc etc, but that really varies from driver to driver so this gets pretty clunky.
 
I found a solution by invoking the function snd_pcm_hw_params_any, but this solution requires the playback device to be not busy. Unfortunately, the device is usually already in use by camilladsp, so the solution does not actually work.
CDSP reports the hw params into log, before starting operation. Maybe you could read this info. If a device is already busy, it's hard to query it.
 
@HenrikEnquist , @phofman thank you for your commens.

CDSP reports the hw params into log, before starting operation.
camilladsp reports supported samplerates at loglevel debug only. I would prefer if the solution did not flood the log file, but that is a viable option.

I am also considering programming the systemd services so that camilladsp starts with a small delay. This way camilldsp-setrate can open the playback device, read its maximum sample rate, and release it immediately afterwards for use by camilladsp. But even this solution is invasive on camilladsp's operating environment.
 
If possible capture and store the max rate during boot for example by placing the command in the file /etc/rc.local

Code:
pi@moode9:~ $ alsacap 2>&1 | awk -F"." '/sampling rate/ {print $3}' | cut -d" " -f1 > /tmp/maxrate.txt
pi@moode9:~ $ cat /tmp/maxrate.txt
384000

Code:
# Full alsacap output for playback device. Use -R for recording device.

pi@moode9:~ $ alsacap
*** Scanning for playback devices ***
Card 0, ID `vc4hdmi0', name `vc4-hdmi-0'
  Device 0, ID `MAI PCM i2s-hifi-0', name `MAI PCM i2s-hifi-0', 1 subdevices (1 available)
Error opening sound device for card 0, device 0: Unknown error 524.  Skipping.
Card 1, ID `vc4hdmi1', name `vc4-hdmi-1'
  Device 0, ID `MAI PCM i2s-hifi-0', name `MAI PCM i2s-hifi-0', 1 subdevices (1 available)
Error opening sound device for card 1, device 0: Unknown error 524.  Skipping.
Card 2, ID `BossDAC', name `BossDAC'
  Device 0, ID `Boss DAC HiFi [Master] pcm512x-hifi-0', name `Boss DAC HiFi [Master] pcm512x-hifi-0', 1 subdevices (1 available)
    2 channels, sampling rate 8000..384000 Hz
    Sample formats: S16_LE, S24_LE, S32_LE
    Buffer size range from 32 to 131072
    Period size range from 16 to 1024

      Subdevice 0, name `subdevice #0'
 
@HenrikEnquist , @phofman thank you for your commens.


camilladsp reports supported samplerates at loglevel debug only. I would prefer if the solution did not flood the log file, but that is a viable option.
Well, it's trivial to change that log to warning, or modify as needed (e.g. to write to some file) and recompile, if needed. In fact recompiling rust is much easier (I would say trivial again) compared to other languages, as rust downloads everything needed (plus the alsa-lib dev headers package).
I am also considering programming the systemd services so that camilladsp starts with a small delay. This way camilldsp-setrate can open the playback device, read its maximum sample rate, and release it immediately afterwards for use by camilladsp. But even this solution is invasive on camilladsp's operating environment.
I do not know exactly your use case. But the USB gadget usage should start capturing with minimum delay possible after the rate change is detected, to minimize loosing initial samples.
 
@TimCurtis, I'll try the technique you suggest. Thank you.

Well, it's trivial to change that log to warning,
Besides my own use, the new feature might be of interest to some other users who have downloaded the software from github. I would not want to ask them to recompile camilladsp, just as I would not want to ask them to change their camilladsp operating environment.

I do not know exactly your use case. But the USB gadget usage should start capturing with minimum delay possible after the rate change is detected, to minimize loosing initial samples.
The delay I am talking about is only applied once when the service camilladsp.service starts, hence before the camilladsp process has started . I could achieve this delay with the clause 'ExecStartPre=/bin/sleep XX' in the unit file.
 
The delay I am talking about is only applied once when the service camilladsp.service starts, hence before the camilladsp process has started .
OK, then it's the same usage as Tim suggests, basically for a static setup where the device maximum samplerate does not change. E.g. alsa loopback device could change its rate, depending on the other side process. But that's probably a minor use case.
I could achieve this delay with the clause 'ExecStartPre=/bin/sleep XX' in the unit file.
Handling proces order with delays may be unreliable in some edge cases - a serial sequence (your check first, then starting CDSP) may be safer.
 
Don't know how important this is here, but may be good to keep in mind. Some devices don't support all sample formats at all sample rates, for example a device may support 24-bit up to some rate one, and only 16 bit above that. I think that's mostly for usb 1 (where bandwidth is quite limited).
A more relevant case may be interfaces with adat. For these it's very common that the number of channels changes with sample rate.
For a modern stereo DAC you probably don't need to worry, it's always 2 channels and supported sample formats are unlikely to depend on sample rate. But for others you may need to handle more than just a change of sample rate.
 
@HenrikEnquist makes a great point.
It depends on what feature you're actually trying to implement (you didn't mention), but you might be better off to try to adjust the sampling rate and then if that fails, just continue using the old sample rate. Hopefully cdsp-setrate can actually detect whether setting the samplerate was successful.
 
Handling proces order with delays may be unreliable in some edge cases - a serial sequence (your check first, then starting CDSP) may be safer.
You are right. Having camilladsp launched by camilladsp-setrate after obtaining the information would be the most reliable solution.

Some devices don't support all sample formats at all sample rates
I hadn't considered that. It is probably not possible to find a general solution that is valid for all contexts.

It depends on what feature you're actually trying to implement (you didn't mention), but you might be better off to try to adjust the sampling rate and then if that fails, just continue using the old sample rate. Hopefully cdsp-setrate can actually detect whether setting the samplerate was successful.
camilladsp-setrate changes the sample rate in the camilladsp configuration and checks if this setting is successful. An error for unsupported samplerate would probably only be discovered when camilladsp attempts to send an output to the playback device (@HenrikEnquist could confirm).
 
camilladsp-setrate changes the sample rate in the camilladsp configuration and checks if this setting is successful.
If your project is for USB gadget, perhaps the optimal solution would be checking the output soundcard capabilities at boot and loading the gadget function via configfs with corresponding rates.

For now the gadget cannot have multiple altsettings with individual rates + channels+ formats combinations.
 
  • Thank You
Reactions: mevang
camilladsp-setrate changes the sample rate in the camilladsp configuration and checks if this setting is successful. An error for unsupported samplerate would probably only be discovered when camilladsp attempts to send an output to the playback device (@HenrikEnquist could confirm).

Now that we know it will fail on opening the device, we just need to figure out whether it tries to open the device and returns failure to cdsp-setrate, or just checks the config syntax and return success, only to fail later when opening the device.
 
@TerryForsythe,
I am back from my (sadly short) holiday.
would you please send me the configuration file that produces the error? That would help me to speed up debugging.

@gordoste,
thanks for the suggestion, I will keep it in mind.

I have just uploaded camilladsp-setrate v2.2.1.
This version fixes the issue reported by @TerryForsythe. I also took on board the hints from @phofman and @gordoste.
In the "Final notes" section of the README.md file I provided information about the maximum size of the configuration file camilladsp-setrate can handle and how to increase that size.

https://github.com/marcoevang/camilladsp-setrate
Thank you, mevang!!!

I greatly appreciate everyone's help and work on this project and CamillaDSP!!!

I just got back from holiday. 🙂 I installed version 2.2.1 of camilladsp-setrate and it is working with my biquads configuration!!!

The only issue that I run into (in versions 2.2 and 2.2.1) is that the samplerate set in the CamillaDSP configuration file must match the first song that I play. After that, I can change songs with different samplerates and it seems to be working perfectly.
EDIT: I'm not sure if this really is an issue. I just tried it again after re-starting CamillaDSP and camilladsp-setrate worked flawlessly.

Let me know if you need to see any of my log files, configurations, etc.
 
Last edited:
It will fail when setting the hwparams while opening the device.

I use an audio start bash script exactly resorting to this approach:
aplay -D hw:sndrpihifiberry -c2 -f S24_LE -r 192000 -s1 /dev/zero

In case of a parameters match, aplay will open the device, start to play back one single sample (-s1) of zeros (/dev/zero) and then exit again.
if [ $? -eq 0 ]; then ... success case

In case of a non-match, aplay fails.
elif [ $? -eq 1 ]; then ... fail case

This principle also allows to assess all functional parameters variants of a sound card.
 
Last edited:
This principle also allows to assess all functional parameters variants of a sound card.
Yes, it's doable, but there are many combinations to check. I had to end up using this method in WASAPI excl. connector for javaaudio for REW - the combinations run to hundreds/thousands, delaying REW startup.

Unlike WASAPI the alsa hw params interface gives hints for values and ranges of the parameters which can potentially limit the possible combinations significantly. Also using bash and starting the aplay process for each combination is a bit ineffficient, C/Rust code in a single process would likely be orders of magnitude faster.