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

By communication i mean information sent over "Control transfer" in figure 1 of:
https://www.edn.com/fundamentals-of-usb-audio/

And that the red case applies here:
3.11.4.3 SOURCE AND SINK ENDPOINTS
A typical example for this scenario is a USB headset, implementing both a sink endpoint that receives streaming
audio data from the Host and a source endpoint that sends streaming audio data to the Host.
In general, the endpoints can be treated independently, using the same rules and guidelines as stated above. This
includes the ability for the Device to support separate clocks on each endpoint.
[special=However, if the Device has its own clock and both data streams share this clock, the following two special cases
can be used to allow implicit feedback:
 Both endpoints are Asynchronous. In this case, the data rate that appears on the Source endpoint can be
used by the Host as implicit feedback to adjust the data rate transmitted to the Sink endpoint.]%[/special]
(Taken from UNIVERSAL SERIAL BUS DEVICE CLASS DEFINITION FOR
AUDIO DEVICES Release 3.0 September 22, 2016)

Off topic (maybe?). Windows now has USB Audio 2.0 driver shipped with Windows.
USB Audio 2.0 Drivers - Windows drivers | Microsoft Docs
 
This is a low-level USB protocol and all of that is handled by the USB driver.

Basically you have three options for a USB soundcard:

single independent internal clock: async capture, async playback - more expensive USB soundcards. Async playback can have either explicit or implicit feedback.

independent clock for capture only: async capture, adaptive playback - vast majority of USB soundcards. This mode allows receiving SPDIF (which is always clock master)

no internal clock, USB frame tick is used: adaptive capture, adaptive playback - I have never seen such a device
 
This is a low-level USB protocol and all of that is handled by the USB driver.
The reason I worry is clock drifting between input and output. (Thinking of monthts/years of drifting)
If I understand right, I can assume:
independent clock for capture only: async capture, adaptive playback - vast majority of USB soundcards. This mode allows receiving SPDIF (which is always clock master)
Then
- Soundcard is clockmaster for input and camillaDSP adjusts to Soundcard speed. (async)
- Soundcard adjusts to camillaDSP speed for output (adaptive)
 
Last edited:
Wondering if the chunksize and target_level always should be larger than the USB wMaxPacketSize (for USB soundcards)?

These params are related to the USB communication. I think the alsa usb driver does not allow minimum alsa period size to be below max packet size. I do not know what is relation of Henrik's chunksize and alsa period size. No idea what happens in windows but it will be similar.
 
- Soundcard is clockmaster for input and camillaDSP adjusts to Soundcard speed. (async)
- Soundcard adjusts to camillaDSP speed for output (adaptive)

No software can influence clock of any hardware-based soundcard (with the exception of the planned USB audio gadget but that is a different story as it basically created in software). Adaptive USB streams are clocked by USB controller clock which is again hardware-based.
 
I see.
In adaptive mode a fixed number of samples is sent in each USB frame, in async mode the number of samples is adjusted to satisfy the control feedback from the device. The existing USB-adaptive drivers do not offer to userspace any control of samples distribution into the frames. IMO the PLL'd clock would be quite jittery if samples count in every frame started to deviate more than just by the rounding to integer (44.1kHz samplerate in 1ms USB frame).

The closest to that is IMO the snd-aloop software loopback which allows fine-tuning its software-based clock from userspace. CamillaDSP uses that, of course.
 
Last edited:
In windows lingo, what is the playback device if I want to output the sound to a new intance of CamillaDSP?
Use the Stdout playback device on the first instance, and Stdin capture device on the second. Then in the terminal window you connect them with a pipe character, |.
Code:
camilladsp config1.yml | camilladsp config2.yml

Hi there.

@Henrik.

I was just wondering about the rate adjust for clock drifts you brought up in your latest post.

Yesterday I opened a thread about a slightly different subject.

It's not related to the convolution. It's related to the recording and filter generation.
REW is using a timing reference chirp inside their sweep. That timing reference puts REW in the position to run a "rate-adjust" to clean up whatever clock drift.

Could Camilla somehow be used to match/rate-adjust the (an) original sweep and the recording.

Just by using e.g. file-in >> Camilla rate-adjust >> file-out >> DRC-Fir impulse response >> DRC-Fir filter

I would like to avoid REW (since there's no CLI) and run the whole recording and filter generation process scripted from commandline.

THX
Let's just make sure I understood it right. So REW can generate a sweep that includes an additional frequency sweep that runs simultaneously as the main one, and is only used as a timing fiducial? And it can use this to track drifts that happen during the sweep? I'll continue with the assumption that this is correct.

This could be corrected with the resampler from CamillaDSP. I would leave out CamillaDSP and just use the resampler. The resampler is a library, so you would need to write a simple app to handle input and output, maybe based on the example here: rubato/fixedin64.rs at master * HEnquist/rubato * GitHub
This part is relatively easy. It might also be possible to use Soxr.
The main challenge would be to analyze the waveform to extract the timing info. I don't have a good solution for how to do that part. Maybe some kind of heterodyne solution where you mix the signal with the original timing signal, low-pass filter the result and use this as feedback to the resampler... Doable but a challenge :)
 
This is a low-level USB protocol and all of that is handled by the USB driver.

Basically you have three options for a USB soundcard:

single independent internal clock: async capture, async playback - more expensive USB soundcards. Async playback can have either explicit or implicit feedback.

independent clock for capture only: async capture, adaptive playback - vast majority of USB soundcards. This mode allows receiving SPDIF (which is always clock master)

no internal clock, USB frame tick is used: adaptive capture, adaptive playback - I have never seen such a device
Hmm I assumed that any card that runs playback and capture at the same samplerate would use the same clock for both directions, but maybe that's not always so..

I have a cheap usb card with this chip in it: https://www.ti.com/lit/ds/symlink/p...=https%3A%2F%2Fwww.ti.com%2Fproduct%2FPCM2906
From what I understand, it uses adaptive playback, and asynchronous capture. It has a single PLL that locks to the USB bus, and the output of this is then fed to independant PLLs for capture and playback. This should then mean that even tough the capture is adaptive, it stays locked to the playback rate since the ADC is clocked from the same master PLL. This changes if the spdif input is used, then the capture rate is just the input rate on the spdif input.
To know for sure what the U7 does we would need a datasheet for the controller chip it uses. Does anyone have a link?
 
GitHub - HEnquist/camilladsp: A flexible linux IIR and FIR engine for crossovers, room correction etc.
Don't quite understand "control capture speed" if soundcard is clock master.
Is it communication between CamillaDSP and soundcard. Or is it "Monitor capture speed"?
It can control capture speed (should change that to "rate" to be more consistent) in two ways.
- If the capture device is an alsa loopback, then the samplerate is generated in software and the loopback exposes a control to fine-tune it. Then CamillaDSP uses this to continuously adjust the rate to match the playback device.
- If it's any other device (software or hardware), then the rate can't be changed. Then it must use the asyncronous resampler to emulate this. It can then for example resample from (let's make up some numbers) 48002.7 Hz of a capture device, to 48001.3 Hz of the playback device. This is also continuously updated to keep sync.
 
Thank you, phofman. Not easy to read, but very useful.
Wondering if the chunksize and target_level always should be larger than the USB wMaxPacketSize (for USB soundcards)?
Example from quote:
bNrChannels 8
bBitResolution 24
wMaxPacketSize 0x0270 1x 624 bytes
The sound library I use on windows and macos works a bit differently than Alsa. Instead of just writing to a fixed size buffer, it uses a callback. At more or less regular intervals it gives you a buffer of avarying length that it wants you to fill with audio data. On windows the length varies, IIRC around 500 - 1500 samples. On mac it seems fixed at 1024 samples. So on windows and macos a smaller chunksize that say 512 probably won't reduce the latency, only increase cpu load.



Target level is something else, it's how many frames should be left in the buffers when the next frame arrives. This can be a small value, but if it's too small it probably won't be able to maintain it and there is a risk of buffer underruns.


These params are related to the USB communication. I think the alsa usb driver does not allow minimum alsa period size to be below max packet size. I do not know what is relation of Henrik's chunksize and alsa period size. No idea what happens in windows but it will be similar.
The Alsa period size is set to the nearest allowed value of chunksize/4.
 
Let's just make sure I understood it right. So REW can generate a sweep that includes an additional frequency sweep that runs simultaneously as the main one, and is only used as a timing fiducial? And it can use this to track drifts that happen during the sweep? I'll continue with the assumption that this is correct.
That is not what it does. The Acoustic timing reference is a high frequency chirp that comes out of one specified speaker before the sine sweep begins to allow REW to back calculate delays between speakers not correct for clock drifts, here is no real time aspect to it. This was designed for USB mics where you can't use a soundcard loopback to achieve the same thing.

Making Measurements Scroll right to the bottom.
 
That is not what it does. The Acoustic timing reference is a high frequency chirp that comes out of one specified speaker before the sine sweep begins to allow REW to back calculate delays between speakers not correct for clock drifts, here is no real time aspect to it. This was designed for USB mics where you can't use a soundcard loopback to achieve the same thing.

Making Measurements Scroll right to the bottom.
Realized that after reading some more.. :eek:
 
I have a cheap usb card with this chip in it: https://www.ti.com/lit/ds/symlink/p...=https%3A%2F%2Fwww.ti.com%2Fproduct%2FPCM2906
From what I understand, it uses adaptive playback, and asynchronous capture. It has a single PLL that locks to the USB bus, and the output of this is then fed to independant PLLs for capture and playback. This should then mean that even tough the capture is adaptive, it stays locked to the playback rate since the ADC is clocked from the same master PLL. This changes if the spdif input is used, then the capture rate is just the input rate on the spdif input.

That is my (guessed) understanding of the PCM2906 clock structure too. That would mean for DAC/ADC loop the streams are synchronous.

To know for sure what the U7 does we would need a datasheet for the controller chip it uses. Does anyone have a link?

http://www.arrivalelectronics.co.uk/uploads/files/46043CM6632A_Datasheet_v1.2.pdf

Async IN/OUT, DAC/ADC clocked together, SPDIF independent. No idea what happens with the DAC clock when SPDIF IN. I could not find the full datasheet anywhere https://www.diyaudio.com/forums/digital-line-level/338917-usb-i2s-space-3.html#post5823102
 
@ Henrik:

There seems to be a "quirk" with the log output when updating the config through a websocket call.
If the requested config file is invalid for some reason, there will be no comment about the error in the log (using option -v).

I have seen this both when a config file is missing (misspelled), and when a config file has invalid content.
The same errors with the config file, do result in error messages in the log, if included in the start command for camilladsp.

Is this "by design" ?

The attached log file is from when a config file is missing.
 

Attachments

  • test-2.log.txt
    8.9 KB · Views: 63
@ Henrik:

There seems to be a "quirk" with the log output when updating the config through a websocket call.
If the requested config file is invalid for some reason, there will be no comment about the error in the log (using option -v).

I have seen this both when a config file is missing (misspelled), and when a config file has invalid content.
The same errors with the config file, do result in error messages in the log, if included in the start command for camilladsp.

Is this "by design" ?

The attached log file is from when a config file is missing.
Thanks! There were some log prints missing in the websocket server. I have just added them. The next beta (which is almost ready) will include them!