Sample rate switcher for CamillaDSP

@TerryForsythe ,
I am not an alsa expert, I learnt the bare minimum of the alsa system just to develop my own little software. So if you have problems with alsa, I'm afraid I can't be of much help.
However, please check in the log file produced by camilladsp-setrate (use --loglevel=notice) if alsa has been successfully initialised or the alsa initialization failed for some reason (in both case there should be tracks in the log file). Please let me know the result of this check.
 
When the rate changes the sound distorts.

I just stopped camilla.service, cleared camilladsp.log, and restarted the service. Then I played a song at 96k (played fine), then switched to a song recorded at 41k (played distorted). Then I stopped the service to keep the log short, relatively speaking. The log is attached.

The log indicates "SetSpeed message received", and then indicates everything is "Ok" after that. I'm stumped.
 
@TerryForsythe ,
I am not an alsa expert, I learnt the bare minimum of the alsa system just to develop my own little software. So if you have problems with alsa, I'm afraid I can't be of much help.
However, please check in the log file produced by camilladsp-setrate (use --loglevel=notice) if alsa has been successfully initialised or the alsa initialization failed for some reason (in both case there should be tracks in the log file). Please let me know the result of this check.
Here is a portion of that log:

Mar 20 11:58:31 dspserver camilladsp-setrate[825]: Fatal error: Cannot open alsa control for the device TosLink: No such file or directory
Mar 20 11:58:31 dspserver systemd[1]: camilladsp-setrate.service: Main process exited, code=exited, status=255/EXCEPTION
Mar 20 11:58:31 dspserver systemd[1]: camilladsp-setrate.service: Failed with result 'exit-code'.
Mar 20 11:58:32 dspserver systemd[1]: camilladsp-setrate.service: Scheduled restart job, restart counter is at 5.
Mar 20 11:58:32 dspserver systemd[1]: Stopped camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP.
Mar 20 11:58:32 dspserver systemd[1]: camilladsp-setrate.service: Start request repeated too quickly.
Mar 20 11:58:32 dspserver systemd[1]: camilladsp-setrate.service: Failed with result 'exit-code'.
Mar 20 11:58:32 dspserver systemd[1]: Failed to start camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP.

You previously mentioned using USB Gadget instead of TosLink. Do I set it as "hw:USB Audio"?

EDIT: arecord -l outputs:

** List of CAPTURE Hardware Devices **
card 0: TosLink [MCHStreamer TosLink], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
 
I tried changing the device in Camilla and changing the exec line device in the camilladsp-setrate.service file to the following:

hw:USB Audio
hw:'USB Audio'

Neither worked. No sound came out.

EDIT: The camilladsp-setrate.service log indicates "Fatal error: Cannot open alsa control for the device TosLink: No such file or directory". But, there is a TosLink file at /proc/asound/TosLink.

EDIT 2: The following files also are on my system:

/dev/snd/by-id/usb-miniDSP_MCHStreamer_TosLink_00007-00
/run/udev/links/snd\x2fby-id\x2fusb-miniDSP_MCHStreamer_TosLink_00007-00

Would using one of those files for "hw;" work? Probably not the one in /run. I'll give the other one a shot.

EDIT 3: hw:usb-miniDSP_MCHStreamer_TosLink_00007-00 did not work.
 
Last edited:
Here is a portion of that log:

Mar 20 11:58:31 dspserver camilladsp-setrate[825]: Fatal error: Cannot open alsa control for the device TosLink: No such file or directory
This confirms that the initialisation of the capture device failed. One reason is for sure that you have not prepended the device type "hw:", so please specify "hw:Toslink" as device name (also in the configuration file of CamillaDSP). But other problems may exist.

You previously mentioned using USB Gadget instead of TosLink. Do I set it as "hw:USB Audio"?
No. Using USB Gadget means using the USB-C port of your Raspberry Pi as a peripheral, the same port used to provide power. A splitter is therefore required to separate power from USB data. Moreover, a particular configuration is required. If I remember well, there are good "how to" guides on this forum. The USB gadget works fine as a capture device on a Raspberry Pi 4. I don't know if it works on a Raspberry Pi 5.
 
Last edited:
mevang, I did use "hw:TosLink", both in the camilladsp-setrate.service and camilladsp. Here is the exec line:

ExecStart=/usr/local/bin/camilladsp-setrate --device hw:TosLink --loglevel=notice --syslog

EDIT: I didn't scroll far enough down the log file - my bad. I just noticed the date on what I posted - it was from yesterday when I was trying a bunch of different settings. Here is the latest log entry when I tried changing songs:

Mar 21 20:57:03 dspserver systemd[1]: Stopping camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP...
Mar 21 20:57:03 dspserver systemd[1]: camilladsp-setrate.service: Deactivated successfully.
Mar 21 20:57:03 dspserver systemd[1]: Stopped camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP.
Mar 21 20:57:03 dspserver systemd[1]: Starting camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP...
Mar 21 20:57:03 dspserver systemd[1]: Started camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP.
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: /usr/local/bin/camilladsp-setrate 2.1.0
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: An automatic sample rate switcher for CamillaDSP
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: Finite-state machine initialised
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: LWS: 4.1.6-, loglevel 1031
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: NET CLI SRV H1 H2 WS IPV6-on
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Websocket environment initialised
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Alsa control for the device hw:TosLink initialised
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 31
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 27
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 85
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: A new client websocket instance was created
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 71
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 29
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 24
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 44
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 2
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Connected to websocket server localhost:1234
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Event : CONNECT
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Action : NULL
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: State : WAIT_RATE_CHANGE
 
Last edited:
I tried putting "-d hw:/proc/asound/TosLink" in the exec line of the camilladsp-setrate.service file.
That is not a valid device name.

Before even testing with camilladsp and camilladsp-setrate, check that the audio device names are correct and that those devices are working properly. You can do this as follows:
arecord -f cd -t wav -D <your capture device> | aplay -D <your playback device> &
For example, if your capture device is hw:Toslink and your playback device is hw:MyDAC, try the following:
arecord -f cd -t wav -D hw:Toslink | aplay -D hw:MyDAC &
(your devices must support CD format, i.e. 16 bit 44100 Hz)

If names are correct and your devices work, you should get this output:
Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

If device names are wrong or devices do not work properly, you should get an error message.

(You could also try with the full device name, e.g. hw:CARD=Toslink,DEV=0)
 
I have TosLink input and TosLink output. I confirmed the device names with "arecord -l" and "aplay -l". Thus, I entered:

arecord -f cd -t wav -D hw:TosLink | aplay -D hw:TosLink &

I get the following output:

Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
arecord: set_params:1352: Sample format non available
Available formats:
- S32_LE
aplay: read_header:2912: read error
 
mevang, thank you very, very much for all of your assistance!

Unless the issue is clear to you, don't worry about it.

I'm going to see if I can find out what all of the "Unhandled callback: reason" log entries mean. I'm hoping I can find a list that explains what the different numbers represent.
 
Last edited:
I have TosLink input and TosLink output. I confirmed the device names with "arecord -l" and "aplay -l". Thus, I entered:

arecord -f cd -t wav -D hw:TosLink | aplay -D hw:TosLink &

I get the following output:

Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
arecord: set_params:1352: Sample format non available
Available formats:
- S32_LE
aplay: read_header:2912: read error
Clearly your device does not support the format S16_LE which is hardcoded in the cd format (-f cd). You will need to set all the parameters manually (-r 44100 -f S16_LE -c 2). Parameters available by alsa device are listed e.g. by command

Code:
aplay --dump-hw-params -D DEVICE /dev/zero

Still - does your usb-audio device Toslink have the alsa control "Capture Rate" with notifications enabled as required by the setrate project https://github.com/marcoevang/camil...eaa74275ee773b080ff52b/setrate_alsa.c#L52-L54 ? IIRC there is no such control provided by the snd-usb-audio driver, it's only provided by the USB gadget driver (and by drivers for a few PCI cards with SPDIF receiver).
 
  • Like
Reactions: 1 user
Mar 21 20:57:03 dspserver systemd[1]: Stopping camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP...
Mar 21 20:57:03 dspserver systemd[1]: camilladsp-setrate.service: Deactivated successfully.
Mar 21 20:57:03 dspserver systemd[1]: Stopped camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP.
Mar 21 20:57:03 dspserver systemd[1]: Starting camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP...
Mar 21 20:57:03 dspserver systemd[1]: Started camilladsp-setrate.service - Automatic Sample Rate Changer Daemon for CamillaDSP.
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: /usr/local/bin/camilladsp-setrate 2.1.0
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: An automatic sample rate switcher for CamillaDSP
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: Finite-state machine initialised
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: LWS: 4.1.6-, loglevel 1031
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: NET CLI SRV H1 H2 WS IPV6-on
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Websocket environment initialised
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Alsa control for the device hw:TosLink initialised
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 31
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 27
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 85
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: A new client websocket instance was created
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 71
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 29
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 24
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 44
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Unhandled callback: reason 2
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Callback: Connected to websocket server localhost:1234
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Event : CONNECT
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: Action : NULL
Mar 21 20:57:03 dspserver camilladsp-setrate[2056]: START: State : WAIT_RATE_CHANGE
This log shows that the alsa capture device has been correctly initialised and that the alsa control is waiting for an event from that device (initialisation includes opening the alsa control, associating a callback function, and subscribing to events).

Those lines reporting an "Unhandled callback: reason XX" correspond to normal steps in the websocket connection process. I will delete them in the future because they can be misleading.

At this point:
  • if your source is playing tracks at different sample rates,
  • if the capture device is actually capturing the audio stream sent by the source and
  • if the log file does not show any line such as "BEGIN : Sample Rate = XX"
we might conclude that the device driver of the capture device does not provide any information about the sample rate change.
 
Last edited:
  • Like
Reactions: 1 user
amixer -D hw:TosLink contents
numid=7,iface=CARD,name='miniDSP Internal Clock Validity'
; type=BOOLEAN,access=r-------,values=1
: values=on
numid=8,iface=CARD,name='miniDSP TOSLINK Clock Validity'
; type=BOOLEAN,access=r-------,values=1
: values=on
numid=10,iface=MIXER,name='IEC958 In Capture Switch'
; type=BOOLEAN,access=rw------,values=2
: values=on,on
numid=11,iface=MIXER,name='IEC958 In Capture Switch',index=1
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=12,iface=MIXER,name='IEC958 In Capture Volume'
; type=INTEGER,access=rw---R--,values=2,min=0,max=127,step=0
: values=127,127
| dBminmax-min=-127.00dB,max=0.00dB
numid=13,iface=MIXER,name='IEC958 In Capture Volume',index=1
; type=INTEGER,access=rw---R--,values=1,min=0,max=127,step=0
: values=127
| dBminmax-min=-127.00dB,max=0.00dB
numid=3,iface=MIXER,name='MCHStreamer TosLink Playback Switch'
; type=BOOLEAN,access=rw------,values=2
: values=on,on
numid=4,iface=MIXER,name='MCHStreamer TosLink Playback Switch',index=1
; type=BOOLEAN,access=rw------,values=1
: values=on
numid=5,iface=MIXER,name='MCHStreamer TosLink Playback Volume'
; type=INTEGER,access=rw---R--,values=2,min=0,max=127,step=0
: values=127,127
| dBminmax-min=-127.00dB,max=0.00dB
numid=6,iface=MIXER,name='MCHStreamer TosLink Playback Volume',index=1
; type=INTEGER,access=rw---R--,values=1,min=0,max=127,step=0
: values=127
| dBminmax-min=-127.00dB,max=0.00dB
numid=9,iface=MIXER,name='miniDSP Clock Selector Clock Source'
; type=ENUMERATED,access=rw------,values=1,items=2
; Item #0 'miniDSP Internal Clock'
; Item #1 'miniDSP TOSLINK Clock'
: values=0
numid=2,iface=PCM,name='Capture Channel Map'
; type=INTEGER,access=r----R--,values=2,min=0,max=36,step=0
: values=3,4
| container
| chmap-fixed=FL,FR
numid=1,iface=PCM,name='Playback Channel Map'
; type=INTEGER,access=r----R--,values=2,min=0,max=36,step=0
: values=3,4
| container
| chmap-fixed=FL,FR


NOTE: I need to connect the MCHStreamer to my Windows computer to configure it (miniDSP does not provide a Linux version of the app). For the clock, there are two options: TosLink at 48000 and internal at 48000. I select the TosLink clock, but as soon as I disconnect the MCHStreamer from the Windows computer and connect it back up to the Raspberry Pi, it reverts back to the internal clock. Nonetheless, it uses that same clock for all sample rates (44.1k, 48k, 96k and 192k). So this may or may not be a moot point.
 
The amixer contents looks like a standard soundcard with SPDIF input. Only the ctl 'miniDSP TOSLINK Clock Validity' informs that some SPDIF input signal is present (the TOSLINK clock is valid). No ctl with current samplerate though, as expected.

Maybe (but really very unlikely) the capture device clock would accept only currently-matching samplerate, if it makes some internal check. That could be easily checked with

Code:
arecord -v --dump-hw-params -D hw:TosLink > /dev/null

while there is some incoming SPDIF stream. Still, if this method worked, the cdsp-setrate project would have be to modified to read this value, either in a loop with some sleep, or maybe the ctl 'miniDSP TOSLINK Clock Validity' would send a notification. Looking at the snd-usb-audio source code, IIUC, if the USB device sends an interrupt request with some new parameter value, the driver notifies all defined ctls. I do not know if your device sends some new value parameter when the incoming SPDIF rate changes, that would have to be analyzed e.g. in wireshark. Certainly not a simple project though.
 
Still - does your usb-audio device Toslink have the alsa control "Capture Rate" with notifications enabled as required by the setrate project https://github.com/marcoevang/camil...eaa74275ee773b080ff52b/setrate_alsa.c#L52-L54 ? IIRC there is no such control provided by the snd-usb-audio driver, it's only provided by the USB gadget driver (and by drivers for a few PCI cards with SPDIF receiver).
I have gone through the MCHStreamer kit user manual, and it does not indicate whether it has Alsa control "Capture Rate" with notifications enabled. I checked the miniDSP website and it merely states that for Linux use Alsa.

The MCHStreamer kit also has SPDIF via 2-pin connectors. Later today I am going to connect RCA jacks to the 2-pin connectors (I need to get a crimping tool that works for the tiny female pins). I'll give that a try.

If that does not work I'll get a splitter for the USB-C connector on the Raspberry Pi and try that.
 
I have gone through the MCHStreamer kit user manual, and it does not indicate whether it has Alsa control "Capture Rate" with notifications enabled. I checked the miniDSP website and it merely states that for Linux use Alsa.
It has no such alsa control, as your amixer contents command shows. Also there is no such control defined in the alsa usb audio (host) driver source code.
 
  • Like
Reactions: 1 user