How to implement a series of second-order, digital state-variable filters, using the high-pass output from each section to effect the low-pass to high-pass transformation in MATLAB?
Hello, I am trying to implement the state-variable filters detailed in the picture I have attached. This to achieve a near-field correction based on the order of Ambisonics in use. As you will be able to see, the filter is implemented in FAUST and also involves feedback configurations as can be seen in the block diagram.
My knowledge of dsp, extends only from the project I have currently been working on and I'm also unaware of the FAUST programming language but understand the very very basics of how it is utilised. I am aware of the state-variable functions in MATLAB but I also note the feedback in the block diagram. I am trying to recreate the filter being implemented in FAUST but instead in MATLAB. Any assistance or even validation that this type of filter can be implemented in MATLAB would be much appreciated. Please forgive me if any of my above statements are incorrect.
---EDIT---
Based on sletz's advice, I copied the below code into the FAUST editor:
radius = 1.6;
SR_ = 48000;
SR = float(SR_);
temp_celcius = 20;
c = 331.3 * sqrt(1.0 + (temp_celcius/273.15));
process = nfcn(2, radius);
nfcn(2, radius) =
nfc2x(radius, 3, 3);
svf2(g,d1,d2) = _ : *(g) : (((_,_,_):> _ <: +~_, _ ) ~ *(d1) : +~_, _) ~ *(d2) : !,_ ;
nfc2x(radius,a1,a2) = svf2(g,d1,d2)
with {
omega = c/(float(radius)*SR);
r = omega/2.0;
b1 = a1 * r;
b2 = a2 * r * r;
g = 1.0 / (1.0 + b1 + b2);
d1 = 0.0 - (2.0*b1 + 4.0*b2) * g;
d2 = 0.0 - (4.0*b2) * g;
};
which produced an output in C++ of:
/* ------------------------------------------------------------
name: "exfaust0"
Code generated with Faust 2.28.0 (https://faust.grame.fr)
Compilation options: -lang cpp -scal -ftz 0
------------------------------------------------------------ */
#ifndef __mydsp_H__
#define __mydsp_H__
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif
#include <algorithm>
#include <cmath>
#ifndef FAUSTCLASS
#define FAUSTCLASS mydsp
#endif
#ifdef __APPLE__
#define exp10f __exp10f
#define exp10 __exp10
#endif
class mydsp : public dsp {
private:
float fRec5[2];
float fRec3[2];
float fRec2[2];
float fRec0[2];
int fSampleRate;
public:
void metadata(Meta* m) {
m->declare("filename", "exfaust0.dsp");
m->declare("name", "exfaust0");
}
virtual int getNumInputs() {
return 1;
}
virtual int getNumOutputs() {
return 1;
}
virtual int getInputRate(int channel) {
int rate;
switch ((channel)) {
case 0: {
rate = 1;
break;
}
default: {
rate = -1;
break;
}
}
return rate;
}
virtual int getOutputRate(int channel) {
int rate;
switch ((channel)) {
case 0: {
rate = 1;
break;
}
default: {
rate = -1;
break;
}
}
return rate;
}
static void classInit(int sample_rate) {
}
virtual void instanceConstants(int sample_rate) {
fSampleRate = sample_rate;
}
virtual void instanceResetUserInterface() {
}
virtual void instanceClear() {
for (int l0 = 0; (l0 < 2); l0 = (l0 + 1)) {
fRec5[l0] = 0.0f;
}
for (int l1 = 0; (l1 < 2); l1 = (l1 + 1)) {
fRec3[l1] = 0.0f;
}
for (int l2 = 0; (l2 < 2); l2 = (l2 + 1)) {
fRec2[l2] = 0.0f;
}
for (int l3 = 0; (l3 < 2); l3 = (l3 + 1)) {
fRec0[l3] = 0.0f;
}
}
virtual void init(int sample_rate) {
classInit(sample_rate);
instanceInit(sample_rate);
}
virtual void instanceInit(int sample_rate) {
instanceConstants(sample_rate);
instanceResetUserInterface();
instanceClear();
}
virtual mydsp* clone() {
return new mydsp();
}
virtual int getSampleRate() {
return fSampleRate;
}
virtual void buildUserInterface(UI* ui_interface) {
ui_interface->openVerticalBox("exfaust0");
ui_interface->closeBox();
}
virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) {
FAUSTFLOAT* input0 = inputs[0];
FAUSTFLOAT* output0 = outputs[0];
for (int i = 0; (i < count); i = (i + 1)) {
float fTemp0 = (0.993326426f * float(input0[i]));
float fTemp1 = ((0.0133768646f * fRec3[1]) + (5.95144447e-05f * fRec0[1]));
fRec5[0] = ((fRec5[1] + fTemp0) - fTemp1);
fRec3[0] = fRec5[0];
float fRec4 = (fTemp0 - fTemp1);
fRec2[0] = (fRec3[0] + fRec2[1]);
fRec0[0] = fRec2[0];
float fRec1 = fRec4;
output0[i] = FAUSTFLOAT(fRec1);
fRec5[1] = fRec5[0];
fRec3[1] = fRec3[0];
fRec2[1] = fRec2[0];
fRec0[1] = fRec0[0];
}
}
};
#endif
I note the compute stage which seems to be where the actual work of the signal flow diagram is being done. Unfortunately, I am not familiar with the C++ syntax so if anybody can offer any assistance, it would be greatly appreciated. I will continue to work through the code and some basic guides of C++ syntax so I can garner some insight in to the process being executed.