qucs_s/qucs-filter/filter.cpp

353 lines
16 KiB
C++
Raw Normal View History

/***************************************************************************
copyright: (C) 2010 by Michael Margraf
***************************************************************************/
2014-08-28 11:41:14 +07:00
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "lc_filter.h"
#include <qstring.h>
#include <qmessagebox.h>
Filter::Filter()
{
}
// -----------------------------------------------------------------------
// Returns the value of the E6 serie that is the next higher number to "value".
double Filter::getE6value(double value)
{
double e = floor(log10(value));
value /= pow(10.0, e);
if(value == 1.0)
value = 1.0;
else if(value <= 1.2)
value = 1.2;
else if(value <= 1.5)
value = 1.5;
else if(value <= 2.2)
value = 2.2;
else if(value <= 3.3)
value = 3.3;
else if(value <= 4.7)
value = 4.7;
else if(value <= 6.8)
value = 6.8;
else
value = 10.0;
return value * pow(10.0, e);
}
// -----------------------------------------------------------------------
double Filter::getNormValue(int No, tFilter *theFilter)
{
if((No < 0) || (No >= theFilter->Order))
return 1.0;
switch(theFilter->Type) {
case TYPE_BESSEL:
return BesselValue(No, theFilter->Order);
case TYPE_BUTTERWORTH:
return ButterworthValue(No, theFilter->Order);
case TYPE_CHEBYSHEV:
if((theFilter->Order & 1) == 0) {
QMessageBox::critical(0, "Error", "Even order Chebyshev can't be realized with passive filters.");
return 2e30;
}
return ChebyshevValue(No, theFilter->Order, theFilter->Ripple);
}
QMessageBox::critical(0, "Error", "Filter type not supported.");
return 2e30;
}
// -----------------------------------------------------------------------
double Filter::getQuadraticNormValues(int No, tFilter *theFilter, double &b)
{
if((No < 0) || (No >= theFilter->Order))
return 1.0;
switch(theFilter->Type) {
case TYPE_BESSEL:
return quadraticBesselValues(No, theFilter->Order, b);
case TYPE_BUTTERWORTH:
return quadraticButterworthValues(No, theFilter->Order, b);
case TYPE_CHEBYSHEV:
return quadraticChebyshevValues(No, theFilter->Order, theFilter->Ripple, b);
}
QMessageBox::critical(0, "Error", "Filter type not supported.");
return 2e30;
}
// -----------------------------------------------------------------------
QString Filter::num2str(double Num)
{
char c = 0;
double cal = fabs(Num);
if(cal > 1e-20) {
cal = log10(cal) / 3.0;
if(cal < -0.2) cal -= 0.98;
int Expo = int(cal);
if(Expo >= -5) if(Expo <= 4)
switch(Expo) {
case -5: c = 'f'; break;
case -4: c = 'p'; break;
case -3: c = 'n'; break;
case -2: c = 'u'; break;
case -1: c = 'm'; break;
case 1: c = 'k'; break;
case 2: c = 'M'; break;
case 3: c = 'G'; break;
case 4: c = 'T'; break;
}
if(c) Num /= pow(10.0, double(3*Expo));
}
QString Str = QString::number(Num, 'g', 4);
if(c) Str += c;
return Str;
}
// -----------------------------------------------------------------------
double BesselCoef[18][23] = {
/* 2 */ {0.57550275, 2.1478055, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 3 */ {0.33742149, 0.97051182, 2.2034114, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 4 */ {0.2334158, 0.67252481, 1.0815161, 2.2403786, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 5 */ {0.17431938, 0.50724063, 0.80401117, 1.1110332, 2.2582171,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 6 */ {0.13649238, 0.40018984, 0.6391554, 0.85378587, 1.112643,
2.2645236, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 7 */ {0.11056245, 0.32588813, 0.52489273, 0.70200915, 0.86902684,
1.1051644, 2.2659006, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 8 */ {0.091905558, 0.27191069, 0.44092213, 0.59357268, 0.73025665,
0.86950037, 1.0955593, 2.2656071, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 9 */ {0.077965506, 0.23129119, 0.37698651, 0.5107787, 0.63059516,
0.74073299, 0.86387345, 1.0862838, 2.2648789, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 10 */ {0.067229245, 0.19984023, 0.32699699, 0.44543381, 0.55281473,
0.64933545, 0.74201735, 0.85607238, 1.0780948, 2.2641262,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 11 */ {0.058753264, 0.1749102, 0.28706331, 0.39272513, 0.48983467,
0.57742576, 0.6573719, 0.73864992, 0.84789472, 1.0711184,
2.2634675, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 12 */ {0.051923, 0.15475798, 0.25458412, 0.34949045, 0.43777572,
0.51824604, 0.59097358, 0.65913453, 0.73309605, 0.84013853,
1.0652583, 2.2629233, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 13 */ {0.046323098, 0.13819538, 0.22775963, 0.31352943, 0.39412779,
0.46842754, 0.53589822, 0.59744624, 0.65727966, 0.72670805,
0.83311934, 1.0603538, 2.2624829, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 14 */ {0.041663913, 0.12438811, 0.20530976, 0.28325704, 0.35711858,
0.42591257, 0.48895292, 0.54624778, 0.59939971, 0.6534283,
0.72022065, 0.82691896, 1.0562406, 2.262128, 0.0,
0.0, 0.0, 0.0, 0.0,},
/* 15 */ {0.037738195, 0.11273464, 0.186303, 0.25750279, 0.32543754,
0.38927393, 0.44833655, 0.5022966, 0.55162099, 0.59850238,
0.64857809, 0.71401822, 0.8215094, 1.0527729, 2.2618408,
0.0, 0.0, 0.0, 0.0},
/* 16 */ {0.03439122, 0.102799, 0.1700389, 0.23539257, 0.29808411,
0.35745153, 0.41285998, 0.4638916, 0.51051757, 0.55360981,
0.59585789, 0.64334149, 0.70828423, 0.81681581, 1.0498286,
2.2616066, 0.0, 0.0, 0.0},
/* 17 */ {0.031523496, 0.094214373, 0.1560301, 0.21622781, 0.27429733,
0.32962199, 0.38165374, 0.42998671, 0.47437364, 0.51507678,
0.55331904, 0.59220181, 0.63808843, 0.70308744, 0.81274832,
1.0473087, 2.2614134, 0.0, 0.0},
/* 18 */ {0.028450351, 0.088289337, 0.14199897, 0.20112875, 0.25237658,
0.30571616, 0.35380272, 0.39992872, 0.44218287, 0.48110224,
0.5170226, 0.55152405, 0.58802463, 0.63303427, 0.69843256,
0.80921764, 1.0451338, 2.2612522, 0.0},
/* 19 */ {0.027944243, 0.077389235, 0.13716781, 0.18087554, 0.23831545,
0.28142035, 0.33055916, 0.37249664, 0.41348365, 0.45066049,
0.48503552, 0.51711998, 0.54877223, 0.58365096, 0.62829555,
0.69429034, 0.8061422, 1.043241, 2.2611162}
};
// -----------------------------------------------------------------------
// Calculate normalized component value for Bessel filter
double Filter::BesselValue(int No, int Order)
{
return BesselCoef [Order - 2] [No];
}
// -----------------------------------------------------------------------
// Calculate normalized component value for Butterworth filter
double Filter::ButterworthValue(int No, int Order)
{
return 2.0 * sin(double(2*No + 1) / double(2*Order) * M_PI);
}
// -----------------------------------------------------------------------
// This function calculates normalized component value for Chebyshev filter
// "Ripple" is in dB !
double Filter::ChebyshevValue(int No, int Order, double Ripple)
{
int i;
double ak, gk, a, b;
Ripple = sqrt(pow(10.0, Ripple / 10.0) - 1.0);
Ripple = sinh(asinh(1.0 / Ripple) / double(Order));
a = sin(0.5 / double(Order) * M_PI);
gk = a / Ripple;
for(i=1; i<=No; i++) { // coefficients are defined recursivly
ak = a;
a = sin(double(2 * i + 1) / double(2 * Order) * M_PI);
b = sin(double(i) * M_PI / double(Order));
gk *= Ripple * Ripple + b * b;
gk = ak * a / gk;
}
return 2.0 * gk;
}
// -----------------------------------------------------------------------
double BesselCoefA[18][10] = {
{1.36165413e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{9.99629202e-1, 7.56043166e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{7.74253975e-1, 1.33966370e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{6.21595206e-1, 1.14017670e+0, 6.65638800e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{5.13053656e-1, 9.68607026e-1, 1.22173438e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{4.33227776e-1, 8.30363090e-1, 1.09443685e+0, 5.93694426e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{3.72765065e-1, 7.20236277e-1, 9.75366333e-1, 1.11124956e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{3.25741595e-1, 6.31959746e-1, 8.71016716e-1, 1.02435625e+0, 5.38618836e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.88317886e-1, 5.60356263e-1, 7.81532026e-1, 9.39275303e-1, 1.02149912e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.57940189e-1, 5.01515079e-1, 7.05205806e-1, 8.60697679e-1, 9.58389453e-1, 4.95859210e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.32861727e-1, 4.52546178e-1, 6.40003229e-1, 7.89952794e-1, 8.94878610e-1, 9.48908283e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.11855068e-1, 4.11312404e-1, 5.84048406e-1, 7.26963090e-1, 8.34217677e-1, 9.00765966e-1, 4.61662889e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.94036277e-1, 3.76219036e-1, 5.35748797e-1, 6.71104591e-1, 7.77775499e-1, 8.51512428e-1, 8.89196782e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.78754672e-1, 3.46061743e-1, 4.93795485e-1, 6.21587105e-1, 7.25971504e-1, 8.03409152e-1, 8.51071594e-1, 4.33581765e-1, 0.00000000e+0, 0.00000000e+0},
{1.65521843e-1, 3.19919293e-1, 4.57125889e-1, 5.77618536e-1, 6.78756100e-1, 7.57607810e-1, 8.11671545e-1, 8.39164449e-1, 0.00000000e+0, 0.00000000e+0},
{1.53964763e-1, 2.97078021e-1, 4.24880024e-1, 5.38470831e-1, 6.35860400e-1, 7.14630916e-1, 7.72600158e-1, 8.08085104e-1, 4.10016332e-1, 0.00000000e+0},
{1.43794085e-1, 2.76978325e-1, 3.96360733e-1, 5.03501168e-1, 5.96926221e-1, 6.74646597e-1, 7.34775005e-1, 7.75766941e-1, 7.96540602e-1, 0.00000000e+0},
{1.34782229e-1, 2.59176387e-1, 3.71000554e-1, 4.72153283e-1, 5.61572995e-1, 6.37627122e-1, 6.98691780e-1, 7.43373179e-1, 7.70618449e-1, 3.89886704e-1}};
double BesselCoefB[18][10] = {
{6.18033989e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{4.77191359e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{3.88990734e-1, 4.88904151e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{3.24532958e-1, 4.12845035e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.75640713e-1, 3.50472682e-1, 3.88718371e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.38071830e-1, 3.01095494e-1, 3.39457362e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{2.08745496e-1, 2.62125007e-1, 2.97923772e-1, 3.16161446e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.85417727e-1, 2.31048972e-1, 2.63561659e-1, 2.83414384e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.66512035e-1, 2.05908519e-1, 2.35144786e-1, 2.54933562e-1, 2.64963862e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.50928257e-1, 1.85267830e-1, 2.11494870e-1, 2.30458269e-1, 2.41997904e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.37889361e-1, 1.68085979e-1, 1.91640272e-1, 2.09464363e-1, 2.21510535e-1, 2.27594748e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.26836232e-1, 1.53603125e-1, 1.74816790e-1, 1.91408216e-1, 2.03410089e-1, 2.10690872e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.17358569e-1, 1.41257383e-1, 1.60431675e-1, 1.75804748e-1, 1.87465329e-1, 1.95327042e-1, 1.99288298e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.09149583e-1, 1.30627119e-1, 1.48025483e-1, 1.62244776e-1, 1.73411905e-1, 1.81477112e-1, 1.86358434e-1, 0.00000000e+0, 0.00000000e+0, 0.00000000e+0},
{1.01975884e-1, 1.21391278e-1, 1.37240264e-1, 1.50391095e-1, 1.60995980e-1, 1.69033936e-1, 1.74442048e-1, 1.77162502e-1, 0.00000000e+0, 0.00000000e+0},
{9.56571087e-2, 1.13301940e-1, 1.27794991e-1, 1.39968287e-1, 1.49990121e-1, 1.57861706e-1, 1.63537080e-1, 1.66966155e-1, 0.00000000e+0, 0.00000000e+0},
{9.00518801e-2, 1.06165141e-1, 1.19467098e-1, 1.30751802e-1, 1.40197067e-1, 1.47821002e-1, 1.53592086e-1, 1.57468684e-1, 1.59416436e-1, 0.00000000e+0},
{8.50479394e-2, 9.98272764e-2, 1.12078713e-1, 1.22558206e-1, 1.31448429e-1, 1.38780190e-1, 1.44534000e-1, 1.48676318e-1, 1.51176082e-1, 0.00000000e+0}};
// -----------------------------------------------------------------------
// Calculate normalized quadratic polynom coefficients of Bessel filters.
double Filter::quadraticBesselValues(int No, int Order, double &b)
{
if(No == 0) { // linear coefficient for odd order filter?
b = 0;
return BesselCoefA [Order - 2] [Order/2];
}
b = BesselCoefB [Order - 2] [No-1];
return BesselCoefA [Order - 2] [No-1];
}
// -----------------------------------------------------------------------
// Calculate normalized quadratic polynom coefficients of Butterworth filters.
double Filter::quadraticButterworthValues(int No, int Order, double &b)
{
if(No == 0) { // linear coefficient for odd order filter?
b = 0;
return 1.0;
}
double a;
if(Order & 1)
a = double(No);
else
a = double(2*No-1) / 2.0;
a = 2.0 * cos(a * M_PI / double(Order));
b = 1.0;
return a;
}
// -----------------------------------------------------------------------
// Calculate normalized quadratic polynom coefficients of Chebyshev filters.
double Filter::quadraticChebyshevValues(int No, int Order, double Ripple, double &b)
{
double a;
if(No == 0) { // linear coefficient for odd order filter?
b = 0;
a = asinh(1.0 / sqrt(pow(10.0, Ripple/10.0) - 1.0)) / double(Order);
a = 1.0 / sinh(a);
return a;
}
double c = asinh(1.0 / sqrt(pow(10.0, Ripple/10.0) - 1.0)) / double(Order);
if(Order & 1)
a = double(No);
else
a = double(2*No-1) / 2.0;
a = cos(a * M_PI / double(Order));
b = 1.0 / (cosh(c) * cosh(c) - a*a);
a *= 2.0 * b * sinh(c);
return a;
}