mmtty/fir.cpp
2013-07-05 15:00:12 -05:00

2182 lines
47 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//Copyright+LGPL
//-----------------------------------------------------------------------------------------------------------------------------------------------
// Copyright 2000-2013 Makoto Mori, Nobuyuki Oba
//-----------------------------------------------------------------------------------------------------------------------------------------------
// This file is part of MMTTY.
// MMTTY is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
// MMTTY is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License along with MMTTY. If not, see
// <http://www.gnu.org/licenses/>.
//-----------------------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <math.h>
#include "fir.h"
//-------------------------------------------------
// FIRフィルタのたたき込み演算
double __fastcall DoFIR(double *hp, double *zp, double d, int tap)
{
memcpy(zp, &zp[1], sizeof(double)*tap);
zp[tap] = d;
d = 0.0;
for( int i = 0; i <= tap; i++, hp++, zp++ ){
d += (*zp) * (*hp);
}
return d;
}
//---------------------------------------------------------------------------
CIIRTANK::CIIRTANK()
{
b1 = b2 = a0 = z1 = z2 = 0;
SetFreq(2000.0, SampFreq, 50.0);
}
//---------------------------------------------------------------------------
void CIIRTANK::SetFreq(double f, double smp, double bw)
{
double lb1, lb2, la0;
lb1 = 2 * exp(-PI * bw/smp) * cos(2 * PI * f / smp);
lb2 = -exp(-2*PI*bw/smp);
if( bw ){
#if 0
const double _gt[]={18.0, 26.0, 20.0, 20.0};
la0 = sin(2 * PI * f/smp) / (_gt[SampType] * 50 / bw);
#else
la0 = sin(2 * PI * f/smp) / ((smp/6.0) / bw);
#endif
}
else {
la0 = sin(2 * PI * f/smp);
}
b1 = lb1; b2 = lb2; a0 = la0;
}
//---------------------------------------------------------------------------
double CIIRTANK::Do(double d)
{
d *= a0;
d += (z1 * b1);
d += (z2 * b2);
z2 = z1;
if( fabs(d) < 1e-37 ) d = 0.0;
z1 = d;
return d;
}
//---------------------------------------------------------------------------
CLMS::CLMS()
{
Z = new double[TAPMAX+1];
H = new double[TAPMAX+1];
D = new double[DELAYMAX+1];
memset(Z, 0, sizeof(double[TAPMAX+1]));
memset(H, 0, sizeof(double[TAPMAX+1]));
memset(D, 0, sizeof(double[DELAYMAX+1]));
m_lmsADJSC = 1.0 / double(32768 * 32768); // スケール調整値
m_lmsErr = m_lmsMErr = 0;
m_Type = 1; // 0-LMS, 1-NOTICH
m_lmsNotch = 0;
m_lmsNotch2 = 0;
m_twoNotch = 0;
m_Tap = 56;
m_NotchTap = 72;
m_lmsInv = 0;
m_lmsDelay = 0; // LMS Delay
m_lmsAGC = 0; // LMS AGC
m_lmsMU2 = 0.003; // LMS 2μ
m_lmsGM = 0.9999; // LMS γ
m_bpf = 1;
SetWindow(2125, 2125+170);
}
CLMS::~CLMS()
{
delete[] D;
delete[] H;
delete[] Z;
}
void CLMS::Copy(CLMS &other)
{
m_Type = other.m_Type;
m_Tap = other.m_Tap;
m_NotchTap = other.m_NotchTap;
m_lmsInv = other.m_lmsInv; // LMS InvOutput
m_lmsDelay = other.m_lmsDelay; // LMS Delay
m_lmsAGC = other.m_lmsAGC; // LMS AGC
m_lmsMU2 = other.m_lmsMU2; // LMS 2μ
m_lmsGM = other.m_lmsGM; // LMS γ
m_lmsNotch = other.m_lmsNotch;
m_lmsNotch2 = other.m_lmsNotch2;
m_twoNotch = other.m_twoNotch;
m_bpf = other.m_bpf;
SetWindow(m_MarkFreq, m_SpaceFreq);
}
void CLMS::GetFW(double &fl, double &fh, double fq)
{
double fw;
if( fq < m_MarkFreq ){
fw = m_MarkFreq - fq;
if( fw < 80.0 ){
fw = 15.0;
}
else {
fw *= 0.5;
}
}
else if( fq > m_SpaceFreq ){
fw = fq - m_SpaceFreq;
if( fw < 80.0 ){
fw = 15.0;
}
else {
fw *= 0.5;
}
}
else {
fq = (m_MarkFreq + m_SpaceFreq)/2.0;
fw = 15.0;
}
fh = fq + fw;
fl = fq - fw;
}
void CLMS::SetWindow(double mfq, double sfq)
{
m_MarkFreq = mfq;
m_SpaceFreq = sfq;
if( m_Type ){
if( m_lmsNotch && (m_lmsNotch2 == m_lmsNotch) ) m_lmsNotch2 = 0;
double fl, fh;
double c = (m_MarkFreq + m_SpaceFreq)/2;
if( !m_lmsNotch || ((m_lmsNotch >= m_MarkFreq) && (m_lmsNotch <= m_SpaceFreq)) ){
m_lmsNotch = c;
GetFW(fl, fh, c);
MakeFilter(H, m_NotchTap, ffBEF, SampFreq, fl, fh, 10, 1.0);
if( (m_lmsNotch2 >= m_MarkFreq) && (m_lmsNotch2 <= m_SpaceFreq) ){
m_lmsNotch2 = 0;
}
if( m_lmsNotch2 ){
GetFW(fl, fh, m_lmsNotch2);
MakeFilter(HBPF, m_NotchTap, ffBEF, SampFreq, fl, fh, 10, 1.0);
}
}
else {
GetFW(fl, fh, m_lmsNotch);
MakeFilter(H, m_NotchTap, ffBEF, SampFreq, fl, fh, 10, 1.0);
if( (m_lmsNotch2 >= m_MarkFreq) && (m_lmsNotch2 <= m_SpaceFreq) ){
m_lmsNotch2 = c;
}
if( m_lmsNotch2 ){
GetFW(fl, fh, m_lmsNotch2);
MakeFilter(HBPF, m_NotchTap, ffBEF, SampFreq, fl, fh, 10, 1.0);
}
}
}
else {
MakeFilter(HBPF, m_Tap, ffBPF, SampFreq, m_MarkFreq - 150, m_SpaceFreq + 150, 60, 0.00002);
}
}
//-------------------------------------------------
// 適応フィルタの演算
double CLMS::Do(double d)
{
double a = 0.0;
int i;
double *zp = Z;
double *hp = H;
if( m_Type ){
if( !m_NotchTap ) return d; // スルーの時
// ノッチフィルタ
memcpy(Z, &Z[1], sizeof(double)*m_NotchTap);
Z[m_NotchTap] = d;
for( i = 0; i <= m_NotchTap; i++, zp++, hp++ ){
a += (*zp) * (*hp);
}
if( m_lmsNotch2 && m_twoNotch ){
memcpy(D, &D[1], sizeof(double)*m_NotchTap);
D[m_NotchTap] = a;
zp = D;
hp = HBPF;
a = 0;
for( i = 0; i <= m_NotchTap; i++, zp++, hp++ ){
a += (*zp) * (*hp);
}
}
return a;
}
else {
if( !m_Tap ) return d; // スルーの時
// トランスバーサルフィルタ
memcpy(Z, &Z[1], sizeof(double)*m_Tap);
Z[m_Tap] = D[0];
for( i = 0; i <= m_Tap; i++, zp++, hp++ ){
a += (*zp) * (*hp);
}
}
// 誤差計算
m_lmsErr = d - a;
m_lmsMErr = m_lmsErr * m_lmsMU2 * m_lmsADJSC; // lmsADJSC = 1/(32768 * 32768) スケーリング調整値
// 遅延器の移動
if( m_lmsDelay ) memcpy(D, &D[1], sizeof(double)*m_lmsDelay);
D[m_lmsDelay] = d;
// 係数更新
zp = Z;
hp = H;
if( m_lmsAGC ){
double sum = 0.0;
for( i = 0; i <= m_Tap; i++, zp++, hp++ ){
*hp = (m_lmsMErr * (*zp)) + (*hp * m_lmsGM);
if( m_bpf ) *hp += HBPF[i];
sum += fabs(*hp);
}
if( sum >= 1e-3 ) a /= sum;
}
else {
for( i = 0; i <= m_Tap; i++, zp++, hp++ ){
*hp = (m_lmsMErr * (*zp)) + (*hp * m_lmsGM);
if( m_bpf ) *hp += HBPF[i];
}
}
return m_lmsInv ? m_lmsErr : a;
}
//*********************************************************************
// CDECM2 1/2デシメータ処理クラス
//
CDECM2::CDECM2()
{
memset(Z1, 0, sizeof(Z1));
memset(Z2, 0, sizeof(Z2));
::MakeFilter(H, 36, ffLPF, SampFreq, 2900, 3000, 70, 1.0);
}
double CDECM2::Do(double d1, double d2)
{
memcpy(Z1, &Z1[1], sizeof(double)*18);
memcpy(Z2, &Z2[1], sizeof(double)*17);
Z1[18] = d1;
Z2[17] = d2;
double a;
a = Z1[0] * H[36];
a += Z2[0] * H[35];
a += Z1[1] * H[34];
a += Z2[1] * H[33];
a += Z1[2] * H[32];
a += Z2[2] * H[31];
a += Z1[3] * H[30];
a += Z2[3] * H[29];
a += Z1[4] * H[28];
a += Z2[4] * H[27];
a += Z1[5] * H[26];
a += Z2[5] * H[25];
a += Z1[6] * H[24];
a += Z2[6] * H[23];
a += Z1[7] * H[22];
a += Z2[7] * H[21];
a += Z1[8] * H[20];
a += Z2[8] * H[19];
a += Z1[9] * H[18];
a += Z2[9] * H[17];
a += Z1[10] * H[16];
a += Z2[10] * H[15];
a += Z1[11] * H[14];
a += Z2[11] * H[13];
a += Z1[12] * H[12];
a += Z2[12] * H[11];
a += Z1[13] * H[10];
a += Z2[13] * H[9];
a += Z1[14] * H[8];
a += Z2[14] * H[7];
a += Z1[15] * H[6];
a += Z2[15] * H[5];
a += Z1[16] * H[4];
a += Z2[16] * H[3];
a += Z1[17] * H[2];
a += Z2[17] * H[1];
a += Z1[18] * H[0];
return a;
}
#if 0
//*********************************************************************
// CDECM2H 1/2デシメータ処理クラス 64tap
//
CDECM2H::CDECM2H()
{
memset(Z1, 0, sizeof(Z1));
memset(Z2, 0, sizeof(Z2));
::MakeFilter(H, 64, ffLPF, SampFreq, 2900, 3000, 70, 1.0);
}
double CDECM2H::Do(double d1, double d2)
{
memcpy(Z1, &Z1[1], sizeof(double)*32);
memcpy(Z2, &Z2[1], sizeof(double)*31);
Z1[32] = d1;
Z2[31] = d2;
double a;
a = Z1[0] * H[64];
a += Z2[0] * H[63];
a += Z1[1] * H[62];
a += Z2[1] * H[61];
a += Z1[2] * H[60];
a += Z2[2] * H[59];
a += Z1[3] * H[58];
a += Z2[3] * H[57];
a += Z1[4] * H[56];
a += Z2[4] * H[55];
a += Z1[5] * H[54];
a += Z2[5] * H[53];
a += Z1[6] * H[52];
a += Z2[6] * H[51];
a += Z1[7] * H[50];
a += Z2[7] * H[49];
a += Z1[8] * H[48];
a += Z2[8] * H[47];
a += Z1[9] * H[46];
a += Z2[9] * H[45];
a += Z1[10] * H[44];
a += Z2[10] * H[43];
a += Z1[11] * H[42];
a += Z2[11] * H[41];
a += Z1[12] * H[40];
a += Z2[12] * H[39];
a += Z1[13] * H[38];
a += Z2[13] * H[37];
a += Z1[14] * H[36];
a += Z2[14] * H[35];
a += Z1[15] * H[34];
a += Z2[15] * H[33];
a += Z1[16] * H[32];
a += Z2[16] * H[31];
a += Z1[17] * H[30];
a += Z2[17] * H[29];
a += Z1[18] * H[28];
a += Z2[18] * H[27];
a += Z1[19] * H[26];
a += Z2[19] * H[25];
a += Z1[20] * H[24];
a += Z2[20] * H[23];
a += Z1[21] * H[22];
a += Z2[21] * H[21];
a += Z1[22] * H[20];
a += Z2[22] * H[19];
a += Z1[23] * H[18];
a += Z2[23] * H[17];
a += Z1[24] * H[16];
a += Z2[24] * H[15];
a += Z1[25] * H[14];
a += Z2[25] * H[13];
a += Z1[26] * H[12];
a += Z2[26] * H[11];
a += Z1[27] * H[10];
a += Z2[27] * H[9];
a += Z1[28] * H[8];
a += Z2[28] * H[7];
a += Z1[29] * H[6];
a += Z2[29] * H[5];
a += Z1[30] * H[4];
a += Z2[30] * H[3];
a += Z1[31] * H[2];
a += Z2[31] * H[1];
a += Z1[32] * H[0];
return a;
}
#endif
#if 0
//*********************************************************************
// CINTP2 ×2インタポーレータ処理クラス
//
CINTP2::CINTP2()
{
memset(Z, 0, sizeof(Z));
::MakeFilter(H, 36, ffLPF, SampFreq, 2900, 3000, 70, 2.0);
}
void CINTP2::Do(double &d1, double &d2, double d)
{
memcpy(Z, &Z[1], sizeof(double)*18);
Z[18] = d;
d1 = Z[0] * H[36];
d2 = Z[1] * H[35];
d1 += Z[1] * H[34];
d2 += Z[2] * H[33];
d1 += Z[2] * H[32];
d2 += Z[3] * H[31];
d1 += Z[3] * H[30];
d2 += Z[4] * H[29];
d1 += Z[4] * H[28];
d2 += Z[5] * H[27];
d1 += Z[5] * H[26];
d2 += Z[6] * H[25];
d1 += Z[6] * H[24];
d2 += Z[7] * H[23];
d1 += Z[7] * H[22];
d2 += Z[8] * H[21];
d1 += Z[8] * H[20];
d2 += Z[9] * H[19];
d1 += Z[9] * H[18];
d2 += Z[10] * H[17];
d1 += Z[10] * H[16];
d2 += Z[11] * H[15];
d1 += Z[11] * H[14];
d2 += Z[12] * H[13];
d1 += Z[12] * H[12];
d2 += Z[13] * H[11];
d1 += Z[13] * H[10];
d2 += Z[14] * H[9];
d1 += Z[14] * H[8];
d2 += Z[15] * H[7];
d1 += Z[15] * H[6];
d2 += Z[16] * H[5];
d1 += Z[16] * H[4];
d2 += Z[17] * H[3];
d1 += Z[17] * H[2];
d2 += Z[18] * H[1];
d1 += Z[18] * H[0];
}
//*********************************************************************
// CDECM3 1/3デシメータ処理クラス
//
CDECM3::CDECM3()
{
memset(Z1, 0, sizeof(Z1));
memset(Z2, 0, sizeof(Z2));
memset(Z3, 0, sizeof(Z3));
::MakeFilter(H, 48, ffLPF, SampFreq, 1300, 3000, 70, 1.0);
}
double CDECM3::Do(double d1, double d2, double d3)
{
memcpy(Z1, &Z1[1], sizeof(double)*16);
memcpy(Z2, &Z2[1], sizeof(double)*15);
memcpy(Z3, &Z3[1], sizeof(double)*15);
Z1[16] = d1;
Z2[15] = d2;
Z3[15] = d3;
double a;
a = Z1[0] * H[48];
a += Z3[0] * H[47];
a += Z2[0] * H[46];
a += Z1[1] * H[45];
a += Z3[1] * H[44];
a += Z2[1] * H[43];
a += Z1[2] * H[42];
a += Z3[2] * H[41];
a += Z2[2] * H[40];
a += Z1[3] * H[39];
a += Z3[3] * H[38];
a += Z2[3] * H[37];
a += Z1[4] * H[36];
a += Z3[4] * H[35];
a += Z2[4] * H[34];
a += Z1[5] * H[33];
a += Z3[5] * H[32];
a += Z2[5] * H[31];
a += Z1[6] * H[30];
a += Z3[6] * H[29];
a += Z2[6] * H[28];
a += Z1[7] * H[27];
a += Z3[7] * H[26];
a += Z2[7] * H[25];
a += Z1[8] * H[24];
a += Z3[8] * H[23];
a += Z2[8] * H[22];
a += Z1[9] * H[21];
a += Z3[9] * H[20];
a += Z2[9] * H[19];
a += Z1[10] * H[18];
a += Z3[10] * H[17];
a += Z2[10] * H[16];
a += Z1[11] * H[15];
a += Z3[11] * H[14];
a += Z2[11] * H[13];
a += Z1[12] * H[12];
a += Z3[12] * H[11];
a += Z2[12] * H[10];
a += Z1[13] * H[9];
a += Z3[13] * H[8];
a += Z2[13] * H[7];
a += Z1[14] * H[6];
a += Z3[14] * H[5];
a += Z2[14] * H[4];
a += Z1[15] * H[3];
a += Z3[15] * H[2];
a += Z2[15] * H[1];
a += Z1[16] * H[0];
return a;
}
//*********************************************************************
// CINTP3 ×3インタポーレータ処理クラス
//
CINTP3::CINTP3()
{
memset(Z, 0, sizeof(Z));
::MakeFilter(H, 48, ffLPF, SampFreq, 1300, 3000, 70, 3.0);
}
void CINTP3::Do(double &d1, double &d2, double &d3, double d)
{
memcpy(Z, &Z[1], sizeof(double)*16);
Z[16] = d;
d1 = Z[0] * H[48];
d3 = Z[1] * H[47];
d2 = Z[1] * H[46];
d1 += Z[1] * H[45];
d3 += Z[2] * H[44];
d2 += Z[2] * H[43];
d1 += Z[2] * H[42];
d3 += Z[3] * H[41];
d2 += Z[3] * H[40];
d1 += Z[3] * H[39];
d3 += Z[4] * H[38];
d2 += Z[4] * H[37];
d1 += Z[4] * H[36];
d3 += Z[5] * H[35];
d2 += Z[5] * H[34];
d1 += Z[5] * H[33];
d3 += Z[6] * H[32];
d2 += Z[6] * H[31];
d1 += Z[6] * H[30];
d3 += Z[7] * H[29];
d2 += Z[7] * H[28];
d1 += Z[7] * H[27];
d3 += Z[8] * H[26];
d2 += Z[8] * H[25];
d1 += Z[8] * H[24];
d3 += Z[9] * H[23];
d2 += Z[9] * H[22];
d1 += Z[9] * H[21];
d3 += Z[10] * H[20];
d2 += Z[10] * H[19];
d1 += Z[10] * H[18];
d3 += Z[11] * H[17];
d2 += Z[11] * H[16];
d1 += Z[11] * H[15];
d3 += Z[12] * H[14];
d2 += Z[12] * H[13];
d1 += Z[12] * H[12];
d3 += Z[13] * H[11];
d2 += Z[13] * H[10];
d1 += Z[13] * H[9];
d3 += Z[14] * H[8];
d2 += Z[14] * H[7];
d1 += Z[14] * H[6];
d3 += Z[15] * H[5];
d2 += Z[15] * H[4];
d1 += Z[15] * H[3];
d3 += Z[16] * H[2];
d2 += Z[16] * H[1];
d1 += Z[16] * H[0];
}
#endif
/**********************************************************************
FIRフィルタ設計関数
**********************************************************************/
/*
====================================================
ベッセル関数
====================================================
*/
static double I0(double x)
{
double sum, xj;
int j;
sum = 1.0;
xj = 1.0;
j = 1;
while(1){
xj *= ((0.5 * x) / (double)j);
sum += (xj*xj);
j++;
if( ((0.00000001 * sum) - (xj*xj)) > 0 ) break;
}
return(sum);
}
/*
====================================================
FIRフィルタの設計
====================================================
*/
void MakeFilter(double *HP, int tap, int type, double fs, double fcl, double fch, double att, double gain)
{
FIR fir;
fir.typ = type;
fir.n = tap;
fir.fs = fs;
fir.fcl = fcl;
fir.fch = fch;
fir.att = att;
fir.gain = gain;
MakeFilter(HP, &fir);
}
void MakeFilter(double *HP, FIR *fp)
{
int j, m;
double alpha, win, fm, w0, sum;
double *hp;
if( fp->typ == ffHPF ){
fp->fc = 0.5*fp->fs - fp->fcl;
}
else if( fp->typ != ffLPF ){
fp->fc = (fp->fch - fp->fcl)/2.0;
}
else {
fp->fc = fp->fcl;
}
if( fp->att >= 50.0 ){
alpha = 0.1102 * (fp->att - 8.7);
}
else if( fp->att >= 21 ){
alpha = (0.5842 * pow(fp->att - 21.0, 0.4)) + (0.07886 * (fp->att - 21.0));
}
else {
alpha = 0.0;
}
hp = fp->hp;
sum = PI*2.0*fp->fc/fp->fs;
if( fp->att >= 21 ){ // インパルス応答と窓関数を計算
for( j = 0; j <= (fp->n/2); j++, hp++ ){
fm = (double)(2 * j)/(double)fp->n;
win = I0(alpha * sqrt(1.0-(fm*fm)))/I0(alpha);
if( !j ){
*hp = fp->fc * 2.0/fp->fs;
}
else {
*hp = (1.0/(PI*(double)j))*sin((double)j*sum)*win;
}
}
}
else { // インパルス応答のみ計算
for( j = 0; j <= (fp->n/2); j++, hp++ ){
if( !j ){
*hp = fp->fc * 2.0/fp->fs;
}
else {
*hp = (1.0/(PI*(double)j))*sin((double)j*sum);
}
}
}
hp = fp->hp;
sum = *hp++;
for( j = 1; j <= (fp->n/2); j++, hp++ ) sum += 2.0 * (*hp);
hp = fp->hp;
if( sum > 0.0 ){
for( j = 0; j <= (fp->n/2); j++, hp++ ) (*hp) /= sum;
}
// 周波数変換
if( fp->typ == ffHPF ){
hp = fp->hp;
for( j = 0; j <= (fp->n/2); j++, hp++ ) (*hp) *= cos((double)j*PI);
}
else if( fp->typ != ffLPF ){
w0 = PI * (fp->fcl + fp->fch) / fp->fs;
if( fp->typ == ffBPF ){
hp = fp->hp;
for( j = 0; j <= (fp->n/2); j++, hp++ ) (*hp) *= 2.0*cos((double)j*w0);
}
else {
hp = fp->hp;
*hp = 1.0 - (2.0 * (*hp));
for( hp++, j = 1; j <= (fp->n/2); j++, hp++ ) (*hp) *= -2.0*cos((double)j*w0);
}
}
for( m = fp->n/2, hp = &fp->hp[m], j = m; j >= 0; j--, hp-- ){
*HP++ = (*hp) * fp->gain;
}
for( hp = &fp->hp[1], j = 1; j <= (fp->n/2); j++, hp++ ){
*HP++ = (*hp) * fp->gain;
}
}
//---------------------------------------------------------------------------
//FIRフィルタ(ヒルベルト変換フィルタ)の設計
// Added by JE3HHT on Aug.2010
void __fastcall MakeHilbert(double *H, int N, double fs, double fc1, double fc2)
{
int L = N / 2;
double T = 1.0 / fs;
double W1 = 2 * PI * fc1;
double W2 = 2 * PI * fc2;
// 2*fc2*T*SA((n-L)*W2*T) - 2*fc1*T*SA((n-L)*W1*T)
double w;
int n;
double x1, x2;
for( n = 0; n <= N; n++ ){
if( n == L ){
x1 = x2 = 0.0;
}
else if( (n - L) ){
x1 = ((n - L) * W1 * T);
x1 = cos(x1) / x1;
x2 = ((n - L) * W2 * T);
x2 = cos(x2) / x2;
}
else {
x1 = x2 = 1.0;
}
w = 0.54 - 0.46 * cos(2*PI*n/(N));
H[n] = -(2 * fc2 * T * x2 - 2 * fc1 * T * x1) * w;
}
if( N < 8 ){
w = 0;
for( n = 0; n <= N; n++ ){
w += fabs(H[n]);
}
if( w ){
w = 1.0 / w;
for( n = 0; n <= N; n++ ){
H[n] *= w;
}
}
}
}
//---------------------------------------------------------------------
// 周波数特性グラフ(フィルタスレッド内でコールしてはいけない)
//
// H(ejωT) = [Σ0]Hm cos(mωT) - j[Σ1]Hm sin(mωT)
//
void DrawGraph(Graphics::TBitmap *pBitmap, const double *H, int Tap, int Over, int &nmax, int init, TColor col)
{
int k, x, y;
double f, gdb, g, pi2t, fs;
double max;
char bf[80];
TCanvas *tp = pBitmap->Canvas;
TRect rc;
rc.Left = 0;
rc.Right = pBitmap->Width;
rc.Top = 0;
rc.Bottom = pBitmap->Height;
if( init ){
tp->Brush->Color = clWhite;
tp->FillRect(rc);
}
int LM; // 周波数表示のあるライン数
int DM; // 内部線の数
int MM; // 実線の間隔
switch(Over){
case 2:
max = 3000;
fs = SampFreq/2.0;
break;
case 3:
max = 2000;
fs = SampFreq/3.0;
break;
default:
max = 4000;
fs = SampFreq;
break;
}
if( nmax ){
max = nmax;
}
else {
nmax = max;
}
switch(nmax){
case 3000:
LM = 3;
DM = 14;
MM = 5;
break;
case 100:
case 200:
case 2000:
LM = 4;
DM = 19;
MM = 5;
break;
case 400:
case 800:
case 4000:
LM = 4;
DM = 19;
MM = 5;
break;
default: // 6000
LM = 3;
DM = 11;
MM = 4;
break;
}
int XL = 32;
int XR = pBitmap->Width - 16;
int YT = 16;
int YB = pBitmap->Height - 24;
int i;
if( init ){
tp->Pen->Color = clBlack;
tp->Font->Size = 8;
tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT);
tp->Pen->Color = clGray;
for( i = 0; i < 7; i++ ){
tp->Pen->Style = (i & 1) ? psSolid : psDot;
y = (int)(double(i + 1) * double(YB - YT)/8.0 + YT);
tp->MoveTo(XL, y); tp->LineTo(XR, y);
}
for( i = 1; i < 5; i++ ){
y = (int)(double(i) * double(YB - YT)/4.0 + YT);
sprintf( bf, "-%2u", (80 / 4)*i );
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf);
}
strcpy(bf, "dB");
tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf);
for( i = 1; i <= DM; i++ ){
tp->Pen->Style = (i % MM) ? psDot : psSolid;
x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL);
tp->MoveTo(x, YT); tp->LineTo(x, YB);
}
for( i = 0; i <= LM; i++ ){
x = (int)(double(i) * double(XR - XL)/double(LM) + XL);
sprintf(bf, "%4.0lf", (max*i)/LM);
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf);
}
tp->Pen->Color = clRed;
tp->Pen->Style = psDot;
x = (int)(XL + (fs/2) * (double(XR-XL)/max));
tp->MoveTo(x, YT); tp->LineTo(x, YB);
tp->Pen->Color = clBlue;
tp->Pen->Style = psSolid;
}
int ay = 0;
double ra, im;
pi2t = 2.0 * PI / fs;
tp->Pen->Color = col;
for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){
if( Tap ){
ra = im = 0.0;
for( k = 0; k <= Tap; k++ ){
ra += H[k] * cos(pi2t*f*k);
if( k ) im -= H[k] * sin(pi2t*f*k);
}
if( ra * im ){
g = sqrt(ra * ra + im * im);
}
else {
g = 0.0;
}
}
else {
g = 1.0;
}
if( g == 0 ) g = 1.0e-38;
gdb = 20*0.4342944*log(fabs(g)) + 80.0;
if( gdb < 0.0 ) gdb = 0.0;
gdb = (gdb * double(YB-YT))/80.0;
y = YB - (int)gdb;
if( x == XL ){
tp->MoveTo(x, y);
tp->LineTo(x, y);
}
else {
tp->MoveTo(x-1, ay);
tp->LineTo(x, y);
}
ay = y;
}
}
void DrawGraph2(Graphics::TBitmap *pBitmap, const double *H1, int Tap1, const double *H2, int Tap2, int Over, int &nmax, int init, TColor col)
{
int k, x, y;
double f, gdb, g, pi2t, fs;
double max;
char bf[80];
TCanvas *tp = pBitmap->Canvas;
TRect rc;
rc.Left = 0;
rc.Right = pBitmap->Width;
rc.Top = 0;
rc.Bottom = pBitmap->Height;
if( init ){
tp->Brush->Color = clWhite;
tp->FillRect(rc);
}
int LM; // 周波数表示のあるライン数
int DM; // 内部線の数
int MM; // 実線の間隔
switch(Over){
case 2:
max = 3000;
fs = SampFreq/2.0;
break;
case 3:
max = 2000;
fs = SampFreq/3.0;
break;
default:
max = 4000;
fs = SampFreq;
break;
}
if( nmax ){
max = nmax;
}
else {
nmax = max;
}
switch(nmax){
case 3000:
LM = 3;
DM = 14;
MM = 5;
break;
case 100:
case 200:
case 2000:
LM = 4;
DM = 19;
MM = 5;
break;
case 400:
case 800:
case 4000:
LM = 4;
DM = 19;
MM = 5;
break;
default: // 6000
LM = 3;
DM = 11;
MM = 4;
break;
}
int XL = 32;
int XR = pBitmap->Width - 16;
int YT = 16;
int YB = pBitmap->Height - 24;
int i;
if( init ){
tp->Pen->Color = clBlack;
tp->Font->Size = 8;
tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT);
tp->Pen->Color = clGray;
for( i = 0; i < 7; i++ ){
tp->Pen->Style = (i & 1) ? psSolid : psDot;
y = (int)(double(i + 1) * double(YB - YT)/8.0 + YT);
tp->MoveTo(XL, y); tp->LineTo(XR, y);
}
for( i = 1; i < 5; i++ ){
y = (int)(double(i) * double(YB - YT)/4.0 + YT);
sprintf( bf, "-%2u", (80 / 4)*i );
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf);
}
strcpy(bf, "dB");
tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf);
for( i = 1; i <= DM; i++ ){
tp->Pen->Style = (i % MM) ? psDot : psSolid;
x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL);
tp->MoveTo(x, YT); tp->LineTo(x, YB);
}
for( i = 0; i <= LM; i++ ){
x = (int)(double(i) * double(XR - XL)/double(LM) + XL);
sprintf(bf, "%4.0lf", (max*i)/LM);
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf);
}
tp->Pen->Color = clRed;
tp->Pen->Style = psDot;
x = (int)(XL + (fs/2) * (double(XR-XL)/max));
tp->MoveTo(x, YT); tp->LineTo(x, YB);
tp->Pen->Color = clBlue;
tp->Pen->Style = psSolid;
}
int ay = 0;
double ra, im;
pi2t = 2.0 * PI / fs;
tp->Pen->Color = col;
for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){
if( Tap1 ){
ra = im = 0.0;
for( k = 0; k <= Tap1; k++ ){
ra += H1[k] * cos(pi2t*f*k);
if( k ) im -= H1[k] * sin(pi2t*f*k);
}
if( ra * im ){
g = sqrt(ra * ra + im * im);
}
else {
g = 0.0;
}
}
else {
g = 1.0;
}
if( Tap2 ){
ra = im = 0.0;
for( k = 0; k <= Tap2; k++ ){
ra += H2[k] * cos(pi2t*f*k);
if( k ) im -= H2[k] * sin(pi2t*f*k);
}
if( ra * im ){
g *= sqrt(ra * ra + im * im);
}
else {
g *= 0.0;
}
}
else {
g *= 1.0;
}
if( g == 0 ) g = 1.0e-38;
gdb = 20*0.4342944*log(fabs(g)) + 80.0;
if( gdb < 0.0 ) gdb = 0.0;
gdb = (gdb * double(YB-YT))/80.0;
y = YB - (int)gdb;
if( x == XL ){
tp->MoveTo(x, y);
tp->LineTo(x, y);
}
else {
tp->MoveTo(x-1, ay);
tp->LineTo(x, y);
}
ay = y;
}
}
//---------------------------------------------------------------------
// 周波数特性グラフ(フィルタスレッド内でコールしてはいけない)
//
//
void DrawGraphIIR(Graphics::TBitmap *pBitmap, double a0, double a1, double a2, double b1, double b2, int Over, int &nmax, int init, TColor col)
{
int x, y;
double f, gdb, g, pi2t, pi4t, fs;
double max;
char bf[80];
TCanvas *tp = pBitmap->Canvas;
TRect rc;
rc.Left = 0;
rc.Right = pBitmap->Width;
rc.Top = 0;
rc.Bottom = pBitmap->Height;
if( init ){
tp->Brush->Color = clWhite;
tp->FillRect(rc);
}
int LM; // 周波数表示のあるライン数
int DM; // 内部線の数
int MM; // 実線の間隔
switch(Over){
case 2:
max = 3000;
fs = SampFreq/2.0;
break;
case 3:
max = 2000;
fs = SampFreq/3.0;
break;
default:
max = 4000;
fs = SampFreq;
break;
}
if( nmax ){
max = nmax;
}
else {
nmax = max;
}
switch(nmax){
case 3000:
LM = 3;
DM = 14;
MM = 5;
break;
case 100:
case 200:
case 2000:
LM = 4;
DM = 19;
MM = 5;
break;
case 400:
case 800:
case 4000:
LM = 4;
DM = 19;
MM = 5;
break;
default: // 6000
LM = 3;
DM = 11;
MM = 4;
break;
}
int XL = 32;
int XR = pBitmap->Width - 16;
int YT = 16;
int YB = pBitmap->Height - 24;
int i;
if( init ){
tp->Pen->Color = clBlack;
tp->Font->Size = 8;
tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT);
tp->Pen->Color = clGray;
for( i = 0; i < 5; i++ ){
tp->Pen->Style = (i & 1) ? psSolid : psDot;
y = (int)(double(i + 1) * double(YB - YT)/6.0 + YT);
tp->MoveTo(XL, y); tp->LineTo(XR, y);
}
for( i = 1; i < 4; i++ ){
y = (int)(double(i) * double(YB - YT)/3.0 + YT);
sprintf( bf, "-%2u", (60 / 3)*i );
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf);
}
strcpy(bf, "dB");
tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf);
for( i = 1; i <= DM; i++ ){
tp->Pen->Style = (i % MM) ? psDot : psSolid;
x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL);
tp->MoveTo(x, YT); tp->LineTo(x, YB);
}
for( i = 0; i <= LM; i++ ){
x = (int)(double(i) * double(XR - XL)/double(LM) + XL);
sprintf(bf, "%4.0lf", (max*i)/LM);
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf);
}
tp->Pen->Color = clRed;
tp->Pen->Style = psDot;
x = (int)(XL + (fs/2) * (double(XR-XL)/max));
tp->MoveTo(x, YT); tp->LineTo(x, YB);
tp->Pen->Color = clBlue;
tp->Pen->Style = psSolid;
}
int ay = 0;
pi2t = 2.0 * PI / fs;
pi4t = 2.0 * pi2t;
tp->Pen->Color = col;
double A, B, C, D, P, R;
double cosw, sinw, cos2w, sin2w;
for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){
cosw = cos(pi2t*f);
sinw = sin(pi2t*f);
cos2w = cos(pi4t*f);
sin2w = sin(pi4t*f);
A = a0 + a1 * cosw + a2 * cos2w;
B = 1 + b1 * cosw + b2 * cos2w;
C = a1 * sinw + a2 * sin2w;
D = b1 * sinw + b2 * sin2w;
P = A*A + C*C;
R = B*B + D*D;
g = sqrt(P/R);
if( g == 0 ) g = 1.0e-38;
gdb = 20*0.4342944*log(fabs(g)) + 60.0;
if( gdb < 0.0 ) gdb = 0.0;
gdb = (gdb * double(YB-YT))/60.0;
y = YB - (int)gdb;
if( x == XL ){
tp->MoveTo(x, y);
tp->LineTo(x, y);
}
else {
tp->MoveTo(x-1, ay);
tp->LineTo(x, y);
}
ay = y;
}
}
//---------------------------------------------------------------------
// 周波数特性グラフ(フィルタスレッド内でコールしてはいけない)
//
//
void DrawGraphIIR(Graphics::TBitmap *pBitmap, CIIR *ip, int Over, int &nmax, int init, TColor col)
{
int x, y;
double f, gdb, g, pi2t, pi4t, fs;
double max;
char bf[80];
TCanvas *tp = pBitmap->Canvas;
TRect rc;
rc.Left = 0;
rc.Right = pBitmap->Width;
rc.Top = 0;
rc.Bottom = pBitmap->Height;
if( init ){
tp->Brush->Color = clWhite;
tp->FillRect(rc);
}
int LM; // 周波数表示のあるライン数
int DM; // 内部線の数
int MM; // 実線の間隔
switch(Over){
case 2:
max = 3000;
fs = SampFreq/2.0;
break;
case 3:
max = 2000;
fs = SampFreq/3.0;
break;
default:
max = 4000;
fs = SampFreq;
break;
}
if( nmax ){
max = nmax;
}
else {
nmax = max;
}
switch(nmax){
case 3000:
LM = 3;
DM = 14;
MM = 5;
break;
case 100:
case 200:
case 2000:
LM = 4;
DM = 19;
MM = 5;
break;
case 400:
case 800:
case 4000:
LM = 4;
DM = 19;
MM = 5;
break;
default: // 6000
LM = 3;
DM = 11;
MM = 4;
break;
}
int XL = 32;
int XR = pBitmap->Width - 16;
int YT = 16;
int YB = pBitmap->Height - 24;
int i;
if( init ){
tp->Pen->Color = clBlack;
tp->Font->Size = 8;
tp->MoveTo(XL, YT); tp->LineTo(XR, YT); tp->LineTo(XR, YB); tp->LineTo(XL, YB); tp->LineTo(XL, YT);
tp->Pen->Color = clGray;
for( i = 0; i < 5; i++ ){
tp->Pen->Style = (i & 1) ? psSolid : psDot;
y = (int)(double(i + 1) * double(YB - YT)/6.0 + YT);
tp->MoveTo(XL, y); tp->LineTo(XR, y);
}
for( i = 1; i < 4; i++ ){
y = (int)(double(i) * double(YB - YT)/3.0 + YT);
sprintf( bf, "-%2u", (60 / 3)*i );
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(XL - 6 - tp->TextWidth(bf), y - (tp->TextHeight(bf)/2), bf);
}
strcpy(bf, "dB");
tp->TextOut(XL - 6 - tp->TextWidth(bf), YT-(tp->TextHeight(bf)/2), bf);
for( i = 1; i <= DM; i++ ){
tp->Pen->Style = (i % MM) ? psDot : psSolid;
x = (int)(double(i) * double(XR - XL)/double(DM+1) + XL);
tp->MoveTo(x, YT); tp->LineTo(x, YB);
}
for( i = 0; i <= LM; i++ ){
x = (int)(double(i) * double(XR - XL)/double(LM) + XL);
sprintf(bf, "%4.0lf", (max*i)/LM);
::SetBkMode(tp->Handle, TRANSPARENT);
tp->TextOut(x - (tp->TextWidth(bf)/2), YB + 6, bf);
}
tp->Pen->Color = clRed;
tp->Pen->Style = psDot;
x = (int)(XL + (fs/2) * (double(XR-XL)/max));
tp->MoveTo(x, YT); tp->LineTo(x, YB);
tp->Pen->Color = clBlue;
tp->Pen->Style = psSolid;
}
int ay = 0;
pi2t = 2.0 * PI / fs;
pi4t = 2.0 * pi2t;
tp->Pen->Color = col;
double A, B, C, D, P, R;
double cosw, sinw, cos2w, sin2w;
for( x = XL, f = 0.0; x < XR; x++, f += (max/double(XR-XL)) ){
cosw = cos(pi2t*f);
sinw = sin(pi2t*f);
cos2w = cos(pi4t*f);
sin2w = sin(pi4t*f);
g = 1.0;
double *ap = ip->A;
double *bp = ip->B;
for( i = 0; i < ip->m_order/2; i++, ap += 3, bp += 2 ){
/*
A = a0 + a1 * cosw + a2 * cos2w;
B = 1 + b1 * cosw + b2 * cos2w;
C = a1 * sinw + a2 * sin2w;
D = b1 * sinw + b2 * sin2w;
*/
A = bp[0] + bp[1] * cosw + bp[0] * cos2w;
B = 1 + -ap[1] * cosw + -ap[2] * cos2w;
C = bp[1] * sinw + bp[0] * sin2w;
D = -ap[1] * sinw + -ap[2] * sin2w;
P = A*A + C*C;
R = B*B + D*D;
g *= sqrt(P/R);
}
if( ip->m_order & 1 ){
A = bp[0] + bp[1] * cosw;
B = 1 + -ap[1] * cosw;
C = bp[1] * sinw;
D = -ap[1] * sinw;
P = A*A + C*C;
R = B*B + D*D;
g *= sqrt(P/R);
}
if( g == 0 ) g = 1.0e-38;
gdb = 20*0.4342944*log(fabs(g)) + 60.0;
if( gdb < 0.0 ) gdb = 0.0;
gdb = (gdb * double(YB-YT))/60.0;
y = YB - (int)gdb;
if( x == XL ){
tp->MoveTo(x, y);
tp->LineTo(x, y);
}
else {
tp->MoveTo(x-1, ay);
tp->LineTo(x, y);
}
ay = y;
}
}
double asinh(double x)
{
return log(x + sqrt(x*x+1.0));
}
//------------------------------------------------------------------
// bc : 0-バターワース, 1-チェビシフ
// rp : 通過域のリップル
void MakeIIR(double *A, double *B, double fc, double fs, int order, int bc, double rp)
{
double w0, wa, u, zt, x;
int j, n;
if( bc ){ // チェビシフ
u = 1.0/double(order)*asinh(1.0/sqrt(pow(10.0,0.1*rp)-1.0));
}
wa = tan(PI*fc/fs);
w0 = 1.0;
n = (order & 1) + 1;
double *pA = A;
double *pB = B;
double d1, d2;
for( j = 1; j <= order/2; j++, pA+=3, pB+=2 ){
if( bc ){ // チェビシフ
d1 = sinh(u)*cos(n*PI/(2*order));
d2 = cosh(u)*sin(n*PI/(2*order));
w0 = sqrt(d1 * d1 + d2 * d2);
zt = sinh(u)*cos(n*PI/(2*order))/w0;
}
else { // バターワース
w0 = 1.0;
zt = cos(n*PI/(2*order));
}
pA[0] = 1 + wa*w0*2*zt + wa*w0*wa*w0;
pA[1] = -2 * (wa*w0*wa*w0 - 1)/pA[0];
pA[2] = -(1.0 - wa*w0*2*zt + wa*w0*wa*w0)/pA[0];
pB[0] = wa*w0*wa*w0 / pA[0];
pB[1] = 2*pB[0];
n += 2;
}
if( bc && !(order & 1) ){
x = pow( 1.0/pow(10.0,rp/20.0), 1/double(order/2) );
pB = B;
for( j = 1; j <= order/2; j++, pB+=2 ){
pB[0] *= x;
pB[1] *= x;
}
}
if( order & 1 ){
if( bc ) w0 = sinh(u);
j = (order / 2);
pA = A + (j*3);
pB = B + (j*2);
pA[0] = 1 + wa*w0;
pA[1] = -(wa*w0 - 1)/pA[0];
pB[0] = wa*w0/pA[0];
pB[1] = pB[0];
}
}
//---------------------------------------------------------------------------
CIIR::CIIR()
{
m_order = 0;
A = new double[IIRMAX*3];
B = new double[IIRMAX*2];
Z = new double[IIRMAX*2];
memset(A, 0, sizeof(double[IIRMAX*3]));
memset(B, 0, sizeof(double[IIRMAX*2]));
memset(Z, 0, sizeof(double[IIRMAX*2]));
}
CIIR::~CIIR()
{
if( A != NULL ) delete[] A;
if( B != NULL ) delete[] B;
if( Z != NULL ) delete[] Z;
}
void CIIR::Clear(void)
{
memset(Z, 0, sizeof(double[IIRMAX*2]));
}
void CIIR::MakeIIR(double fc, double fs, int order, int bc, double rp)
{
m_order = order;
m_bc = bc;
m_rp = rp;
::MakeIIR(A, B, fc, fs, order, bc, rp);
}
double CIIR::Do(double d)
{
double *pA = A;
double *pB = B;
double *pZ = Z;
double o;
for( int i = 0; i < m_order/2; i++, pA+=3, pB+=2, pZ+=2 ){
d += pZ[0] * pA[1] + pZ[1] * pA[2];
o = d * pB[0] + pZ[0] * pB[1] + pZ[1] * pB[0];
pZ[1] = pZ[0];
if( fabs(d) < 1e-37 ) d = 0.0;
pZ[0] = d;
d = o;
}
if( m_order & 1 ){
d += pZ[0] * pA[1];
o = d * pB[0] + pZ[0] * pB[0];
if( fabs(d) < 1e-37 ) d = 0.0;
pZ[0] = d;
d = o;
}
return d;
}
//*********************************************************************
// CINTPXY XYScope 用 ×2インタポーレータ処理クラス
//
CINTPXY2::CINTPXY2()
{
iir.MakeIIR(2800, DemSamp * 2.0, 14, 0, 0);
}
void __fastcall CINTPXY2::Do(double *p, double d)
{
*p++ = iir.Do(d);
*p = iir.Do(d);
}
#if 0
//*********************************************************************
// CINTPXY XYScope 用 ×4インタポーレータ処理クラス
//
CINTPXY4::CINTPXY4()
{
iir.MakeIIR(2800, DemSamp * 4.0, 24, 0, 0);
}
void __fastcall CINTPXY4::Do(double *p, double d)
{
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p = iir.Do(d);
}
//*********************************************************************
// CINTPXY XYScope 用 ×8インタポーレータ処理クラス
//
CINTPXY8::CINTPXY8()
{
iir.MakeIIR(2800, DemSamp * 8.0, 30, 0, 0);
}
void __fastcall CINTPXY8::Do(double *p, double d)
{
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p++ = iir.Do(d);
*p = iir.Do(d);
}
//*********************************************************************
// CINTPXYFIR XYScope 用 ×2インタポーレータ処理クラス
//
CINTPXY2FIR::CINTPXY2FIR()
{
memset(Z, 0, sizeof(Z));
::MakeFilter(H, 32, ffLPF, DemSamp * 2.0, 2800, 3000, 40, 1.7);
}
void CINTPXY2FIR::Do(double *dp, double d)
{
memcpy(Z, &Z[1], sizeof(double)*16);
Z[16] = d;
dp[0] = Z[0] * H[32];
dp[1] = Z[1] * H[31];
dp[0] += Z[1] * H[30];
dp[1] += Z[2] * H[29];
dp[0] += Z[2] * H[28];
dp[1] += Z[3] * H[27];
dp[0] += Z[3] * H[26];
dp[1] += Z[4] * H[25];
dp[0] += Z[4] * H[24];
dp[1] += Z[5] * H[23];
dp[0] += Z[5] * H[22];
dp[1] += Z[6] * H[21];
dp[0] += Z[6] * H[20];
dp[1] += Z[7] * H[19];
dp[0] += Z[7] * H[18];
dp[1] += Z[8] * H[17];
dp[0] += Z[8] * H[16];
dp[1] += Z[9] * H[15];
dp[0] += Z[9] * H[14];
dp[1] += Z[10] * H[13];
dp[0] += Z[10] * H[12];
dp[1] += Z[11] * H[11];
dp[0] += Z[11] * H[10];
dp[1] += Z[12] * H[9];
dp[0] += Z[12] * H[8];
dp[1] += Z[13] * H[7];
dp[0] += Z[13] * H[6];
dp[1] += Z[14] * H[5];
dp[0] += Z[14] * H[4];
dp[1] += Z[15] * H[3];
dp[0] += Z[15] * H[2];
dp[1] += Z[16] * H[1];
dp[0] += Z[16] * H[0];
}
#endif
//*********************************************************************
// CINTPXYFIR XYScope 用 ×4インタポーレータ処理クラス
//
CINTPXY4FIR::CINTPXY4FIR()
{
memset(Z, 0, sizeof(Z));
::MakeFilter(H, 64, ffLPF, DemSamp * 4.0, 2800, 3000, 60, 4.0);
}
void __fastcall CINTPXY4FIR::Do(double *dp, double d)
{
memcpy(Z, &Z[1], sizeof(double)*16);
Z[16] = d;
dp[0] = Z[0] * H[64];
dp[1] = Z[1] * H[63];
dp[2] = Z[1] * H[62];
dp[3] = Z[1] * H[61];
dp[0] += Z[1] * H[60];
dp[1] += Z[2] * H[59];
dp[2] += Z[2] * H[58];
dp[3] += Z[2] * H[57];
dp[0] += Z[2] * H[56];
dp[1] += Z[3] * H[55];
dp[2] += Z[3] * H[54];
dp[3] += Z[3] * H[53];
dp[0] += Z[3] * H[52];
dp[1] += Z[4] * H[51];
dp[2] += Z[4] * H[50];
dp[3] += Z[4] * H[49];
dp[0] += Z[4] * H[48];
dp[1] += Z[5] * H[47];
dp[2] += Z[5] * H[46];
dp[3] += Z[5] * H[45];
dp[0] += Z[5] * H[44];
dp[1] += Z[6] * H[43];
dp[2] += Z[6] * H[42];
dp[3] += Z[6] * H[41];
dp[0] += Z[6] * H[40];
dp[1] += Z[7] * H[39];
dp[2] += Z[7] * H[38];
dp[3] += Z[7] * H[37];
dp[0] += Z[7] * H[36];
dp[1] += Z[8] * H[35];
dp[2] += Z[8] * H[34];
dp[3] += Z[8] * H[33];
dp[0] += Z[8] * H[32];
dp[1] += Z[9] * H[31];
dp[2] += Z[9] * H[30];
dp[3] += Z[9] * H[29];
dp[0] += Z[9] * H[28];
dp[1] += Z[10] * H[27];
dp[2] += Z[10] * H[26];
dp[3] += Z[10] * H[25];
dp[0] += Z[10] * H[24];
dp[1] += Z[11] * H[23];
dp[2] += Z[11] * H[22];
dp[3] += Z[11] * H[21];
dp[0] += Z[11] * H[20];
dp[1] += Z[12] * H[19];
dp[2] += Z[12] * H[18];
dp[3] += Z[12] * H[17];
dp[0] += Z[12] * H[16];
dp[1] += Z[12] * H[15];
dp[2] += Z[12] * H[14];
dp[3] += Z[12] * H[13];
dp[0] += Z[12] * H[12];
dp[1] += Z[12] * H[11];
dp[2] += Z[12] * H[10];
dp[3] += Z[12] * H[9];
dp[0] += Z[12] * H[8];
dp[1] += Z[12] * H[7];
dp[2] += Z[12] * H[6];
dp[3] += Z[12] * H[5];
dp[0] += Z[12] * H[4];
dp[1] += Z[12] * H[3];
dp[2] += Z[12] * H[2];
dp[3] += Z[12] * H[1];
dp[0] += Z[12] * H[0];
}
//*********************************************************************
// CINTPXYFIR XYScope 用 ×8インタポーレータ処理クラス
//
CINTPXY8FIR::CINTPXY8FIR()
{
memset(Z, 0, sizeof(Z));
::MakeFilter(H, 96, ffLPF, DemSamp * 8.0, 2800, 3000, 60, 8.0);
}
void __fastcall CINTPXY8FIR::Do(double *dp, double d)
{
memcpy(Z, &Z[1], sizeof(double)*12);
Z[12] = d;
dp[0] = Z[0] * H[96];
dp[1] = Z[1] * H[95];
dp[2] = Z[1] * H[94];
dp[3] = Z[1] * H[93];
dp[4] = Z[1] * H[92];
dp[5] = Z[1] * H[91];
dp[6] = Z[1] * H[90];
dp[7] = Z[1] * H[89];
dp[0] += Z[1] * H[88];
dp[1] += Z[2] * H[87];
dp[2] += Z[2] * H[86];
dp[3] += Z[2] * H[85];
dp[4] += Z[2] * H[84];
dp[5] += Z[2] * H[83];
dp[6] += Z[2] * H[82];
dp[7] += Z[2] * H[81];
dp[0] += Z[2] * H[80];
dp[1] += Z[3] * H[79];
dp[2] += Z[3] * H[78];
dp[3] += Z[3] * H[77];
dp[4] += Z[3] * H[76];
dp[5] += Z[3] * H[75];
dp[6] += Z[3] * H[74];
dp[7] += Z[3] * H[73];
dp[0] += Z[3] * H[72];
dp[1] += Z[4] * H[71];
dp[2] += Z[4] * H[70];
dp[3] += Z[4] * H[69];
dp[4] += Z[4] * H[68];
dp[5] += Z[4] * H[67];
dp[6] += Z[4] * H[66];
dp[7] += Z[4] * H[65];
dp[0] += Z[4] * H[64];
dp[1] += Z[5] * H[63];
dp[2] += Z[5] * H[62];
dp[3] += Z[5] * H[61];
dp[4] += Z[5] * H[60];
dp[5] += Z[5] * H[59];
dp[6] += Z[5] * H[58];
dp[7] += Z[5] * H[57];
dp[0] += Z[5] * H[56];
dp[1] += Z[6] * H[55];
dp[2] += Z[6] * H[54];
dp[3] += Z[6] * H[53];
dp[4] += Z[6] * H[52];
dp[5] += Z[6] * H[51];
dp[6] += Z[6] * H[50];
dp[7] += Z[6] * H[49];
dp[0] += Z[6] * H[48];
dp[1] += Z[7] * H[47];
dp[2] += Z[7] * H[46];
dp[3] += Z[7] * H[45];
dp[4] += Z[7] * H[44];
dp[5] += Z[7] * H[43];
dp[6] += Z[7] * H[42];
dp[7] += Z[7] * H[41];
dp[0] += Z[7] * H[40];
dp[1] += Z[8] * H[39];
dp[2] += Z[8] * H[38];
dp[3] += Z[8] * H[37];
dp[4] += Z[8] * H[36];
dp[5] += Z[8] * H[35];
dp[6] += Z[8] * H[34];
dp[7] += Z[8] * H[33];
dp[0] += Z[8] * H[32];
dp[1] += Z[9] * H[31];
dp[2] += Z[9] * H[30];
dp[3] += Z[9] * H[29];
dp[4] += Z[9] * H[28];
dp[5] += Z[9] * H[27];
dp[6] += Z[9] * H[26];
dp[7] += Z[9] * H[25];
dp[0] += Z[9] * H[24];
dp[1] += Z[10] * H[23];
dp[2] += Z[10] * H[22];
dp[3] += Z[10] * H[21];
dp[4] += Z[10] * H[20];
dp[5] += Z[10] * H[19];
dp[6] += Z[10] * H[18];
dp[7] += Z[10] * H[17];
dp[0] += Z[10] * H[16];
dp[1] += Z[11] * H[15];
dp[2] += Z[11] * H[14];
dp[3] += Z[11] * H[13];
dp[4] += Z[11] * H[12];
dp[5] += Z[11] * H[11];
dp[6] += Z[11] * H[10];
dp[7] += Z[11] * H[9];
dp[0] += Z[11] * H[8];
dp[1] += Z[12] * H[7];
dp[2] += Z[12] * H[6];
dp[3] += Z[12] * H[5];
dp[4] += Z[12] * H[4];
dp[5] += Z[12] * H[3];
dp[6] += Z[12] * H[2];
dp[7] += Z[12] * H[1];
dp[0] += Z[12] * H[0];
}
#if OVERFIR
//*********************************************************************
// CDECM4 1/4デシメータ処理クラス
//
CDECM4::CDECM4()
{
const double _mt[]={1.11, 1.25, 1.40, 1.11};
memset(Z1, 0, sizeof(Z1));
memset(Z2, 0, sizeof(Z2));
memset(Z3, 0, sizeof(Z3));
memset(Z4, 0, sizeof(Z4));
::MakeFilter(H, 80, ffLPF, SampFreq*4, 2800, 3000, 50, _mt[SampType]);
}
double __fastcall CDECM4::Do(double *dp)
{
memcpy(Z1, &Z1[1], sizeof(double)*20);
memcpy(Z2, &Z2[1], sizeof(double)*19);
memcpy(Z3, &Z3[1], sizeof(double)*19);
memcpy(Z4, &Z4[1], sizeof(double)*19);
#if 1
Z4[19] = *dp++;
Z3[19] = *dp++;
Z2[19] = *dp++;
Z1[20] = *dp;
#else
Z1[20] = *dp++;
Z2[19] = *dp++;
Z3[19] = *dp++;
Z4[19] = *dp;
#endif
double a;
a = Z1[0] * H[80];
a += Z4[0] * H[79];
a += Z3[0] * H[78];
a += Z2[0] * H[77];
a += Z1[1] * H[76];
a += Z4[1] * H[75];
a += Z3[1] * H[74];
a += Z2[1] * H[73];
a += Z1[2] * H[72];
a += Z4[2] * H[71];
a += Z3[2] * H[70];
a += Z2[2] * H[69];
a += Z1[3] * H[68];
a += Z4[3] * H[67];
a += Z3[3] * H[66];
a += Z2[3] * H[65];
a += Z1[4] * H[64];
a += Z4[4] * H[63];
a += Z3[4] * H[62];
a += Z2[4] * H[61];
a += Z1[5] * H[60];
a += Z4[5] * H[59];
a += Z3[5] * H[58];
a += Z2[5] * H[57];
a += Z1[6] * H[56];
a += Z4[6] * H[55];
a += Z3[6] * H[54];
a += Z2[6] * H[53];
a += Z1[7] * H[52];
a += Z4[7] * H[51];
a += Z3[7] * H[50];
a += Z2[7] * H[49];
a += Z1[8] * H[48];
a += Z4[8] * H[47];
a += Z3[8] * H[46];
a += Z2[8] * H[45];
a += Z1[9] * H[44];
a += Z4[9] * H[43];
a += Z3[9] * H[42];
a += Z2[9] * H[41];
a += Z1[10] * H[40];
a += Z4[10] * H[39];
a += Z3[10] * H[38];
a += Z2[10] * H[37];
a += Z1[11] * H[36];
a += Z4[11] * H[35];
a += Z3[11] * H[34];
a += Z2[11] * H[33];
a += Z1[12] * H[32];
a += Z4[12] * H[31];
a += Z3[12] * H[30];
a += Z2[12] * H[29];
a += Z1[13] * H[28];
a += Z4[13] * H[27];
a += Z3[13] * H[26];
a += Z2[13] * H[25];
a += Z1[14] * H[24];
a += Z4[14] * H[23];
a += Z3[14] * H[22];
a += Z2[14] * H[21];
a += Z1[15] * H[20];
a += Z4[15] * H[19];
a += Z3[15] * H[18];
a += Z2[15] * H[17];
a += Z1[16] * H[16];
a += Z4[16] * H[15];
a += Z3[16] * H[14];
a += Z2[16] * H[13];
a += Z1[17] * H[12];
a += Z4[17] * H[11];
a += Z3[17] * H[10];
a += Z2[17] * H[9];
a += Z1[18] * H[8];
a += Z4[18] * H[7];
a += Z3[18] * H[6];
a += Z2[18] * H[5];
a += Z1[19] * H[4];
a += Z4[19] * H[3];
a += Z3[19] * H[2];
a += Z2[19] * H[1];
a += Z1[20] * H[0];
return a;
}
//*********************************************************************
// CINTP4 x4インタポーレータ処理クラス
//
CINTP4::CINTP4()
{
memset(Z, 0, sizeof(Z));
::MakeFilter(H, 80, ffLPF, SampFreq*4, 2800, 3000, 50, 4.0);
}
void __fastcall CINTP4::Do(double *dp, double d)
{
memcpy(Z, &Z[1], sizeof(double)*20);
Z[20] = d;
dp[0] = Z[0] * H[80];
dp[1] = Z[1] * H[79];
dp[2] = Z[1] * H[78];
dp[3] = Z[1] * H[77];
dp[0] += Z[1] * H[76];
dp[1] += Z[2] * H[75];
dp[2] += Z[2] * H[74];
dp[3] += Z[2] * H[73];
dp[0] += Z[2] * H[72];
dp[1] += Z[3] * H[71];
dp[2] += Z[3] * H[70];
dp[3] += Z[3] * H[69];
dp[0] += Z[3] * H[68];
dp[1] += Z[4] * H[67];
dp[2] += Z[4] * H[66];
dp[3] += Z[4] * H[65];
dp[0] += Z[4] * H[64];
dp[1] += Z[5] * H[63];
dp[2] += Z[5] * H[62];
dp[3] += Z[5] * H[61];
dp[0] += Z[5] * H[60];
dp[1] += Z[6] * H[59];
dp[2] += Z[6] * H[58];
dp[3] += Z[6] * H[57];
dp[0] += Z[6] * H[56];
dp[1] += Z[7] * H[55];
dp[2] += Z[7] * H[54];
dp[3] += Z[7] * H[53];
dp[0] += Z[7] * H[52];
dp[1] += Z[8] * H[51];
dp[2] += Z[8] * H[50];
dp[3] += Z[8] * H[49];
dp[0] += Z[8] * H[48];
dp[1] += Z[9] * H[47];
dp[2] += Z[9] * H[46];
dp[3] += Z[9] * H[45];
dp[0] += Z[9] * H[44];
dp[1] += Z[10] * H[43];
dp[2] += Z[10] * H[42];
dp[3] += Z[10] * H[41];
dp[0] += Z[10] * H[40];
dp[1] += Z[11] * H[39];
dp[2] += Z[11] * H[38];
dp[3] += Z[11] * H[37];
dp[0] += Z[11] * H[36];
dp[1] += Z[12] * H[35];
dp[2] += Z[12] * H[34];
dp[3] += Z[12] * H[33];
dp[0] += Z[12] * H[32];
dp[1] += Z[13] * H[31];
dp[2] += Z[13] * H[30];
dp[3] += Z[13] * H[29];
dp[0] += Z[13] * H[28];
dp[1] += Z[14] * H[27];
dp[2] += Z[14] * H[26];
dp[3] += Z[14] * H[25];
dp[0] += Z[14] * H[24];
dp[1] += Z[15] * H[23];
dp[2] += Z[15] * H[22];
dp[3] += Z[15] * H[21];
dp[0] += Z[15] * H[20];
dp[1] += Z[16] * H[19];
dp[2] += Z[16] * H[18];
dp[3] += Z[16] * H[17];
dp[0] += Z[16] * H[16];
dp[1] += Z[17] * H[15];
dp[2] += Z[17] * H[14];
dp[3] += Z[17] * H[13];
dp[0] += Z[17] * H[12];
dp[1] += Z[18] * H[11];
dp[2] += Z[18] * H[10];
dp[3] += Z[18] * H[9];
dp[0] += Z[18] * H[8];
dp[1] += Z[19] * H[7];
dp[2] += Z[19] * H[6];
dp[3] += Z[19] * H[5];
dp[0] += Z[19] * H[4];
dp[1] += Z[20] * H[3];
dp[2] += Z[20] * H[2];
dp[3] += Z[20] * H[1];
dp[0] += Z[20] * H[0];
}
#endif
//*********************************************************************
// COVERLIMIT 高品質リミッタ
//
COVERLIMIT::COVERLIMIT()
{
#if !OVERFIR
iira.MakeIIR(2800, SampFreq * 4.0, 24, 0, 0);
iirb.MakeIIR(2800, SampFreq * 4.0, 24, 0, 0);
#endif
}
double COVERLIMIT::Do(double d, double lmt)
{
#if OVERFIR
double dt[4];
intp.Do(dt, d);
dt[0] *= lmt;
if( dt[0] > 16384.0 ) dt[0] = 16384.0;
if( dt[0] < -16384.0 ) dt[0] = -16384.0;
dt[1] *= lmt;
if( dt[1] > 16384.0 ) dt[1] = 16384.0;
if( dt[1] < -16384.0 ) dt[1] = -16384.0;
dt[2] *= lmt;
if( dt[2] > 16384.0 ) dt[2] = 16384.0;
if( dt[2] < -16384.0 ) dt[2] = -16384.0;
dt[3] *= lmt;
if( dt[3] > 16384.0 ) dt[3] = 16384.0;
if( dt[3] < -16384.0 ) dt[3] = -16384.0;
return decm.Do(dt);
#else
double d1, d2, d3, d4;
// X4 インターポーレータ
d1 = iira.Do(d);
d2 = iira.Do(d);
d3 = iira.Do(d);
d4 = iira.Do(d);
d1 *= lmt;
if( d1 > 16384.0 ) d1 = 16384.0;
if( d1 < -16384.0 ) d1 = -16384.0;
d2 *= lmt;
if( d2 > 16384.0 ) d2 = 16384.0;
if( d2 < -16384.0 ) d2 = -16384.0;
d3 *= lmt;
if( d3 > 16384.0 ) d3 = 16384.0;
if( d3 < -16384.0 ) d3 = -16384.0;
d4 *= lmt;
if( d4 > 16384.0 ) d4 = 16384.0;
if( d4 < -16384.0 ) d4 = -16384.0;
// 1/4 デシメータ
iirb.Do(d1);
iirb.Do(d2);
iirb.Do(d3);
return iirb.Do(d4);
#endif
}
//*********************************************************************
// CDECM2IIR 1/2デシメータ処理クラス
//
CDECM2IIR::CDECM2IIR()
{
iir.MakeIIR(2900, SampFreq, 12, 0, 0);
}
double CDECM2IIR::Do(double d1, double d2)
{
iir.Do(d2);
return iir.Do(d1);
}
#if 0
//*********************************************************************
// CHILL ヒルベルト変換クラス
//
CHILL::CHILL()
{
memset(Z, 0, sizeof(Z));
m_tap = 8;
m_htap = m_tap / 2;
m_CenterFreq = 2125 + 170*0.5;
SetSampFreq(SampFreq);
SetFreq(2125, 2125+170);
}
void CHILL::SetSampFreq(double samp)
{
m_SampFreq = samp;
m_OUT = 32768.0 * m_SampFreq / (2 * PI * 800);
m_OFF = (2 * PI * m_CenterFreq) / m_SampFreq;
}
void CHILL::SetFreq(double mark, double space)
{
m_MarkFreq = mark;
m_SpaceFreq = space;
m_CenterFreq = (mark + space) * 0.5;
m_OFF = (2 * PI * m_CenterFreq) / m_SampFreq;
MakeFilter(H, m_tap, ffLPF, m_SampFreq, m_CenterFreq, m_CenterFreq, 6, 1.0);
H[m_htap] = 0;
for( int i = 0; i < m_htap; i++ ){
H[i] = -H[i];
}
m_A[0] = m_A[1] = m_A[2] = m_A[3] = 0;
m_ph = &Z[m_htap];
}
void CHILL::SetMarkFreq(double mark)
{
SetFreq(mark, m_SpaceFreq);
}
void CHILL::SetSpaceFreq(double space)
{
SetFreq(m_MarkFreq, space);
}
double CHILL::Do(double d)
{
d = DoFIR(H, Z, d, m_tap);
double a = *m_ph;
if( a ) a = atan2(d, a);
d = a - m_A[0];
m_A[0] = a;
if( d >= PI ){
d = d - PI*2;
}
else if( d <= -PI ){
d = d + PI*2;
}
d += m_OFF;
return d * m_OUT;
}
#endif