Hi! So RonnieX = Lokathor? I have seen that you have been contributing quite a bit to simd in Rust 🙂Hi all
Rust is a main topic of mine, and I wrote some of the SIMD libs which you might want to use (https://github.com/Lokathor/wide) for performance; Rust is great at threading so maybe I can take a look at the code on that?
The heaviest parts of Camillladsp is the FFT/iFFT steps used for convolution and synchronous resampling (from RustFFT), and the multiply-accumulate steps in the asynchronous resampler. These are already using AVX, SSE or Neon if available (almost, Neon is nearly done for RustFFT).
Some other parts could be accelerated too but the overall benefit would be quite small. Considering that I prefer to keep the code simpler.
I would like to break the processing pipeline up into more than a single thread at some point. That will take some thinking since most steps in the pipeline depend on the previous one.
HenrikEnquist,This is just how convolution works. Mathematically it's equivalent to convolve a signal first with one IR and then another, as to first convolve the two IRs and then convolve the signal with that result.
Let's say both IRs consist of a large main feature in the middle, surrounded by smaller wiggles that get smaller and smaller towards each end. To calculate the discrete convolution of them, we slide one over the other. For each step, we multiply all elements, and then sum all the products. This sum is one point of the result. The first point is when the IRs overlap in just a single point, and the last point is when they have passed so only the last points overlap. This gives lenth1+lenght2 new points.
Because the wiggles at the start and end of the IRs are of small amplitude, the result will have very very low amplitude far from the center. You should be able to truncate it back down to the length of the IRs you started with, just apply a window function to make sure the ends go to zero.
Thanks much. That helps. I tweaked the DRC-FIR code to optionally merge a supplied RePhase XO with the target solution it generates so the XO defines the correction gating. I looked at how it's code calculated the RMS value and the center value. The RMS code just walks all of the samples from beginning to end searching for the sample and position with the largest absolute value of all of the (64-bit floats) samples. Once the centering value was right, the test convolutions snapped into place. I then compared that DRC-FIR modified result with the CamillaDSP result (after realizing it could be done in CamillaDSP). The results of the 2 are very close, but the modified code file length is off by 1 sample so I have some more work to do [(2 x #taps) - 1 versus (2 x #taps)].
My assumption was the following would happen [ sample c = sample a convolve sample b]:
IR1 - aaaaaaaaaaaaaAAAAAAAAAAAAAAaaaaaaaaaaaaa
IR2 - bbbbbbbbbbbbbBBBBBBBBBBBBBBbbbbbbbbbbbbb
SUM - cccccccccccccCCCCCCCCCCCCCCccccccccccccc
But if I understand your response correctly, the following would happen:
IR1 - aaaaaaaaaaaaaAAAAAAAAAAAAAAaaaaaaaaaaaaa
IR2 - bbbbbbbbbbbbbBBBBBBBBBBBBBBbbbbbbbbbbbbb
SUM - ccccccccccccccccccccccccccCCCCCCCCCCCCCCCCCCCCCCCCCCCCcccccccccccccccccccccccccc
Which can be windowed down to something like this:
SUM - cccccCCCCCCCCCCCCCCCCCCCCCCCCCCCCccccccc
Check the actual values, I would bet that the extra value in the longer one is a zero at either start or end.The results of the 2 are very close, but the modified code file length is off by 1 sample so I have some more work to do [(2 x #taps) - 1 versus (2 x #taps)].
Yes correct!But if I understand your response correctly, the following would happen:
IR1 - aaaaaaaaaaaaaAAAAAAAAAAAAAAaaaaaaaaaaaaa
IR2 - bbbbbbbbbbbbbBBBBBBBBBBBBBBbbbbbbbbbbbbb
SUM - ccccccccccccccccccccccccccCCCCCCCCCCCCCCCCCCCCCCCCCCCCcccccccccccccccccccccccccc
Which can be windowed down to something like this:
SUM - cccccCCCCCCCCCCCCCCCCCCCCCCCCCCCCccccccc
Check the actual values, I would bet that the extra value in the longer one is a zero at either start or end.
Yes correct!
It depends on how you define zero. =)
The printouts below only print out differing indexes (e.g. index [1 & 2] are both zero, thus omitted).
Beginning of both files:
Code:
INDEX CamillaDSP Merge DRC-FIR-MOD Merge
[0000000] -0.000000000000000000027105 ?= 0.000000000000000000000000
[0000003] -0.000000000000000000027105 ?= 0.000000000000000000000000
[0000004] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000006] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000008] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000009] 0.000000000000000000027105 ?= 0.000000000000000000000000
[0000010] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000011] -0.000000000000000000054210 ?= 0.000000000000000000000000
[0000016] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000018] 0.000000000000000000027105 ?= 0.000000000000000000000000
[0000019] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000020] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000021] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000023] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000025] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000026] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000027] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000029] -0.000000000000000000027105 ?= 0.000000000000000000000000
[0000031] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000032] -0.000000000000000000027105 ?= 0.000000000000000000000000
[0000033] -0.000000000000000000013553 ?= 0.000000000000000000000000
[0000034] -0.000000000000000000013553 ?= 0.000000000000000000000000
Leading edge where second merge transitions from all-zeros to non-zeros at index 84,420 with a center sample @ 262,144.
Code:
INDEX CamillaDSP Merge DRC-FIR-MOD Merge
[0084807] -0.000000000231745564208937 ?= 0.000000000000000000000000
[0084808] -0.000000000231836689473423 ?= 0.000000000000000000000000
[0084809] -0.000000000231927804393042 ?= 0.000000000000000000000000
[0084810] -0.000000000232018908999877 ?= 0.000000000000000000000000
[0084811] -0.000000000232110003233046 ?= 0.000000000000000000000000
[0084812] -0.000000000232201087091332 ?= 0.000000000000000000000000
[0084813] -0.000000000232292160558535 ?= 0.000000000000000000000000
[0084814] -0.000000000232383223626291 ?= 0.000000000000000000000000
[0084815] -0.000000000232474276263472 ?= 0.000000000000000000000000
[0084816] -0.000000000232565318476960 ?= 0.000000000000000000000000
[0084817] -0.000000000232656350263895 ?= 0.000000000000000000000000
[0084818] -0.000000000232747371579704 ?= 0.000000000000000000000000
[0084819] -0.000000000232838382369275 ?= 0.000000000000000000000000
[0084820] -0.000000000232929382718635 ?= -0.000000000465661287307739
[0084821] -0.000000000233020372547688 ?= -0.000000000465661287307739
[0084822] -0.000000000233111351857068 ?= -0.000000000465661287307739
[0084823] -0.000000000233202320621311 ?= -0.000000000465661287307739
[0084824] -0.000000000233293278813789 ?= -0.000000000465661287307739
[0084825] -0.000000000233384226471295 ?= -0.000000000465661287307739
[0084826] -0.000000000233475163564446 ?= -0.000000000465661287307739
[0084827] -0.000000000233566090021935 ?= -0.000000000465661287307739
[0084828] -0.000000000233657005878594 ?= -0.000000000465661287307739
[0084829] -0.000000000233747911120713 ?= -0.000000000465661287307739
[0084830] -0.000000000233838805699588 ?= -0.000000000465661287307739
[0084831] -0.000000000233929689626017 ?= -0.000000000465661287307739
The center of the files mound up together and taper in reverse order of the preceding dumps.
Code:
INDEX CamillaDSP Merge DRC-FIR-MOD Merge
[0438702] 0.000000000234196688609010 ?= 0.000000000465661287307739
[0438703] 0.000000000234072690078163 ?= 0.000000000465661287307739
[0438704] 0.000000000233948688711343 ?= 0.000000000465661287307739
[0438705] 0.000000000233824684533485 ?= 0.000000000465661287307739
[0438706] 0.000000000233700677508221 ?= 0.000000000465661287307739
[0438707] 0.000000000233576667724752 ?= 0.000000000465661287307739
[0438708] 0.000000000233452655142634 ?= 0.000000000465661287307739
[0438709] 0.000000000233328639805223 ?= 0.000000000465661287307739
[0438710] 0.000000000233204621740631 ?= 0.000000000465661287307739
[0438711] 0.000000000233080600942505 ?= 0.000000000465661287307739
[0438712] 0.000000000232956577433079 ?= 0.000000000465661287307739
[0438713] 0.000000000232832551220136 ?= 0.000000000000000000000000
[0438714] 0.000000000232708522375885 ?= 0.000000000000000000000000
[0438715] 0.000000000232584490849504 ?= 0.000000000000000000000000
[0438716] 0.000000000232460456669951 ?= 0.000000000000000000000000
[0438717] 0.000000000232336419895301 ?= 0.000000000000000000000000
[0438718] 0.000000000232212380517561 ?= 0.000000000000000000000000
[0438719] 0.000000000232088338538687 ?= 0.000000000000000000000000
[0438720] 0.000000000231964293993039 ?= 0.000000000000000000000000
[0438721] 0.000000000231840246897028 ?= 0.000000000000000000000000
[0438722] 0.000000000231716197257748 ?= 0.000000000000000000000000
[0438723] 0.000000000231592145130149 ?= 0.000000000000000000000000
[0438724] 0.000000000231468090476646 ?= 0.000000000000000000000000
[0438730] 0.000000000230723711030715 ?= 0.000000000000000000000000
Might this be the difference between Linear and Minimum Phase merges ???
Last edited:
Those differences look like they could be just numerical noise. Is drc-fir using f32 or f64 internally?
It is configured to use f64, but can optionally use f32.Those differences look like they could be just numerical noise. Is drc-fir using f32 or f64 internally?
Actually, it seems like there is an integer step somewhere in the DRC-FIR version.
0.000000000465661287307739 = 2^-31, that's what you get if you use 32-bit signed integers and then convert to floats in the range -1.0 .. 1.0.
0.000000000465661287307739 = 2^-31, that's what you get if you use 32-bit signed integers and then convert to floats in the range -1.0 .. 1.0.
Actually, it seems like there is an integer step somewhere in the DRC-FIR version.
0.000000000465661287307739 = 2^-31, that's what you get if you use 32-bit signed integers and then convert to floats in the range -1.0 .. 1.0.
Thanks for the tip.
I will check both source FIRs for similar behavior as inspect the source that merged them. One source is from DRC-FIR and one is from RePhase.
It appears to come from using SoX to convert between raw PCM and WAV.Actually, it seems like there is an integer step somewhere in the DRC-FIR version.
0.000000000465661287307739 = 2^-31, that's what you get if you use 32-bit signed integers and then convert to floats in the range -1.0 .. 1.0.
SoX should ideally just add/remove a header when switching between the 2 without changing sample rate, bits, format, etc.
IMO for SoX a file conversion is like any other chain - input -> processing ->output, where the processing stage applies no effects. The SoX internal format is int32.
"... The SoX internal format is int32. ..." 🙁IMO for SoX a file conversion is like any other chain - input -> processing ->output, where the processing stage applies no effects. The SoX internal format is int32.
Int32 is losing precision.
Time to file a bug/enhancement report to bring SoX out of the 90's.
I am writing my own code to switch between WAV and PCM that just strips the headers and meta-data footers to convert to PCM and adds a WAV header to convert to WAV so the raw data is left unscathed for when I don't have to change anything else.
I have been using SoX for over a decade and never had a usecase where int32 would not suffice. Your case is extremely special, IMO.Int32 is losing precision.
Time to file a bug/enhancement report to bring SoX out of the 90's.
I am afraid changing the internal inter-effect format would be a very large change (effects use other formats internally as needed, int32 is for passing samples (type sample_t)). You can file a report, but I would expect a response of the kind "patch welcome" 🙂
f64 in general is not "extremely special". It is a standard numerical format and more audio tools are going all 64-bit (including CamillaDSP, JRMC, and RePhase).I have been using SoX for over a decade and never had a usecase where int32 would not suffice. Your case is extremely special, IMO.
I am afraid changing the internal inter-effect format would be a very large change (effects use other formats internally as needed, int32 is for passing samples (type sample_t)). You can file a report, but I would expect a response of the kind "patch welcome" 🙂
Henrik was able to catch the issue by just looking at a partial hexdump of an IR.
I plan to download the code and take a look at how much work is involved and have no problem issuing a patch. Acceptance of the patch is another thing. DRC-FIR uses #ifdef/#define types to swap between f32 and f64 builds. SoX should be able to do similar especially since they offer misleading f64 "pseduo-support". False advertising.
When converting between WAV and PCM and back (with no other changes), the PCM payload data should not be touched, but it is. No different than switching between WAV, FLAC and back to WAV. The audio data should remain the same (sans the meta data tags, headers and footers). That I consider a bug. Correct functionality for that conversion could be archived with int8 code (which is what I am using in the converter app I just wrote for 16, 32 and 64-bit payload formats).
I have just started using Camilladsp, intended use is to perform crossover for active 3-way replacing a miniDSP miniSHARC DSP. Experiments so far all good using Moode and front-ending wit squeezelite, gaining a reasonable understanding of the SW.
However I need to be able to feed Camilladsp with the frequency sweep out of REW running on my laptop. I am trying to get Camilladsp to take input from a USB ADC (cheap headphone/mic adapter) but not successful.
Here is the output from arecord for the USB device
And here is the pipeline I am using
I get no errors but no output from Camilla. Any help or suggestions greatly appreciated.
However I need to be able to feed Camilladsp with the frequency sweep out of REW running on my laptop. I am trying to get Camilladsp to take input from a USB ADC (cheap headphone/mic adapter) but not successful.
Here is the output from arecord for the USB device
Code:
**** List of CAPTURE Hardware Devices ****
card 3: Device [USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
Code:
Recording WAVE '/dev/null' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "hw:Device":
--------------------
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 16
CHANNELS: 1
RATE: [44100 48000]
PERIOD_TIME: [1000 5944309)
PERIOD_SIZE: [45 262144]
PERIOD_BYTES: [90 524288]
PERIODS: [2 1024]
BUFFER_TIME: [1875 11888617)
BUFFER_SIZE: [90 524288]
BUFFER_BYTES: [180 1048576]
TICK_TIME: ALL
--------------------
arecord: set_params:1339: Sample format non available
Available formats:
- S16_LE
And here is the pipeline I am using
Code:
devices:
adjust_period: 10
capture:
avoid_blocking_read: false
channels: 1
device: hw:3,0
format: S16LE
retry_on_error: false
type: Alsa
capture_samplerate: 0
chunksize: 1024
enable_rate_adjust: false
enable_resampling: false
playback:
channels: 2
device: hw:Headphones,0
format: S16LE
type: Alsa
queuelimit: 1
rate_measure_interval: 1
resampler_type: Synchronous
samplerate: 44100
silence_threshold: -60
silence_timeout: 3
stop_on_rate_change: false
target_level: 0
filters:
gain:
parameters:
gain: 10
inverted: false
mute: false
type: Gain
vol:
parameters:
ramp_time: 200
type: Volume
mixers:
stereo:
channels:
in: 1
out: 2
mapping:
- dest: 0
mute: false
sources:
- channel: 0
gain: 6
inverted: false
mute: false
- dest: 1
mute: false
sources:
- channel: 0
gain: 6
inverted: false
mute: false
pipeline:
- name: stereo
type: Mixer
- channel: 0
names:
- gain
- vol
type: Filter
- channel: 1
names:
- gain
- vol
type: Filter
I get no errors but no output from Camilla. Any help or suggestions greatly appreciated.
Try enabling balancedasync resampling, every time I've used physically separate capture and playback devicse I've needed to do that. Also, any reason you cannot just run REW on the device running CamillaDSP? It is not the fastest but I've been able to do it with a RPi4.
Michael
Michael
Thanks Michael (once again!).
Tried balancedsync and also using the same device as capture/playback, no joy. I notice the state is "offline". When using with squeezelite I get the volume level bars but not with the USB input. Am I missing some step here?
Tried balancedsync and also using the same device as capture/playback, no joy. I notice the state is "offline". When using with squeezelite I get the volume level bars but not with the USB input. Am I missing some step here?
For just recording a sweep I would guess asynchronous resampling would not be needed. Typically it's possible to run glitch-free for a few minutes without it.
The config looks fine. Does the USB input device have a volume control that is muted or set very low? Can you record anything useful from it with arecord?
The config looks fine. Does the USB input device have a volume control that is muted or set very low? Can you record anything useful from it with arecord?
I have tested the USB device on my Linux laptop using loopback I was able to feed music in from my cellphone and listen via the laptop speaker.
I will try arecord on the Rpi and see if I can record anything.
I will try arecord on the Rpi and see if I can record anything.
Managed to use arecord to record and play back the file on my laptop but struggling to do same on the Rpi (records but unable to successfully play back). I used alsamixer to set the volume to 100% on the mic but to no avail.
Coming back to the status, when I switch to the config for squeezelite and activate squeezelite renderer the status goes to "running" and I get music. With the config for the USB input it remains "offline" no matter what I do. Is there some action necessary to get the status to running for the USB input?
Coming back to the status, when I switch to the config for squeezelite and activate squeezelite renderer the status goes to "running" and I get music. With the config for the USB input it remains "offline" no matter what I do. Is there some action necessary to get the status to running for the USB input?
If it is offline that typically means it doesn't like something about the configuration file. Are you saying if you start CamillaDSP from the command line you get no errors?
Although if you are using Moode I think it may show this when nothing is playing as well.
Michael
Although if you are using Moode I think it may show this when nothing is playing as well.
Michael
- Home
- Source & Line
- PC Based
- CamillaDSP - Cross-platform IIR and FIR engine for crossovers, room correction etc