// 以下は、フィルターの計算をする部分 void __fastcall TForm1::filter3( int pos) { int k0,l0; int c2; float x0,y0; char *spc; short *sp; int eq0; float dummy; spc= (char*)pPlaybackBuffer+pos; sp=(short *) spc;    // 波形データを示すポインター if( filter_flag == true){ if( nchannel==2) c2 = DATABLOCK_SIZE / 4; else c2= DATABLOCK_SIZE / 2; for(k0=0;k0< c2; ++k0) { if( nchannel == 2) // ステレオ 2チャネルのとき { // add type like lpf, hpf, bpf dummy=0.0; for(eq0=0;eq0 32767.) dummy=32767.; else if( dummy < -32768.) dummy= -32768.; sp[2 * k0] = (short ) dummy; // 2チャネルの残りのチャンネルの分も同様に計算する。 dummy=0.; for(eq0=0;eq0 32767.) dummy=32767.; else if( dummy < -32768.) dummy= -32768.; sp[2 * k0 + 1] = (short)dummy; } else   // モノ 1チャネルのとき { dummy=0.; for(eq0=0;eq0 32767.) dummy=32767.; else if( dummy < -32768.) dummy= -32768.; sp[k0] = (short) dummy; } } } } // 以下は、アナログのBPF HPF LPF APF のフィルターの係数を求めるもの。 /* w0= 2 * pai * f0 */ int __fastcall TForm1::set_bpf_ana(double g0, double w0, double q0, double x[], double y[]) { if( q0 ==0.0) { Memo1->Lines->Add(" error:input will occure zero divide , In set_bpf_ana "); return -1; } y[0]=0.0; y[1]= g0 * w0 / q0; y[2]=0.0; x[0]=1.0; x[1]= w0 / q0; x[2]= w0 * w0; return 0; } int __fastcall TForm1::set_hpf_ana(double g0, double w0, double q0, double x[], double y[]) { if( q0 ==0.0) { Memo1->Lines->Add(" error:input will occure zero divide , In set_hpf_ana "); return -1; } if ( xorder == 1) // フィルターの次数が1次の場合 { // 1-st order hpf y[0]= g0; y[1]= 0.0; y[2]= 0.0; x[0]= 1.0; x[1]= w0; x[2]= 0.0 ; } else  // フィルターの次数が2次の場合 { // 2-nd order hpf y[0]= g0; y[1]= 0.0; y[2]=0.0; x[0]=1.0; x[1]= w0 / q0; x[2]= w0 * w0; } return 0; } int __fastcall TForm1:: set_lpf_ana(double g0, double w0, double q0, double x[], double y[]) { if( q0 ==0.0) { Memo1->Lines->Add(" error:input will occure zero divide , In set_lpf_ana "); return -1; } if ( xorder == 1) { // 1-st order lpf y[0]=0.0; y[1]= g0 * w0; y[2]= 0.0; x[0]= 1.0; x[1]= w0; x[2]= 0.0 ; }else { // 2-nd order lpf y[0]=0.0; y[1]= 0.0; y[2]= w0 * w0 * g0; x[0]=1.0; x[1]= w0 / q0; x[2]= w0 * w0; } return 0; } int __fastcall TForm1:: set_apf_ana(double g0, double w0, double q0, double x[], double y[]) { if( q0 ==0.0) { Memo1->Lines->Add("\n error:input will occure zero divide , In set_apf_ana\n"); return -1; } if ( xorder == 1) { // 1-st order apf y[0]= g0; y[1]= -1.0 * g0 * w0; y[2]= 0.0; x[0]= 1.0; x[1]= w0; x[2]= 0.0 ; }else { // 2-nd order apf y[0]= g0; y[1]= -1.0* (w0 / q0) * g0 ; y[2]= w0 * w0 * g0; x[0]=1.0; x[1]= w0 / q0; x[2]= w0 * w0; } return 0; } //双一次変換でずれてしまう周波数を補正するためのもの。 double __fastcall TForm1::souitizi_trans(double w0, double t0) /* w0 is target f0 * 2 * PAI */ /* t0 is sampling frequency */ { double wout; wout = ((w0/(2.0 * 3.141592)) / (1.0 / t0)) * 2.0 * 3.141592; /* w0-> digital w he */ wout = tan( wout /2.0); wout = (wout * 2.0 / t0); return( wout); } // 以下は、デジタルのフィルターの係数を求めるもの。 double __fastcall TForm1::set_hpf_dig( double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; /* cal new _w0, and t0 */ t0x= 1.0/fs; new_w0 = souitizi_trans( w0, t0x); /* cal analog x,y */ set_hpf_ana(g0,new_w0,q0, x0, y0); if ( xorder == 1 ) { y[0]=y0[0]; y[1]= -1.0 * y0[0]; y[2]= 0.0; x[0]= (t0x * x0[1] / 2.0) + 1.0; x[1]= (t0x * x0[1] / 2.0 ) - 1.0; x[2]=0.0; }else { /* cal X */ y[0]= (4.0 * y0[0] / ( t0x * t0x)); y[1]= ( -8.0 * y0[0] / ( t0x * t0x)); y[2]= (4.0 * y0[0] / ( t0x * t0x)); /* cal Y */ x[0]= (4.0/ (t0x * t0x) ) + (2.0 * x0[1] / t0x) + x0[2]; x[1]= (-8.0 / t0x /t0x) + (2.0 * x0[2]); x[2]= (4.0/ (t0x * t0x) ) + (-2.0 * x0[1] / t0x) + x0[2]; } /* 直接形その1へ */ if( x[0] == 0.0) { Memo1->Lines->Add(" error:0 divide will happen! In set_bpf_dig "); return -1.0; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); } double __fastcall TForm1::set_bpf_dig(double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; /* cal new _w0, and t0 */ t0x= 1.0/fs; /* cal analog x,y */ set_bpf_ana(g0,new_w0,q0, x0, y0); /* cal X */ y[0]= (2.0 * y0[1] / t0x) + y0[2]; y[1]= 2.0 * y0[2]; y[2]= (-2.0 * y0[1] / t0x) + y0[2]; /* cal Y */ x[0]= (4.0/ (t0x * t0x) ) + (2.0 * x0[1] / t0x) + x0[2]; x[1]= (-8.0 / t0x /t0x) + (2.0 * x0[2]); x[2]= (4.0/ (t0x * t0x) ) + (-2.0 * x0[1] / t0x) + x0[2]; /* 直接形その1へ */ if( x[0] == 0.0) { Memo1->Lines->Add(" error:0 divide will happen! In set_bpf_dig "); return -1.0; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); } double __fastcall TForm1::set_lpf_dig(double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; /* cal new _w0, and t0 */ t0x= 1.0/fs; new_w0 = souitizi_trans( w0, t0x); /* cal analog x,y */ set_lpf_ana(g0,new_w0,q0, x0, y0); if ( xorder == 1) { y[0]=y0[1]; y[1]=y0[1]; y[2]=0.0; x[0]= (2.0 / t0x) + x0[1]; x[1]= x0[1] - (2.0 / t0x); x[2]=0.0; } else { /* cal X */ y[0]= (2.0 * y0[1] / t0x) + y0[2]; y[1]= 2.0 * y0[2]; y[2]= (-2.0 * y0[1] / t0x) + y0[2]; /* cal Y */ x[0]= (4.0/ (t0x * t0x) ) + (2.0 * x0[1] / t0x) + x0[2]; x[1]= (-8.0 / t0x /t0x) + (2.0 * x0[2]); x[2]= (4.0/ (t0x * t0x) ) + (-2.0 * x0[1] / t0x) + x0[2]; } /* 直接形その1へ */ if( x[0] == 0.0) { Memo1->Lines->Add(" error:0 divide will happen! In set_bpf_dig "); return -1.0;; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); } double __fastcall TForm1::set_apf_dig(double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; /* cal new _w0, and t0 */ t0x= 1.0/fs; new_w0 = souitizi_trans( w0, t0x); /* cal analog x,y */ set_apf_ana(g0,new_w0,q0, x0, y0); if ( xorder == 1) { y[0]= (2.0 / t0x) * y0[0] + y0[1]; y[1]= -1.0 * (2.0 / t0x) * y0[0] + y0[1]; y[2]=0.0; x[0]= (2.0 / t0x) + x0[1]; x[1]= x0[1] - (2.0 / t0x); x[2]=0.0; } else { /* cal X */ y[0]= ((4.0/ (t0x * t0x) ) * y0[0]) + (2.0 * y0[1] / t0x) + y0[2]; y[1]= ((-8.0 / t0x /t0x) * y0[0]) + (2.0 * y0[2]); y[2]= (4.0/ (t0x * t0x) * y0[0]) + (-2.0 * y0[1] / t0x) + y0[2]; /* cal Y */ x[0]= (4.0/ (t0x * t0x) ) + (2.0 * x0[1] / t0x) + x0[2]; x[1]= (-8.0 / t0x /t0x) + (2.0 * x0[2]); x[2]= (4.0/ (t0x * t0x) ) + (-2.0 * x0[1] / t0x) + x0[2]; } /* hyokusetu gata sono 1 he henkei */ if( x[0] == 0.0) { Memo1->Lines->Add("\nerror:0 divide will happen! In set_apf_dig\n"); return -1.0;; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); } /****************************************************************/ /* Second order Low shelf /* /* Q=Qb , 1-> 1/A, W= Wb * sqrt(A) /* ・・・・ /* ------------------------------------- /* s^2 + (sqrt(A)/Q) * (1/A) * S + 1/A /****************************************************************/ double __fastcall TForm1::set_low_shelf_dig(double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; double omega,sn,cs,alpha,beta; double A; if ( g0 > 0 ) A=sqrt(g0); else { Memo1->Lines->Add("Error: g0 is 0 or minus."); A=1.; // force to set 1 g0=1.0; } if( xorder == 2) { /* change Wb to W */ w0 = w0 * sqrt(sqrt(g0)); } /* cal new _w0, and t0 */ t0x= 1.0/fs; new_w0 = souitizi_trans( w0, t0x); omega= new_w0 / fs; sn = sin(omega); cs = cos(omega); alpha = sn / (2.0 * q0); beta = sqrt(sqrt(g0)) / q0; if ( xorder == 1) { if( g0 >= 1.0) { y[0] = 1.0 + g0 * new_w0 * t0x; y[1] = g0 * new_w0 * t0x - 1.0; y[2] = 0.0; x[0] = 1 + new_w0 * t0x; x[1] = new_w0 * t0x - 1.0; x[2] = 0.0; } else { g0 = 1.0 / g0; x[0] = 1.0 + g0 * new_w0 * t0x; x[1] = g0 * new_w0 * t0x - 1.0; x[2] = 0.0; y[0] = 1 + new_w0 * t0x; y[1] = new_w0 * t0x - 1.0; y[2] = 0.0; } } else { /* cal X */ y[0] = (A * ((A + 1.0) - (A - 1.0) * cs + beta * sn)); y[1] = ( 2.0 * A * ((A - 1.0) - (A + 1.0) * cs)); y[2] = ( A * ((A + 1.0) - (A - 1.0) * cs - beta * sn)); /* cal Y */ x[0] = ((A + 1.0) + (A - 1.0) * cs + beta * sn); x[1] = ( -2.0 * ((A - 1.0f) + (A + 1.0) * cs)); x[2] = ((A + 1.f) + (A - 1.0) * cs - beta * sn); } /* 直接形その1へ */ if( x[0] == 0.0) { Memo1->Lines->Add(" error:0 divide will happen! In set_bpf_dig "); return -1.0; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); } /****************************************************************/ /* Second order High shelf /* /* Q=Qb , 1-> A, W= Wb/sqrt(A) /* ・・・・ /* --------------------- /* s^2 + sqrt(A)/Q S + A /****************************************************************/ double __fastcall TForm1::set_high_shelf_dig(double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; double omega,sn,cs,alpha,beta; double A; if ( g0 > 0 ) A=sqrt(g0); else { Memo1->Lines->Add("Error: g0 is 0 or minus."); A=1.; // force to set 1 g0=1.0; } if( xorder == 2) { /* change Wb to W */ w0 = w0 / sqrt(sqrt(g0)); } /* cal new _w0, and t0 */ t0x= 1.0/fs; new_w0 = souitizi_trans( w0, t0x); omega= new_w0 / fs; sn = sin(omega); cs = cos(omega); alpha = sn / (2.0 * q0); beta = sqrt(sqrt(g0)) / q0; if ( xorder == 1) { if( g0 >= 1.0) { y[0] = g0 + new_w0 * t0x; y[1] = new_w0 * t0x - g0; y[2] = 0.0; x[0] = 1 + new_w0 * t0x; x[1] = new_w0 * t0x - 1.0; x[2] = 0.0; } else { g0 = 1.0 / g0; x[0] = g0 + new_w0 * t0x; x[1] = new_w0 * t0x - g0; x[2] = 0.0; y[0] = 1 + new_w0 * t0x; y[1] = new_w0 * t0x - 1.0; y[2] = 0.0; } } else { /* cal X */ y[0] = A * ((A + 1.0) + (A - 1.0) * cs + beta * sn); y[1] = - 2.0 * A * ((A - 1.0) + (A + 1.0) * cs); y[2] = A * ((A + 1.0) + (A - 1.0) * cs - beta * sn); /* cal Y */ x[0] = (A + 1.0f) - (A - 1.0) * cs + beta * sn; x[1] = 2.0 * ((A - 1.0) - (A + 1.0) * cs); x[2] = (A + 1.0) - (A - 1.0) * cs - beta * sn; } /* 直接形その1へ */ if( x[0] == 0.0) { Memo1->Lines->Add(" error:0 divide will happen! In set_bpf_dig "); return -1.0; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); } //--- /****************************************************************/ /* /* Peaking = L.P.F. + B.P.F. + L.P.F. /* /* Q=Qb/A, G0= A^2 /* /* S^2 + A/Q S + 1 S^2 G0 S 1 /* --------------- = ----------------- + ----------------- + ---------------- /* s^2 + 1/AQ S + 1 S^2 + 1/Qb S + 1 S^2 + 1/Qb S + 1 S^2 + 1/Qb S + 1 /* /****************************************************************/ double __fastcall TForm1::set_peaking_dig(double fs, double g0, double w0, double q0, double x[], double y[]) { static double new_w0,t0x,x0[10],y0[10]; double omega,sn,cs,alpha,beta; /* change Qb to Q */ q0 = q0 / sqrt(g0); /* cal new _w0, and t0 */ t0x= 1.0/fs; new_w0 = souitizi_trans( w0, t0x); omega= new_w0 / fs; sn = sin(omega); cs = cos(omega); alpha = sn / (2.0 * q0); beta = sqrt(sqrt(g0)) / q0; double A; if ( g0 > 0 ) A=sqrt(g0); else { Memo1->Lines->Add("Error: g0 is 0 or minus."); A=1.; // force to set 1 } /* cal X */ y[0] = 1.0 + alpha * A; y[1] = - 2.0 * cs; y[2] = 1.0 - alpha * A; /* cal Y */ x[0] = 1.0 + alpha / A; x[1] = - 2.0 * cs; x[2] = 1.0 - alpha / A; /* 直接形その1へ */ if( x[0] == 0.0) { Memo1->Lines->Add(" error:0 divide will happen! In set_bpf_dig "); return -1.0; } y[0]=y[0]/x[0]; y[1]=y[1]/x[0]; y[2]=y[2]/x[0]; x[1]= -1.0 * x[1]/x[0]; x[2]= -1.0 * x[2]/x[0]; x[0]=x[0]/x[0]; return(t0x); }