• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. 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've been running my RPi Zero 2 with Camilla DSP a couple of weeks nearly daily, continuously multiple hours. I'm regularly, one every 10-15 mins, getting short pauses and log reveals they are either buffer underrun or some sort of write errors (are they the same?):
2024-09-10 01:17:15.006062 WARN [src/audiodevice.rs:523] Needless 1:1 sample rate conversion active. Not needed since enable_rate_adjust=False
2024-09-10 01:17:15.026158 INFO [src/alsadevice.rs:648] Capture device supports rate adjust

playback device type=Alsa, sampleformat=S32LE and using hifiberry driver
capture device is also Alsa, S32LE UAC2Gadget

The capture and playback devices run asynchronously, therefore the rate adjust needs to be enabled, otherwise they will regularly run out of buffers.
Async resampler is not required becase the USB gadget allows adjusting its rate which CDSP does with enable_rate_adjust = true.
 
Last edited:
The capture and playback devices run asynchronously, therefore the rate adjust needs to be enabled, otherwise they will regularly run out of buffers.
Async resampler is not required becase the USB gadget allows adjusting its rate which CDSP does with enable_rate_adjust = true.
Okey, I set the Rate adjust feature on, enable_rate_adjust=yes, this is the feature you mean? There is also the the Resampling feature, which is none in my CDsp.

After turning it on, I still get "PB: Prepare playback after buffer underrun" rows in my log, but considerably less and what's more important, I haven't noticed any audible pauses. The GUI shows this rate adjustment from time to time:
Screenshot_20240918-110358~2.png

So it will sync with the playback by playing slightly faster from time to time? I'm not sure what to think about that, but it's mostly inaudible. The DAC boasts this precise clock:
IMG_20240918_111005_HDR~3.jpg


I do have a RPi 4B that I will test with this hat with later. It's currently on my dev bench because I'm testing out rotary encoders and a display with it. I will probably publish the source when it's done.

PS. If the CDsp needs to play faster to keep up with data feed, the USB is not truly async, as it would request new batch of data when it needs it. Or the PC keeps rushing the data, which would mean a very sucky player app (Spotify through web UI, Chrome). I don't think the data feed is behind the playback.
 
Last edited:
After turning it on, I still get "PB: Prepare playback after buffer underrun" rows in my log, but considerably less and what's more important, I haven't noticed any audible pauses.
Your CDSP config is a very important info for troubleshooting, please post it here.

If the CDsp needs to play faster to keep up with data feed, the USB is not truly async, as it would request new batch of data when it needs it. Or the PC keeps rushing the data, which would mean a very sucky player app (Spotify through web UI, Chrome). I don't think the data feed is behind the playback.
Your chain has only one fixed clock - the DAC crystal clock. That clocks your RPi/CDSP playback soundcard. The other soundcard is the USB gadget (which determines sample consumption rate on the USB host for the player and sample production rate in CDSP capture thread), but its "clock" can be tuned by the async control. CDSP is able to monitor and determine the relative ratio of the capture and playback clocks and adjust the USB gadget "clock" accordingly - if told to do so via the enable_rate_adjust config. It even complains in the logs if that parameter is not set for the USB gadget device - I quoted that from your logs. Also Henrik describes meaning of the enable_rate_adjust param in the documentation https://github.com/HEnquist/camilladsp?tab=readme-ov-file quite in detail.
 
Your chain has only one fixed clock - the DAC crystal clock.
Actually, your chain is clocked by RPi internal clock which sets pace of the I2S interface. The I2S stream is asynchronously resampled to the 50MHz clock by the DAC chip. But it's not important for the gadget functionality.
 
After turning it on, I still get "PB: Prepare playback after buffer underrun" rows in my log, but considerably less and what's more important, I haven't noticed any audible pauses.

I've found that most devices will report this when starting CamillaDSP from a pause. If you have a silence timeout in your configuration, remove it and see if the underruns disappear.

Michael
 
Your CDSP config is a very important info for troubleshooting, please post it here.


Your chain has only one fixed clock - the DAC crystal clock. That clocks your RPi/CDSP playback soundcard. The other soundcard is the USB gadget (which determines sample consumption rate on the USB host for the player and sample production rate in CDSP capture thread), but its "clock" can be tuned by the async control. CDSP is able to monitor and determine the relative ratio of the capture and playback clocks and adjust the USB gadget "clock" accordingly - if told to do so via the enable_rate_adjust config. It even complains in the logs if that parameter is not set for the USB gadget device - I quoted that from your logs. Also Henrik describes meaning of the enable_rate_adjust param in the documentation https://github.com/HEnquist/camilladsp?tab=readme-ov-file quite in detail.
My CamillaDSP config file that's been running for the past two days is the following:
YAML:
description: 'Audiophonics DAC HAT to W4 speakers.

  Filters to optimize the W4 performance.'
devices:
  adjust_period: null
  capture:
    channels: 2
    device: default:CARD=UAC2Gadget
    format: S24LE
    type: Alsa
  capture_samplerate: 96000
  chunksize: 1024
  enable_rate_adjust: true
  playback:
    channels: 2
    device: default:CARD=sndrpihifiberry
    format: S24LE
    type: Alsa
  queuelimit: null
  rate_measure_interval: null
  resampler: null
  samplerate: 96000
  silence_threshold: -60
  silence_timeout: 10
  stop_on_rate_change: null
  target_level: null
  volume_ramp_time: 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: 8
      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
mixers:
  W4-mixer:
    channels:
      in: 2
      out: 2
    description: Includes -10 db gain for filter headroom.
    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: false
  description: null
  name: W4-mixer
  type: Mixer
- bypassed: false
  channel: 0
  description: null
  names:
  - W4 global HPF2
  - W4 global HPF2
  - W4 fix1
  - W4 fix2
  - W4 fix3
  type: Filter
- bypassed: false
  channel: 1
  description: null
  names:
  - W4 global HPF2
  - W4 global HPF2
  - W4 fix1
  - W4 fix2
  - W4 fix3
  type: Filter
processors: {}
title: Audiophonics-W4
And for the record usb_g_audio.conf (one line):
options g_audio c_srate=44100,48000,88200,96000,176400,192000 c_ssize=4 c_chmask=3 p_chmask=0
The c_ssize=4 is there even though format in the yaml is S24LE, because lowering c_ssize to 3 would somehow not work. I'm trying to change as few things as possible at a time to see how a specific change affects, so it's 4 for now. Windows sees it as 32 bit sink in sound options.

It seems that I quite often get the
2024-09-18 17:55:40.001811 WARN [src/alsadevice.rs:138] PB: Prepare playback after buffer underrun
message when host PC is starting an audio stream. W10 does this a lot more than W11. I'm not sure how I could verify this, but I'm certain that some of the timestamps are when I started playback. (I got two laptops and a dock on my desk. When switching from laptop to another, I connect the docks data cable to the laptop I'm using. The RPi is connected to the dock. The W10 gets much more playback hours.)

Actually I can repeat this. Pause playback on host pc, wait at least silence_timeout duration, and start playback. The log entry is stamped on the start of playback. Just pausing will not generate a log entry. Using W11 Spotify app. If I set the timeout low, like 2 seconds, it will trigger it if a song has that much continuous silence, like at the end of a song. Yup, 100 % return rate and always at when sound starts to come out again.

A chunk size of 1024 is a bit on the small side at 96 kHz. You can try doubling or quadrupling it.
Thanks, I just read your docs over github and noticed the same thing. I adjusted it now to see how it goes. I've been listening to music with increased buffer while writing this and I've seen log entries of the said kind while writing the last paragraph.

FWIW: The Audiophonics DAC officially supports B-variants of the RPi, but I'm currently using it on top of a Zero 2 W, because it seems to work without obvious audible issues. The Zero line is kind of low power implementation in the Raspberry family, I wonder if the SKU has any inherent problems for this kind of use? It's a better choice power-wise, because it can be comfortably powered by USB bus (less cable clutter). My 4B is still reserved for dev use, so I cannot pull it yet, but I have appropriate power/data splitter cable for it. The Zero currently uses the dtoverlay=hifiberry-dac driver that ships with the RPi OS. I'm not sure if it's exactly the correct one, but sound comes out.
 
Actually I can repeat this. Pause playback on host pc, wait at least silence_timeout duration, and start playback. The log entry is stamped on the start of playback.
This is perfectly normal. When the Windows host stops playback, the usb gadget stops delivering data to camilladsp, and the playback device runs out of samples. Then when playback is resumed, the playback device needs to be prepared from the underrun state. The same thing happens if it pauses because of silence.
 
Hello Henrik, thank you very much for CSDP.

Speaking of logs, I use the loudness filter and I noticed that every time the volume slider is moved a log entry is made (for every step if making a large change). Is there a way to disable these INFO messages? It makes the logs extremely long and makes for a lot of scrolling when looking for issues.

Also a "clear log" button for those of us with autism would be appreciated. :D Sometimes I restart CDSP or reboot my Pi just to get a fresh log.
 

Attachments

  • Screenshot 2024-09-19 at 01.06.14.jpg
    Screenshot 2024-09-19 at 01.06.14.jpg
    1,008.2 KB · Views: 27
The c_ssize=4 is there even though format in the yaml is S24LE, because lowering c_ssize to 3 would somehow not work.
That's correct - again if you look at CDSP documentation https://github.com/HEnquist/camilladsp:

S24LE - Signed 24-bit int, stored as four bytes (three bytes of data, one padding byte)
as opposed to
S24LE3 - Signed 24-bit int, stored as three bytes (with no padding)

As of the config:

device: default:CARD=UAC2Gadget
...
device: default:CARD=sndrpihifiberry
Have your checked what the definition of default does on your system, e.g. through 'arecord -v -D default:CARD=UAC2Gadget ...' or 'aplay -v -D default:CARD=sndrpihifiberry ...'? I would consider direct path hw:UAC2Gadget/hw:sndrpihifiberry.

The UAC2Gadget card has a rather limited buffer/period size range. It would be good to check what are the actual values used, i.e. in file /proc/asound/UAC2Gadget/pcm0c/sub/hw_params.
 
Last edited:
Thanks for the instructions @mdsimon2
Just found the bluez-alsa installation @#2039, thanks again for the detailed instruction.
And I just found the way to "update" the bluez-alsa by compile it from source to have the aptX. aptX-HD supported codecs.
Haven't tried LDAC yet, but lack of decode, this become useless codec for now, unless someone just share a way impelement it.

The problem is:
I found even using the aptX-HD codec, the capt. sample rate is still 44.1kHz, which should be 48kHz?
And also, I found there's no loopback signal when set the sample format to S24LE while aptX-HD should be 24-bit format codec.

Finally have the LDAC as sink.
Thank again for your tutorial! @mdsimon2

Checked from syslog. (not sure why but PCM overrun often occurs when using bluetooth.)
1726755858147.jpg



Checked from "bluealsad -h"
1726755875441.jpg


Checked from my Android phone. (have set to 990/909 kbps and it works like a charm.)
7070.jpg
 
I noticed that every time the volume slider is moved a log entry is made
Thanks for reporting! That should clearly not be on info level. I'll fix it in the next release.

a "clear log" button
I look at adding optional log file rotation. The settings could be at what file size to start on a new file, and how many old files to keep.
 
That's correct - again if you look at CDSP documentation https://github.com/HEnquist/camilladsp:


as opposed to


As of the config:


Have your checked what the definition of default does on your system, e.g. through 'arecord -v -D default:CARD=UAC2Gadget ...' or 'aplay -v -D default:CARD=sndrpihifiberry ...'? I would consider direct path hw:UAC2Gadget/hw:sndrpihifiberry.

The UAC2Gadget card has a rather limited buffer/period size range. It would be good to check what are the actual values used, i.e. in file /proc/asound/UAC2Gadget/pcm0c/sub/hw_params.
I could not get any combination of format settings to work when I lowered the c_ssize to 3. Windows would see the device, but it would not play any sound or even display the available formats. As if it was illegal value or misconfigured and simply would not operate.

I left the default option on because it seemed to choose whatever the system deemed as default audio device. That was handy when switching usb dacs. Now that I use the hat, I could address hw-device instead. I had to stop camilladsp service to get readings for those commands, but I have some results.

"arecord -L":
Code:
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
default, sysdefault and plughw were identical:
Code:
Warning: Some sources (like microphones) may produce inaudible results
         with 8-bit sampling. Use '-f' argument to increase resolution
         e.g. '-f S16_LE'.
Recording WAVE '...' : Unsigned 8 bit, Rate 8000 Hz, Mono
Plug PCM: Rate conversion PCM (96000, sformat=U8)
Converter: linear-interpolation
Protocol version: 10003
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : U8
  subformat    : STD
  channels     : 1
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 8
  buffer_size  : 682
  period_size  : 42
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 42
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 682
  silence_threshold: 0
  silence_size : 0
  boundary     : 383931868233334784
Slave: Route conversion PCM (sformat=S32_LE)
  Transformation table:
    0 <- 0*0.5 + 1*0.5
Its setup is:
  stream       : CAPTURE
  access       : MMAP_INTERLEAVED
  format       : U8
  subformat    : STD
  channels     : 1
  rate         : 96000
  exact rate   : 96000 (96000/1)
  msbits       : 8
  buffer_size  : 8192
  period_size  : 512
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 512
  period_event : 0
  start_threshold  : 12
  stop_threshold   : 8192
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Hardware PCM card 0 'UAC2_Gadget' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : MMAP_INTERLEAVED
  format       : S32_LE
  subformat    : STD
  channels     : 2
  rate         : 96000
  exact rate   : 96000 (96000/1)
  msbits       : 32
  buffer_size  : 8192
  period_size  : 512
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 512
  period_event : 0
  start_threshold  : 12
  stop_threshold   : 8192
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
hw was short:
Code:
Warning: Some sources (like microphones) may produce inaudible results
         with 8-bit sampling. Use '-f' argument to increase resolution
         e.g. '-f S16_LE'.
Recording WAVE '...' : Unsigned 8 bit, Rate 8000 Hz, Mono
arecord: set_params:1352: Sample format non available
Available formats:
- S32_LE
It's the same story with playback.
"aplay -L":
Code:
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
default, sysdefault and plughw were identical:
Code:
Playing WAVE '...' : Unsigned 8 bit, Rate 8000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : U8
  subformat    : STD
  channels     : 1
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 8
  buffer_size  : 4000
  period_size  : 1000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1000
  period_event : 0
  start_threshold  : 4000
  stop_threshold   : 4000
  silence_threshold: 0
  silence_size : 0
  boundary     : 9007199254740992000
Slave: Hardware PCM card 1 'snd_rpi_hifiberry_dac' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 16
  buffer_size  : 4000
  period_size  : 1000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1000
  period_event : 0
  start_threshold  : 4000
  stop_threshold   : 4000
  silence_threshold: 0
  silence_size : 0
  boundary     : 9007199254740992000
  appl_ptr     : 0
  hw_ptr       : 0
hw was short:
Code:
Playing WAVE '...' : Unsigned 8 bit, Rate 8000 Hz, Mono
aplay: set_params:1352: Sample format non available
Available formats:
- S16_LE
- S24_LE
- S32_LE
 
This is perfectly normal. When the Windows host stops playback, the usb gadget stops delivering data to camilladsp, and the playback device runs out of samples. Then when playback is resumed, the playback device needs to be prepared from the underrun state. The same thing happens if it pauses because of silence.
If it's normal, maybe it shouldn't produce a WARN log message? I like the fact that the DSP engine goes to sleep when there is only silence, it saves power. So maybe it should clear any playback state as well so there would be no warnings?

One other thing. Windows volume controls don't affect the Camilla DSP at all. This might be by design (miniDSP SHD also ignores Windows volume control), but if there is an easy way to make this configurable option, it would suit my low-fi environment better. On my main system I would prefer that Windows would not mess with the volume, but on this work computer I prefer the other way around. And it would need to work two-ways, when adjusting volume on Camilla, it would need to be reflected back to Windows, if possible. Also it might be useful to allow mute on/off separately from actual volume control.
 
Finally have the LDAC as sink.
Thank again for your tutorial! @mdsimon2

Checked from syslog. (not sure why but PCM overrun often occurs when using bluetooth.)
View attachment 393330


Checked from "bluealsad -h"
View attachment 393332

Checked from my Android phone. (have set to 990/909 kbps and it works like a charm.)
View attachment 393331
Always thought ldac receive was not open by Sony, happy that this possibility exists.
How is the reception at high bit rate with the RPI own antenna?
 
If it's normal, maybe it shouldn't produce a WARN log message? I like the fact that the DSP engine goes to sleep when there is only silence, it saves power. So maybe it should clear any playback state as well so there would be no warnings?
I have thought about different ways of handling this, but in practice the only issue is the warning message that could be on info level instead. Fixing it would need require making the device state handling more complicated. I don't think this is enough of a problem to motivate that.


Windows volume controls don't affect the Camilla DSP at all
This is due to how the usb gadget works. It exposes a "hardware" volume control to the Windows host, so windows uses that to set volume instead of modifying the audio stream. The volume setting can be read from an Alsa control, and the next version of camilladsp can slave its volume control to that.
 
And it would need to work two-ways, when adjusting volume on Camilla, it would need to be reflected back to Windows, if possible.
I don't know if the usb gadget allows this. If it does, you would need some service that monitors the gadget and camilladsp volume settings, and syncs the changes the right way. The next camilladsp version can only follow.
 
The gadget volume controls are read/write. But the new value would have to be queried by windows and its internal volume structure would have to be adjusted accordingly. I have no idea if windows do that, it would be simple to test. I do not know if UAC specifies this kind of feedback behavior, volume buttons on USB devices are standard HID multimedia keys which operate the windows volume (which in turn controls the gadget volume feature).

But the gadget volume controls can be disabled with configfs params https://github.com/torvalds/linux/b...tion/ABI/testing/configfs-usb-gadget-uac2#L15 and https://github.com/torvalds/linux/b...tion/ABI/testing/configfs-usb-gadget-uac2#L28 . Of course the uac2 function would have to be loaded via configfs, not via the gaudio loader module which exposes only a limited subset of all configfs parameters.
 
... have to be queried by windows and its internal volume structure would have to be adjusted accordingly. I have no idea if windows do that, it would be simple to test.
Yes this would be interesting and easy to check with alsactl. I don't plan to let Camilladsp write to the gadget volume control, but it could be of interest for external scripts.
 
I stream from USB out of a WiiM Ultra to my Raspberry Pi using USB Gadget mode. I am running Raspberry Pi OS Lite with CamillaDSP and camilladsp-setrate.

An issue recently has popped up, probably within the last couple of weeks. Sometimes, I start the stream, but CamillaDSP does not receive it - the GUI volume indicator shows no incoming stream. I reboot my Raspberry Pi and then everything works.

Attached is my log file between when I successfully used CamillaDSP yesterday and unsuccessfully attempted to use it this morning. There was an apt daily update service that ran during that period. Is this creating the issue?

Any help would be greatly appreciated. I'm leaning toward disabling the apt daily update service, but figured I would check here before doing that, just in case I am barking up the wrong tree.
 

Attachments

  • Pi Log File.zip
    1.3 KB · Views: 23
Back
Top Bottom