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

It keeps regulating the speed. It's a dumb P controller, so no I or D. If the ideal rate is 100.002%, it won't settle exactly at the target level. If there is a need I could add the I to make it converge better. I don't expect it to be needed though, it probably doesn't matter if it settles at 520 samples instead of 512.

Thanks for the confirmation, that will certainly do OK, a bit of control from time never hurts :)
 
Sure you can build the same filters with a bunch of Biquads.

For the tweeter you need to chain two Highpass filters for the 4:th order highpass, and then maybe replace the allpass with a simple delay. For the woofer you need a High- or LowShelf, and two chained Lowpass filters.

Of course.

BTW, looked the sources and (if I got it right) looks like you use Butterworth type LP/HP filters for IIR type filtering ... which does maybe not produce the best possible response as shown in attached comparison plot.

Here's Octave/Matlab code for the LR4 vs 4th order Butterworth response comparison I made (these are 4th order filters but one can transfer those to 2nd order sets):

Code:
pkg load signal
pkg load control

clf;

fs = 44100;
fc = 2500;

% Butterworth filters
[Lb, La] = butter (4, fc/(fs/2));
ButterLP4 = tf(Lb, La, 1/fs);
[Hb, Ha] = butter (4, fc/(fs/2), "high");
ButterHP4 = tf(Hb, Ha, 1/fs);

% Linkwitz-Riley filters
[b, a] = LR4_HP4(fs, fc);
HP4 = tf(b, a, 1/fs);
[b, a] = LR4_LP4(fs, fc);
LP4 = tf(b, a, 1/fs);

% sum response
LR4 = HP4 + LP4;
ButterLR4 = ButterLP4 + ButterHP4;

% coefficients
[b, a, T] = tfdata(LR4, 'v')
[b, a, T] = tfdata(ButterLR4, 'v')

nf = logspace(0, 5, fs/2);

figure(1);
[mag, pha] = bode(LP4,2*pi*nf);
semilogx(nf, 20*log10(abs(mag)), 'color', 'r', 'linewidth', 2, 'linestyle', '-');
hold on;
%semilogx(nf, pha, 'color', 'r','linewidth', 2 , 'linestyle', '--');
hold on;

[mag, pha] = bode(HP4,2*pi*nf);
semilogx(nf, 20*log10(abs(mag)), 'color', 'r', 'linewidth', 2, 'linestyle', '-');
%semilogx(nf, pha, 'color', 'b','linewidth', 2 , 'linestyle', '--');
hold on;

[mag, pha] = bode(LR4,2*pi*nf);
semilogx(nf, 20*log10(abs(mag)), 'color', 'g', 'linewidth', 2, 'linestyle', '-');
%semilogx(nf, pha, 'color', 'g','linewidth', 2 , 'linestyle', '--');
hold on;
[mag, pha] = bode(ButterLP4,2*pi*nf);
semilogx(nf, 20*log10(abs(mag)), 'color', 'k', 'linewidth', 2, 'linestyle', '--');
%semilogx(nf, pha, 'color', 'g','linewidth', k , 'linestyle', '--');
hold on;
[mag, pha] = bode(ButterHP4,2*pi*nf);
semilogx(nf, 20*log10(abs(mag)), 'color', 'k', 'linewidth', 2, 'linestyle', '--');
%semilogx(nf, pha, 'color', 'g','linewidth', k , 'linestyle', '--');
hold on;
[mag, pha] = bode(ButterLR4,2*pi*nf);
semilogx(nf, 20*log10(abs(mag)), 'color', 'b', 'linewidth', 2, 'linestyle', '--');
%semilogx(nf, pha, 'color', 'g','linewidth', k , 'linestyle', '--');

legend('LR4 LP', 'LR4 HP', 'LR4 SUM', 'Butterworth4 LP','Butterworth4 HP','Butterworth4 SUM',  'location', 'southwest');
axis([10 fs/2 -30 1]);
grid on;

% Linkwitz-Riley
Code:
function [b, a] = LR4_LP4(fs, fc)
  
wc=2*pi*fc;
wc2=wc*wc;
wc3=wc2*wc;
wc4=wc2*wc2;
k=wc/tan(pi*fc/fs);
k2=k*k;
k3=k2*k;
k4=k2*k2;
sqrt2=sqrt(2);
sq_tmp1=sqrt2*wc3*k;
sq_tmp2=sqrt2*wc*k3;
a_tmp=4*wc2*k2+2*sq_tmp1+k4+2*sq_tmp2+wc4;

b0 = 1;
b1=(4*(wc4+sq_tmp1-k4-sq_tmp2))/a_tmp;
b2=(6*wc4-8*wc2*k2+6*k4)/a_tmp;
b3=(4*(wc4-sq_tmp1+sq_tmp2-k4))/a_tmp;
b4=(k4-2*sq_tmp1+wc4-2*sq_tmp2+4*wc2*k2)/a_tmp;

a0=k4/a_tmp;
a1=-4*k4/a_tmp;
a2=6*k4/a_tmp;
a3=a1;
a4=a0;

a = [b0 b1 b2 b3 b4];
b = [a0 a1 a2 a3 a4];

endfunction

Code:
function [b, a] = LR4_HP4(fs, fc)

wc=2*pi*fc;
wc2=wc*wc;
wc3=wc2*wc;
wc4=wc2*wc2;
k=wc/tan(pi*fc/fs);
k2=k*k;
k3=k2*k;
k4=k2*k2;
sqrt2=sqrt(2);
sq_tmp1=sqrt2*wc3*k;
sq_tmp2=sqrt2*wc*k3;
a_tmp=4*wc2*k2+2*sq_tmp1+k4+2*sq_tmp2+wc4;
b0 = 1;
b1=(4*(wc4+sq_tmp1-k4-sq_tmp2))/a_tmp;
b2=(6*wc4-8*wc2*k2+6*k4)/a_tmp;
b3=(4*(wc4-sq_tmp1+sq_tmp2-k4))/a_tmp;
b4=(k4-2*sq_tmp1+wc4-2*sq_tmp2+4*wc2*k2)/a_tmp;

a0=wc4/a_tmp;
a1=4*wc4/a_tmp;
a2=6*wc4/a_tmp;
a3=a1;
a4=a0;

a = [b0 b1 b2 b3 b4];
b = [a0 a1 a2 a3 a4];

endfunction
 

Attachments

  • lr4-vs-butt4.png
    lr4-vs-butt4.png
    21.8 KB · Views: 248
Ah nice to see the rate control working!
What does the plot script show for your Rephase filters? What format are they in?
There is a new version that can handle raw files in a bunch of formats, just check out the "rawfiles" branch.
Mono filters should not cause any trouble at all. The cofficients file should anyway only contain coefficients for one channel.

Running new version from the RAW branch files.
What I am observing today and yesterday is fairly high output when mixed to mono.

This is what I used to mix to mono with Brutefir:


pcm.monocard{
slave.pcm "hw:Loopback,DEV=0"
slave.channels 2
type route
ttable {
# Copy both input channels to output channel 0 (Left).
0.0 0.5
1.0 0.5
# Copy both input to output channel 1 (Right).
0.1 0.5
1.1 0.5
}
}

pcm.!default monocard

It has to be set to 0.5 output, otherwise way to high output.
Does the Camilla config when mixing to mono also do this?
 
Oh sorry I wrote wrong! Should be "aplay", not "arecord"!
Code:
aplay -D sound_out --dump-hw-params some_wav_file.wav

Sry... i didn't make it yesterday :)

pi@SuperBPI:~/Cfilters $ aplay -D sound_out --dump-hw-params *wav
Playing WAVE 'file_example_WAV_1MG.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
HW Params of device "sound_out":
--------------------
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: [44100 48000]
PERIOD_TIME: [1000 2972155)
PERIOD_SIZE: [45 131072]
PERIOD_BYTES: [180 524288]
PERIODS: [2 1024]
BUFFER_TIME: [1875 5944309)
BUFFER_SIZE: [90 262144]
BUFFER_BYTES: [360 1048576]
TICK_TIME: ALL
--------------------
Warning: rate is not accurate (requested = 8000Hz, got = 44100Hz)
please, try the plug plugin (-Dplug:sound_out)

I've got this crappy new cheap dac working, but only with S16_LE, but nevermind that now, this is just for testing.
So all my "Alsa" configs are working, also when showing the .py script.

The playback are full of glitches, and perhaps i have to adjust the dac/squeezelite settings, BUT i would also like to try the output rate control, what do i have to "git" for trying that ?

Jesper.
 

Attachments

  • PY_Show.png
    PY_Show.png
    110.8 KB · Views: 255
Sry... i didn't make it yesterday :)



I've got this crappy new cheap dac working, but only with S16_LE, but nevermind that now, this is just for testing.
So all my "Alsa" configs are working, also when showing the .py script.

The playback are full of glitches, and perhaps i have to adjust the dac/squeezelite settings, BUT i would also like to try the output rate control, what do i have to "git" for trying that ?

Jesper.

Regarding CamillaDSP with Rate control feature, it's located under the the branch ''develop''.
 
Regarding CamillaDSP with Rate control feature, it's located under the the branch ''develop''.

Thanks...

I installed this version allready, how do you make it write out the buffer, like this you posted a while ago ?

Current buffer level 752, set capture rate to 100.027214%

I am not sure it's working with my .yml file?

devices:
samplerate: 44100
buffersize: 1024
target_level: 512
adjust_period: 10


capture:
type: Alsa
channels: 2
device: "camilla_in"
format: S16LE
playback:
type: Alsa
channels: 2
device: "sound_out"
format: S16LE

filters:
highpass_test:
type: Biquad
parameters:
type: Highpass
freq: 30
q: 0.5

pipeline:
- type: Filter
channel: 0
names:
- highpass_test
- type: Filter
channel: 1
names:
- highpass_test
 
Your settings under devices, target_level and adjust_period, are no different than mine, so I think it should..

Okay... The file plays, but do still glitch. but in your'e earlier post the output was like this
That and a fresh raspbian install did it.

Config is right, it was the fir filter that was wrong I think.
Tried it with your IIR filter, great sound!
I created the Fir filters in Rephase. In Brutefir I used .bin filters and those worked.
Probably the culprit is I need mono filters. Right?

Output Rate Control. Works very good, no glitches.

Prepare playback
Current buffer level 752, set capture rate to 100.027214%
Current buffer level 849, set capture rate to 100.03821%
Current buffer level 734, set capture rate to 100.02516%
Current buffer level 514, set capture rate to 100.00023%
Current buffer level 451, set capture rate to 99.99309%
Current buffer level 456, set capture rate to 99.99365%
Current buffer level 488, set capture rate to 99.99728%
Current buffer level 508, set capture rate to 99.99955%
Current buffer level 520, set capture rate to 100.00091%
Current buffer level 520, set capture rate to 100.00091%
Current buffer level 513, set capture rate to 100.00012%
Current buffer level 517, set capture rate to 100.00057%
Current buffer level 514, set capture rate to 100.00023%
Current buffer level 513, set capture rate to 100.00012%
Current buffer level 511, set capture rate to 99.999886%
Current buffer level 515, set capture rate to 100.00034%
Current buffer level 514, set capture rate to 100.00023%
Current buffer level 515, set capture rate to 100.00034%
Current buffer level 511, set capture rate to 99.999886%
Current buffer level 512, set capture rate to 100%
Current buffer level 512, set capture rate to 100%

I cannot see this on output?

Jesper.
 
[It might not be my testday, things are weird here :eek:]

Command line options

Starting with the --help flag prints a short help message:

> camilladsp --help
CamillaDSP 0.0.8
Henrik Enquist <henrik.enquist@gmail.com>
A flexible tool for processing audio

USAGE:
camilladsp [FLAGS] <configfile>

FLAGS:
-c, --check Check config file and exit
-h, --help Prints help information
-V, --version Prints version information
-v Increase message verbosity

ARGS:
<configfile> The configuration file to use

pi@SuperBPI:~/Cfilters $ camilladsp --help highpass.yml
Config file error:
Could not open config file!
pi@SuperBPI:~/Cfilters $ camilladsp --help
Config file error:
Could not open config file!
pi@SuperBPI:~/Cfilters $ camilladsp -h
Config file error:
Could not open config file!
pi@SuperBPI:~/Cfilters $ camilladsp -h highpass.yml
Config file error:
Could not open config file!

Have no clue why this is not working
 
BTW, looked the sources and (if I got it right) looks like you use Butterworth type LP/HP filters for IIR type filtering ... which does maybe not produce the best possible response as shown in attached comparison plot.

Here's Octave/Matlab code for the LR4 vs 4th order Butterworth response comparison I made (these are 4th order filters but one can transfer those to 2nd order sets):

Forgot to note that LR4_HP4 filter implementation presented in quoted post has bad LF issue when value of fc is set to less than 1/63 * fs/2 (i.e. 350Hz @ 44.1kHz) ....
 
Of course.

BTW, looked the sources and (if I got it right) looks like you use Butterworth type LP/HP filters for IIR type filtering ... which does maybe not produce the best possible response as shown in attached comparison plot.
The High- and Lowpass filters have adjustable Q so they can be anything you like. For example to make a 4:th order Butterworth you chain one with Q=0.54 and one with Q=1.31. I'm making a table of the most common types that will be included in the readme for the next version.
 
This is a really cool thread and software, thanks Henrik.

What is wrong here ?

pi@SuperBPI:~/Cfilters $ camilladsp highpass.yml
build filters, waiting to start processing loop
starting playback loop
starting captureloop
Prepare playback
Prepare playback
^C
pi@SuperBPI:~/Cfilters $ camilladsp -v highpass.yml
Config file error:
Could not open config file!
pi@SuperBPI:~/Cfilters $

Playback are working, but not flags.

Jesper.
 
Running new version from the RAW branch files.
What I am observing today and yesterday is fairly high output when mixed to mono.

This is what I used to mix to mono with Brutefir:


pcm.monocard{
slave.pcm "hw:Loopback,DEV=0"
slave.channels 2
type route
ttable {
# Copy both input channels to output channel 0 (Left).
0.0 0.5
1.0 0.5
# Copy both input to output channel 1 (Right).
0.1 0.5
1.1 0.5
}
}

pcm.!default monocard

It has to be set to 0.5 output, otherwise way to high output.
Does the Camilla config when mixing to mono also do this?
The config for the mono-mixer I posted attenuates both channels by 6dB, so should give the same as your BruteFIR config. Do you get clipping warnings?
 
The config for the mono-mixer I posted attenuates both channels by 6dB, so should give the same as your BruteFIR config. Do you get clipping warnings?

Understood.

Still the sound with Repahse generated filter (opposed to your IIR filters) is not the way it should.
What filter in Rephase should work best in Camilladsp ?
Brutefir takes the .bin files and sounds good.

Rephase.jpg