CamillaDSP - Cross-platform IIR and FIR engine for crossovers, room correction etc

"hw:Loopback,0,0" . Can I set up a different path for the capture device so that I can have my existing "Stream in" config to play from Squeezelite and then just load a "Pipe in" config if I want to play music from a browser via pipewire?
There are two loopback devices, Loopback,0 and Loopback,1, so you should be able to do playback to 0, capture from 1 in one config, and playback to 1, capture from 0 in the other.
 
That's not what I meant. Can you try running everything the same as when camilladsp failed when playing sound from the browser, but instead of running camilladsp, just use the "arecord" command line tool to capture sound from the same device that camilladsp would. I want to see if that fails with the same error 77.
Doesn't work. I think it's because arecord will not work with aac audio streamed from a website (tell me if I'm wrong)...

arecord -v -f cd -D hw:0,1 > recording1.wav
Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
arecord: set_params:1352: Sample format non available
Available formats:
- FLOAT_LE

Is that the issue here? Camilla doesn't cope with aac either?
Wouldn't Firefox be converting AAC to something the other apps can use?
 
Last edited:
@Addled : It's not AAC, but standard PCM with FLOAT_LE sample format. It's already listed in that pactl info dump.

Logically the -f cd format which means integer S16_LE does not fit with FLOAT_LE. You can run arecord with full format specification (-c 2 -f FLOAT_LE -r 48000).

The same with camilladsp - do you capture with FLOAT32LE format?
 
I think I need yet more help with this. I feel like I'm making it far more difficult than it should be.
This is where I am right now. Can anyone come up with a better command than this?

arecord -D hw:CARD=Loopback,DEV=1 -c 32 -f FLOAT_LE -v -r 48000 -d 15 > recording1.wav
Recording WAVE 'stdin' : Float 32 bit Little Endian, Rate 48000 Hz, Channels 32
Hardware PCM card 0 'Loopback' device 1 subdevice 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : FLOAT_LE
subformat : STD
channels : 32
rate : 48000
exact rate : 48000 (48000/1)
msbits : 32
buffer_size : 16384
period_size : 4096
period_time : 85333
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 4096
period_event : 0
start_threshold : 1
stop_threshold : 16384
silence_threshold: 0
silence_size : 0
boundary : 4611686018427387904
appl_ptr : 0
hw_ptr : 0
 
Last edited:
I think the 32 channels is right. I tried with 2, then 8, both times got "channel count not available error" 32 makes sense from what I know about Pro Audio.

Does it work? First time I got an 85mb file which I think was silence. Tried just now and got same output as above with "arecord: pcm_read:2221: read error: Input/output error" afterwards.
 
I think the 32 channels is right. I tried with 2, then 8, both times got "channel count not available error" 32 makes sense from what I know about Pro Audio.
No need to guess, just use the --dump-hw-params parameter which will report all params accepted by the device.

What is "Pro Audio" actually?

Does it work? First time I got an 85mb file which I think was silence.
Did you have anything playing (player -> pipewire -> aloop -> arecord) while capturing?

got same output as above with "arecord: pcm_read:2221: read error: Input/output error" afterwards.
What same error? What error number? If it's the same as in camilladsp, good, we have a test bed to troubleshoot.
 
Sorry about the previous post, I realised it wasn't helpful and was editing it when you replied.
here is the output...
arecord -D hw:CARD=Loopback,DEV=1 -c 32 -f FLOAT_LE -v -r 48000 -d 15 > recording1.wav
Recording WAVE 'stdin' : Float 32 bit Little Endian, Rate 48000 Hz, Channels 32
Hardware PCM card 0 'Loopback' device 1 subdevice 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : FLOAT_LE
subformat : STD
channels : 32
rate : 48000
exact rate : 48000 (48000/1)
msbits : 32
buffer_size : 16384
period_size : 4096
period_time : 85333
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 4096
period_event : 0
start_threshold : 1
stop_threshold : 16384
silence_threshold: 0
silence_size : 0
boundary : 4611686018427387904
appl_ptr : 0
hw_ptr : 0
arecord: pcm_read:2221: read error: Input/output error
 
"Audio Pro" is (I think, I can't find much info) something that comes with the drivers for "professional" audio HATS.

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 'card' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "default":
--------------------
ACCESS: RW_INTERLEAVED
FORMAT: U8 S16_LE S16_BE S24_LE S24_BE S32_LE S32_BE FLOAT_LE FLOAT_BE MU_LAW A_LAW S24_3LE S24_3BE
SUBFORMAT: STD
SAMPLE_BITS: [8 32]
FRAME_BITS: [8 1024]
CHANNELS: [1 32]
RATE: [1 384000]
PERIOD_TIME: (2 4294967295)
PERIOD_SIZE: [1 1398102)
PERIOD_BYTES: [128 1398102)
PERIODS: [3 1024]
BUFFER_TIME: (7 4294967295]
BUFFER_SIZE: [3 4194304]
 
When does the error appear? Right after start, or a bit later? Please run arecord in more verbose mode (-v, -vv) to see what's going on - see https://linux.die.net/man/1/aplay
I think I did use the -v command?

I do have the right device, don't I?
arecord -L
null
Discard all samples (playback) or generate zero samples (capture)
default
Playback/recording through the PulseAudio sound server
lavrate
Rate Converter Plugin Using Libav/FFmpeg Library
samplerate
Rate Converter Plugin Using Samplerate Library
speexrate
Rate Converter Plugin Using Speex Resampler
jack
JACK Audio Connection Kit
oss
Open Sound System
pulse
PulseAudio Sound Server
speex
Plugin using Speex DSP (resample, agc, denoise, echo, dereverb)
upmix
Plugin for channel upmix (4,6,8)
vdownmix
Plugin for channel downmix (stereo) with a simple spacialization
hw:CARD=Loopback,DEV=0
Loopback, Loopback PCM
Direct hardware device without any conversions
hw:CARD=Loopback,DEV=1
Loopback, Loopback PCM
Direct hardware device without any conversions
plughw:CARD=Loopback,DEV=0
Loopback, Loopback PCM
Hardware device with all software conversions
plughw:CARD=Loopback,DEV=1
Loopback, Loopback PCM
Hardware device with all software conversions
sysdefault:CARD=Loopback
Loopback, Loopback PCM
Default Audio Device
front:CARD=Loopback,DEV=0
Loopback, Loopback PCM
Front output / input
dsnoop:CARD=Loopback,DEV=0
Loopback, Loopback PCM
Direct sample snooping device
dsnoop:CARD=Loopback,DEV=1
Loopback, Loopback PCM
Direct sample snooping device
usbstream:CARD=Loopback
Loopback
USB Stream Output
usbstream:CARD=sndrpihifiberry
snd_rpi_hifiberry_dac8x
USB Stream Output
 
Last edited:
Browser is playing into the default device, which is hw:0,0 and I'm trying to pick up the output from the other end of the loop, which is hw:0,1.
if that's not what I should be doing, please correct me. If that is not what the arecord command is doing, that's because I've written it incorrectly.
The loop itself does work. If I link hw:0,1 to the DAC8x I get sound. Like this...
 

Attachments

  • Screenshot From 2025-05-11 09-15-51.png
    Screenshot From 2025-05-11 09-15-51.png
    339.6 KB · Views: 4
I don't know if it's helpful to anyone but here is output of selected active pipewire nodes from wpctl. node 277 is the Firefox browser, node 67 is the loopback node it's attached to.

$ wpctl inspect 277
id 277, type PipeWire:Interface:Node
adapt.follower.spa-node = ""
application.language = "en_GB.UTF-8"
* application.name = "Firefox"
application.process.binary = "firefox"
application.process.host = "MEDIAPI"
application.process.id = "14246"
application.process.machine-id = "a7ef12e2852c40ffbf357fb552ec8071"
application.process.session-id = "1"
application.process.user = "*******"
* client.api = "pipewire-pulse"
* client.id = "276"
clock.quantum-limit = "8192"
* factory.id = "7"
library.name = "audioconvert/libspa-audioconvert"
* media.class = "Stream/Output/Audio"
media.name = "AudioStream"
node.autoconnect = "true"
node.driver-id = "65"
node.latency = "3600/48000"
node.loop.name = "data-loop.0"
* node.name = "Firefox"
node.rate = "1/48000"
node.want-driver = "true"
object.register = "false"
* object.serial = "347"
port.group = "stream.0"
pulse.attr.maxlength = "4194304"
pulse.attr.minreq = "9600"
pulse.attr.prebuf = "38408"
pulse.attr.tlength = "48000"
pulse.server.type = "unix"
stream.is-live = "true"
window.x11.display = ":0"

$ wpctl inspect 65
id 65, type PipeWire:Interface:Node
alsa.card = "0"
alsa.card_name = "Loopback"
alsa.class = "generic"
alsa.device = "0"
alsa.driver_name = "snd_aloop"
alsa.id = "Loopback PCM"
alsa.long_card_name = "Loopback 1"
alsa.mixer_name = "Loopback Mixer"
alsa.name = "Loopback PCM"
alsa.resolution_bits = "32"
alsa.subclass = "generic-mix"
alsa.subdevice = "0"
alsa.subdevice_name = "subdevice #0"
alsa.sync.id = "00000000:00000000:00000000:00000000"
api.alsa.card.longname = "Loopback 1"
api.alsa.card.name = "Loopback"
api.alsa.headroom = "0"
api.alsa.path = "hw:0,0"
api.alsa.pcm.card = "0"
api.alsa.pcm.stream = "playback"
api.alsa.period-num = "16"
api.alsa.period-size = "1024"
audio.channels = "32"
audio.position = "AUX0,AUX1,AUX2,AUX3,AUX4,AUX5,AUX6,AUX7,AUX8,AUX9,AUX10,AUX11,AUX12,AUX13,AUX14,AUX15,AUX16,AUX17,AUX18,AUX19,AUX20,AUX21,AUX22,AUX23,AUX24,AUX25,AUX26,AUX27,AUX28,AUX29,AUX30,AUX31"
card.profile.device = "1"
* client.id = "36"
clock.name = "api.alsa.0"
clock.quantum-limit = "8192"
device.api = "alsa"
device.class = "sound"
* device.id = "59"
device.profile.description = "Pro"
device.profile.name = "pro-output-0"
device.profile.pro = "true"
device.routes = "0"
* factory.id = "19"
factory.name = "api.alsa.pcm.sink"
library.name = "audioconvert/libspa-audioconvert"
* media.class = "Audio/Sink"
* node.description = "Built-in Audio Pro"
node.driver = "true"
node.loop.name = "data-loop.0"
node.max-latency = "8192/48000"
* node.name = "alsa_output.platform-snd_aloop.0.pro-output-0"
* node.nick = "Loopback PCM"
node.pause-on-idle = "false"
* object.path = "alsa:acp:Loopback:1😛layback"
* object.serial = "65"
port.group = "playback"
* priority.driver = "1000"
* priority.session = "1000"
 
Browser is playing into the default device, which is hw:0,0
IIUC the browser is playing into pipewire. Then pipewire is playing into your loopback device (hw:Loopback,1).

and I'm trying to pick up the output from the other end of the loop, which is hw:0,1.
That is correct, but it is not what your arecord command with the --dump-hw-params was doing. Since (most likely) you did not specify the capture device with the -D param, arecord dump hw params of the alsa "default" device which is something very different than hw:Loopback,1. Since you have pipewire installed, most likely your alsa default device is pulse plugin back to pipewire.

There is a difference between pipewire default and alsa default.
The loop itself does work. If I link hw:0,1 to the DAC8x I get sound. Like this...
How did you link it? With camilladsp? What is the difference compared to your previous chain?

Again - you need to dump the hw params with arecord for the hw:0,1 device when firefox -> pipewire -> hw:0,0 is active. The reason is we want to see what parameters are offered by hw:0,1 at such moment. Please read e.g. https://www.diyaudio.com/community/threads/using-alsa-loopbacks-and-pipewire.405213/ , https://www.diyaudio.com/community/...studio-pipewire-and-calf.404960/#post-7509784
 
You typed "Again - you need to dump the hw params with arecord for the hw:0,1 device when firefox -> pipewire -> hw:0,0 is active."

I understand this and I have understood this from the beginning. I even had a pretty strong idea that I wasn't using the correct device with arecord. The output from browser to hw:0,0 was active all the time. The difficulty you're having with me isn't because of my lack of understanding of what data is required, it is with my lack of ability to acquire the correct data. I've made quite a lot of attempts to get the information, just haven't yet succeeded.

"How did you link it? With camilladsp? What is the difference compared to your previous chain?"
To get output from browser>loopback>DAC8x all I did was use the GUI qpwgraph and draw in the links between loopback1 and DAC8x as in the picture above. Camilla was operational but not in the chain.

I'm about to eat so can't read that link right now. I'll come back to it asap.
 
I've made quite a lot of attempts to get the information, just haven't yet succeeded.
It's just adding the --dump-hw-params parameter to your previous command. It's better to avoid redirecting stdout in case you want to see stdout - the last filename to aplay/arecord is the input/output name:

Code:
arecord --dump-hw-params -D hw:CARD=Loopback,DEV=1 -c 32 -f FLOAT_LE -v -r 48000 -d 15 recording1.wav

all I did was use the GUI qpwgraph and draw in the links between loopback1 and DAC8x as in the picture above
I see, so instead of linking the two alsa devices with camilladsp, you linked them with PW. That's expected to work. But we need the arecord diagnostics so see what camilladsp sees.
 
I see, so instead of linking the two alsa devices with camilladsp, you linked them with PW. That's expected to work. But we need the arecord diagnostics so see what camilladsp sees.
Yes. But it did at least prove to me that loopback was functional.

I was putting the --dump-hw-params at the end, ho-hum!.
-c 32 didn't work, I changed setting in camilladsp to four channels so perhaps that's the reason though I previously had it set to two channels so dunno.
anyway, I hope this helps....

arecord --dump-hw-params -D hw:CARD=Loopback,DEV=1 -c 4 -f FLOAT_LE -v -r 48000 -d 15 recording1.wav
Recording WAVE 'recording1.wav' : Float 32 bit Little Endian, Rate 48000 Hz, Channels 4
HW Params of device "hw:CARD=Loopback,DEV=1":
--------------------
ACCESS: MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED
FORMAT: FLOAT_LE
SUBFORMAT: STD
SAMPLE_BITS: 32
FRAME_BITS: 128
CHANNELS: 4
RATE: 48000
PERIOD_TIME: (83 1365334)
PERIOD_SIZE: [4 65536]
PERIOD_BYTES: [64 1048576]
PERIODS: [1 1024]
BUFFER_TIME: (83 2730667)
BUFFER_SIZE: [4 131072]
BUFFER_BYTES: [64 2097152]
TICK_TIME: ALL
--------------------
Hardware PCM card 0 'Loopback' device 1 subdevice 0
Its setup is:
stream : CAPTURE
access : RW_INTERLEAVED
format : FLOAT_LE
subformat : STD
channels : 4
rate : 48000
exact rate : 48000 (48000/1)
msbits : 32
buffer_size : 24000
period_size : 6000
period_time : 125000
tstamp_mode : NONE
tstamp_type : MONOTONIC
period_step : 1
avail_min : 6000
period_event : 0
start_threshold : 1
stop_threshold : 24000
silence_threshold: 0
silence_size : 0
boundary : 6755399441055744000
appl_ptr : 0
hw_ptr : 0
arecord: pcm_read:2221: read error: Input/output error
 
Hi all, I have an implementation question for all you audio gurus. I am implementing the following setup:
1747066269051.png


I want to use CamillaDSP for room correction + multi-subwoofer setup.

The issue is that the I2S source can switch between 2 channel 16 bit PCM stereo at 48kHz or 5.1 channel IEC 61937-3 (E)AC3 bitstream at 196 kHz.

So far, I modified this code that does a similar detection to work with alsa instead of pulseaudio and also decode EAC3 with libavcodec:
https://github.com/jakemoroni/audio_async_loopback

However, I need to further modify the code to:
  1. remove the Secret Rabbit Code sample rate converter since I believe the buffering that takes place interferes with Camilla DSP and is not necessary
  2. detect a sample rate change by monitoring a change in audio_sampling_rate v4l control to dynamically reconfigure Camilla DSP to not output 48kHz, but 196kHz (since both my capture and playback are on the same I2S bus and need to share the same clocks)

Before I start doing so, I keep thinking if there is not a simple way to monitor for a change in v4l-ctrl and reconfigure an audio capture (and decoder) pipeline:
  • ffmpeg: arecord -D hw:tc358743 -c 2 -t raw -f S16_LE -r 48000 | ffmpeg -hide_banner -loglevel debug -vn -drc_scale 0 timeout=-1 -rw_timeout=-1 -i pipe: -ac 6 -f alsa plughw:CARD=Loopback,DEV=1
  • gstreamer: gst-launch-1.0 filesrc location=/mnt/code/ac3/ChID_voices_6ch_256kbps_ddp.ec3 ! ac3parse ! avdec_eac3 ! audioconvert ! "audio/x-raw,channels=6" ! alsasink device=plughw:CARD=Loopback,DEV=1
Do you know any software that implements v4l2_ctrl_notify?

It would be great to get your expert thoughts!