いわゆるフィルター。
一般的なものが最低限揃っている。
ソースを見る
class maxiFilter {
double gain;
double input;
double output;
double inputs[10];
double outputs[10];
double cutoff1;
double x;//speed
double y;//pos
double z;//pole
double c;//filter coefficient
public:
maxiFilter():x(0.0), y(0.0), z(0.0), c(0.0){};
double cutoff;
double resonance;
double lores(double input,double cutoff1, double resonance);
double hires(double input,double cutoff1, double resonance);
double bandpass(double input,double cutoff1, double resonance);
double lopass(double input,double cutoff);
double hipass(double input,double cutoff);
};
//I particularly like these. cutoff between 0 and 1
double maxiFilter::lopass(double input, double cutoff) {
output=outputs[0] + cutoff*(input-outputs[0]);
outputs[0]=output;
return(output);
}
//as above
double maxiFilter::hipass(double input, double cutoff) {
output=input-(outputs[0] + cutoff*(input-outputs[0]));
outputs[0]=output;
return(output);
}
//awesome. cuttof is freq in hz. res is between 1 and whatever. Watch out!
double maxiFilter::lores(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
if (cutoff<10) cutoff=10;
if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
double r=(sqrt(2.0)*sqrt(-pow((z-1.0),3.0))+resonance*(z-1))/(resonance*(z-1));
x=x+(input-y)*c;
y=y+x;
x=x*r;
output=y;
return(output);
}
//working hires filter
double maxiFilter::hires(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
if (cutoff<10) cutoff=10;
if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
double r=(sqrt(2.0)*sqrt(-pow((z-1.0),3.0))+resonance*(z-1))/(resonance*(z-1));
x=x+(input-y)*c;
y=y+x;
x=x*r;
output=input-y;
return(output);
}
//This works a bit. Needs attention.
double maxiFilter::bandpass(double input,double cutoff1, double resonance) {
cutoff=cutoff1;
if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance>=1.) resonance=0.999999;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
inputs[0] = (1-resonance)*(sqrt(resonance*(resonance-4.0*pow(z,2.0)+2.0)+1));
inputs[1] = 2*z*resonance;
inputs[2] = pow((resonance*-1),2);
output=inputs[0]*input+inputs[1]*outputs[1]+inputs[2]*outputs[2];
outputs[2]=outputs[1];
outputs[1]=output;
return(output);
}
フィルタの実装
他にフィルタを実装しているライブラリを見て
参考にしようと探したところ
Robert Bristow-Johnsonという方が「RBJ Audio EQ Cookbook」というテキストにまとめているようだ。
説明は下記がわかりやすい。
上記を参考にソースを追ってみたい。
関数を読み解く
と、いろいろ調べていたところで
どうもMaximilianのローパス・ハイパスフィルタはもっとお手軽に実装しているようだ。
//I particularly like these. cutoff between 0 and 1
double maxiFilter::lopass(double input, double cutoff) {
output=outputs[0] + cutoff*(input-outputs[0]);
outputs[0]=output;
return(output);
}
//as above
double maxiFilter::hipass(double input, double cutoff) {
output=input-(outputs[0] + cutoff*(input-outputs[0]));
outputs[0]=output;
return(output);
}
output[0] + cutoff*(input-output[0])
となっている。
これは、加算平均というデジタルフィルタで、主にノイズの除去に使われている
計算に似ている。
しかし加算平均であれば
output[0]*(1-cutoff) + cuoff*(input-output[0])
とすべきだが、それをもっとお手軽にした形なのだろう。
ま、そういうものということで、この二つはいいかと思う。
次にlores,hiresをみよう。
//awesome. cuttof is freq in hz. res is between 1 and whatever. Watch out!
double maxiFilter::lores(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
if (cutoff<10) cutoff=10;
if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
double r=(sqrt(2.0)*sqrt(-pow((z-1.0),3.0))+resonance*(z-1))/(resonance*(z-1));
x=x+(input-y)*c;
y=y+x;
x=x*r;
output=y;
return(output);
}
//working hires filter
double maxiFilter::hires(double input,double cutoff1, double resonance) {
cutoff=cutoff1*0.5;
if (cutoff<10) cutoff=10;
if (cutoff>(maxiSettings::sampleRate*0.5)) cutoff=(maxiSettings::sampleRate*0.5);
if (resonance<1.) resonance = 1.;
z=cos(TWOPI*cutoff/maxiSettings::sampleRate);
c=2-2*z;
double r=(sqrt(2.0)*sqrt(-pow((z-1.0),3.0))+resonance*(z-1))/(resonance*(z-1));
x=x+(input-y)*c;
y=y+x;
x=x*r;
output=input-y;
return(output);
}