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

Well then the capture device is closed, the script says it clear:

Code:
while [ "$(cat /proc/asound/card3/pcm1c/sub0/status)" != "closed" ]
  ....
done
...
echo "Capture device closed. Clock rate control disabled (clk: 1000000)."

Either camilla is not running, or you are querying a different device. If you want to keep the script running all the time, you will have to modify it to accept the closed status (i.e. wrapping the "while not closed" loop with another while true loop with some sleep)
 
How does the chain actually work? There are two independent devices - capture, playback. Which one has the "clock master" role in your code?

IIUC correctly there are options:

A) each side uses blocking read/write in separate threads, with execution thread in between, reading from some buffers. Then the "xrun" would occur in these buffers, not in the alsa drivers.

B) one side (master) uses blocking operation, the other one non-blocking ("slave"). The thread is timed by the blocking side, hoping the non-blocking side will produce/consume in the same rate.

C, D - other variants I do not know

Please which workflow do you use?
It's close to A but not exactly. I use queues instead of plain buffers between the threads. I launch three threads, one for capture, one for processing and one for playback.


The capture thread uses blocking io to read N samples per channel (given by buffersize setting). When done, it converts them to float, and packages them in a message that is sent in a channel to the processing thread. The channel is basically a queue shared between the treads and can hold more than one message. Once sent it goes back to reading another set of N samples.



The processing thread waits for a message, does the processing and sends the processed data as a message on another channel to the playback thread.


The playback thread waits for a message. Once received the data is converted to the right format for the device, and then written to the device using blocking io. Once all the data has been written, it loops around to wait for the next message.


In practice the capture device is the one deciding the rate. If the playback queue will slowly grow with not yet played data. If it instead runs faster, once in a while the message will be late, meaning that the playback device will run out of data. Once a new message has been received, playback is resumed.
 
Well, to my understanding uptime,buftime and clk should update in terminal, right?
However it does not.


Look at the script. The information is echoed only when new = different clkrate is identified:

Code:
# set clock rate of snd-aloop
if [ $clkrate -ne $lastclk ]
then
  amixer -c 3 cset numid=7 $clkrate > /dev/null
  echo "uptime: "$up"s bufsize: "$loopc_bufsize" filled: "$buf_ratio"% clk: "$clkrate
fi

You keep reading from the loopback /proc, right? But as Henrik said - that buffer will be kept empty all the time, because the reading thread in camilladsp has no blocking on the consumer side - there is a nonblocking queue which can grow unlimited.

Try to print the buf_ratio to see the value:
Code:
# fill rate in percent
buf_ratio=$(($loopc_buf_avail*100/$loopc_bufsize))
echo "buf_ratio: $buf_ratio"   # <----

I think you will see values close to zero all the time. It is under 70 constantly and clkrate is always 99000 - no change, no printout.

You need to read buffer fill of the playback soundcard, IMO.
 
Please help NO !!

//
Agreed. Maybe it is not necessary to cheat.

There are indeed perfect solutions already implemented into audio programs: The aforementionned playhrt player which I use in my pipe provides a parameter --extra-bytes-per-second which performs exactly what is discussed here. This parameter allows to specify a correction for the differences between the soundcard's and the computer clocks. Maybe a look into the code of playhrt could be interesting: Bitbucket
 
Very interesting topic, this struggle for servicing out of sync hardware. Either by tweaking directly into the timing of the slave hardware, or by cheating something useful into the data stream. Useful in terms of matching between different hardware devices, and also in terms of irrelevance to psychoacoustic perception.

As intersting as such a functionality is; in my oppinion this functionality has not to be implemented into a convolver. I like a convolver (as any other program) as lean (and as precise) as possible.

So why not opening another, new thread in order to start a completely new project of such a most welcome "anyclocks-anydatastream-harmonizer" which by parameters allows it
- to work either as a HW master's receptor, or a HW slave's supplyier
- to provide either datastream modification or hardware tweaking

This would indeed be a completely different function set than a convolver.
In principle I agree that it's good to keep things slim. Bit I also think that putting CamillaDSP between an Alsa loopback and a real Alsa device will probably be the most common configuration, so there is good reason to handle this.

It's not a lot to add. I just need to watch the buffer, calculate the correction, and pass this along to the Loopback. (Reading and writing the value was a bit tricky because of lacking documentation but I've figured it out).
 
Hello Henrik

I have a wishlist, if I may wish, at all ...

Wish No. 1:
Please make the compensation of out-of-sync clocks switchable [on/off]. This may help the integration of Camilladsp within more complex pipes.

Then, as a longtime brutefir user ...

Wish No. 2:
Brutefir provides a [delay] option in the [input] and [output] sections. This is useful for the time alignment of the different drivers in Xovers within multiway loudspeakers. In Camilladsp such an option would probably best be included within the [mixer] module? If is was possible to do so, then it would be handy if not only positive integers n for delay by n samples would be accepted, but also negative integers -n for a lead by n samples.

Wish No. 3:
Brutefir in it's general declaration section includes a [safety_limit] parameter. [safety_limit] will instantly kill brutefir when the declared threshold limit is reached, which can e.g. be useful for diagnostic purpose. Initially, it has been introduced by A.Torger for another reason: The dither algorithm of Brutefir seems corrupt, which randomly can lead to a shrieking output reading up to +200dB (!). Which distroyed several of my tweeters. A.Torger introduced [safety_limit], then, but it failed: [safety_limit] works fine under regular conditions, but does not prevent the schrieking quirk (this is why I perform dithering not within brutefir, but by sox later in the pipe). This much for the story of [safety_limit]. I would appreciate such a [safety_limit] in Camilladsp also. As said, for diagnostic use within an audio programs pipe. Or a less crude, similar option, logging the maximum reached level. Also this option might be disabled in order to minimize CPU load.

Wish No. 4:
Brutefir includes a [float_bits] parameter to switch between internal float32 and float64 precision. Such an option could be nice also within Camilladsp.

I have not tested Camilladsp yet. I am very eager do so within my funcional audio pipe and then benchmark it against Brutefir as soon as Camilladsp will provide stdin and stdout in float32 and float64 flavors. And I am very eager also to track down the differences, if there will be any.

PS: I discovered a small typo in README.md @ GitHub: "... Vislualizing the config ..."
 
Hello Henrik

Brutefir provides a [delay] option in the [input] and [output] sections. This is useful for the time alignment of the different drivers in Xovers within multiway loudspeakers.


Does not this delay change in time (multiple async cards drifting away) or is it not random at each start (synced cards starting at different time)? Or is it for aligning fixed delays of parallel filtering paths?
 
Hello Henrik

I have a wishlist, if I may wish, at all ...

Wish No. 1:
Please make the compensation of out-of-sync clocks switchable [on/off]. This may help the integration of Camilladsp within more complex pipes.

Then, as a longtime brutefir user ...

Wish No. 2:
Brutefir provides a [delay] option in the [input] and [output] sections. This is useful for the time alignment of the different drivers in Xovers within multiway loudspeakers. In Camilladsp such an option would probably best be included within the [mixer] module? If is was possible to do so, then it would be handy if not only positive integers n for delay by n samples would be accepted, but also negative integers -n for a lead by n samples.

Wish No. 3:
Brutefir in it's general declaration section includes a [safety_limit] parameter. [safety_limit] will instantly kill brutefir when the declared threshold limit is reached, which can e.g. be useful for diagnostic purpose. Initially, it has been introduced by A.Torger for another reason: The dither algorithm of Brutefir seems corrupt, which randomly can lead to a shrieking output reading up to +200dB (!). Which distroyed several of my tweeters. A.Torger introduced [safety_limit], then, but it failed: [safety_limit] works fine under regular conditions, but does not prevent the schrieking quirk (this is why I perform dithering not within brutefir, but by sox later in the pipe). This much for the story of [safety_limit]. I would appreciate such a [safety_limit] in Camilladsp also. As said, for diagnostic use within an audio programs pipe. Or a less crude, similar option, logging the maximum reached level. Also this option might be disabled in order to minimize CPU load.

Wish No. 4:
Brutefir includes a [float_bits] parameter to switch between internal float32 and float64 precision. Such an option could be nice also within Camilladsp.

I have not tested Camilladsp yet. I am very eager do so within my funcional audio pipe and then benchmark it against Brutefir as soon as Camilladsp will provide stdin and stdout in float32 and float64 flavors. And I am very eager also to track down the differences, if there will be any.

PS: I discovered a small typo in README.md @ GitHub: "... Vislualizing the config ..."


#1 I will make the Loopback sync optional yes. At the moment I will only implement it for when both capture and playback devices are Alsa.



#2 The Delay options in BruteFIR are very confusing since you can add delays in many places and they have somewhat different meanings. I have only made a single Delay, that is implemented as a filter. I believe this covers all the needs except subsample delay (which I may implement as a separate filter at some point). I don't really like the idea of negative delays since it means the different delays start depending on each others values. I prefer to keep it simple.


#3 I'm thinking if maybe a Watchdog filter could cover this. Basically a filter that just monitors the signal and either limits the level passing through or stops the processing altogether.



#4 This is implemented as a compile flag. 64-bit is the default, but you can set it 32 using the 32bit feature. Check the readme! Implementing it as a config option basically means I have to duplicate a large part of the code and make separate 32- and 64-bit versions of things.



There is a test version with float support in the branch "floats" if you want to give it a try. The new formats are called FLOAT32LE and FLOAT64LE (and the readme isn't updated). The float part isn't really tested yet so any help with that is appreciated!
 
#1 I will make the Loopback sync optional yes. At the moment I will only implement it for when both capture and playback devices are Alsa.



#2 The Delay options in BruteFIR are very confusing since you can add delays in many places and they have somewhat different meanings. I have only made a single Delay, that is implemented as a filter. I believe this covers all the needs except subsample delay (which I may implement as a separate filter at some point). I don't really like the idea of negative delays since it means the different delays start depending on each others values. I prefer to keep it simple.


#3 I'm thinking if maybe a Watchdog filter could cover this. Basically a filter that just monitors the signal and either limits the level passing through or stops the processing altogether.



#4 This is implemented as a compile flag. 64-bit is the default, but you can set it 32 using the 32bit feature. Check the readme! Implementing it as a config option basically means I have to duplicate a large part of the code and make separate 32- and 64-bit versions of things.



There is a test version with float support in the branch "floats" if you want to give it a try. The new formats are called FLOAT32LE and FLOAT64LE (and the readme isn't updated). The float part isn't really tested yet so any help with that is appreciated!

Hello Henrik,

Tested test version last evening with FLOAT32LE filters created in Rephase on RP2.
No problems so far.
 
Maybee offtopic, but ...

Hello.

I recieved my UMIK-1 microphone the other day, and set it up on my little workshop for playing a bit around with it.

Reason i joined this thread, and reason i bought this mic. is that i want to do some room correction, especially in the lower end, as i feel my bass is some "boomey", and not "sharp" and clean :)

As i wrote before i plan to run camilladsp on an RPI4 directly connected to my Amanero-usb reciever. (AK4490 Dual DAC)..

I have installed the REW program on my Linux laptop, and tried to take some measurement's/calibrating the in/out-put's and so on. But i don't know what to do next, and which program i better use. I therefore kindly ask if someone would tell me what they use, and maybe explain what i need to accomplish my goal to make the filters for camilladsp.
I tried surfing around for several day's, but it's complicated stuff and there are many way's to do it as i see.

So guy's what do you use as software for all this :p

Rgds; Jesper.