denorm_proto.cpp
上传用户:jtjnyq9001
上传日期:2014-11-21
资源大小:3974k
文件大小:15k
源码类别:

3G开发

开发平台:

Visual C++

  1. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. //
  3. //  File = denorm_proto.cpp
  4. //
  5. //  Converts a normalized lowpass prototype filter
  6. //  into a denormalized LP, BP, BS, or HP filter.
  7. //
  8. #include <iostream> 
  9. #include <fstream>
  10. #include <math.h>
  11. #include "misdefs.h"
  12. #include "parmfile.h"
  13. #include "denorm_proto.h"
  14. #include "filter_types.h"
  15. extern ParmFile ParmInput;
  16. extern ofstream *DebugFile;
  17. //======================================================
  18. //  constructor
  19. DenormalizedPrototype::DenormalizedPrototype( AnalogFilterPrototype *lowpass_proto_filt,
  20.                                               FILT_BAND_CONFIG_T filt_band_config,
  21.                                               double passband_edge,
  22.                                               double passband_edge_2 )
  23.                       :AnalogFilterPrototype()
  24. {
  25.   Filt_Order = lowpass_proto_filt->GetOrder();
  26.   Filt_Band_Config = filt_band_config;
  27.   Passband_Edge = passband_edge;
  28.   Passband_Edge_2 = passband_edge_2;
  29.   Lowpass_Proto_Filt = lowpass_proto_filt;
  30.   switch (Filt_Band_Config) 
  31.     {
  32.     case LOWPASS_FILT_BAND_CONFIG:
  33.       {
  34.       LowpassDenormalize();
  35.       break;
  36.       }
  37.     case BANDPASS_FILT_BAND_CONFIG:
  38.       {
  39.       BandpassDenormalize();
  40.       break;
  41.       }
  42.     case HIGHPASS_FILT_BAND_CONFIG:
  43.       {
  44.       HighpassDenormalize();
  45.       break;
  46.       }
  47.     case BANDSTOP_FILT_BAND_CONFIG:
  48.       {
  49.       BandstopDenormalize();
  50.       break;
  51.       }
  52.     default:
  53.       {
  54.       cout << "Invalid Filter Band Config in DenormalizedPrototype" << endl;
  55.       exit(0);
  56.       }
  57.     }// end of switch on Filt_Band_Config
  58. }
  59. //=======================================================
  60. //  destructor
  61. DenormalizedPrototype::~DenormalizedPrototype()
  62. {
  63.   if( !(Pole_Locs == NULL) ) delete []Pole_Locs;
  64.   if( !(Zero_Locs == NULL) ) delete []Zero_Locs;
  65. }
  66. //================================================
  67. void DenormalizedPrototype::LowpassDenormalize(void)
  68. {
  69.   double cutoff_freq;
  70.   int j;
  71.   std::complex<double> *prototype_poles;
  72.   std::complex<double> *prototype_zeros;
  73.   prototype_poles = Lowpass_Proto_Filt->GetPoles();
  74.   prototype_zeros = Lowpass_Proto_Filt->GetZeros();
  75.   Num_Poles = Lowpass_Proto_Filt->GetNumPoles();
  76.   Num_Zeros = Lowpass_Proto_Filt->GetNumZeros();
  77.   //H_Zero = 1.0;
  78.   H_Zero = Lowpass_Proto_Filt->GetHZero();
  79.   cutoff_freq = TWO_PI * Passband_Edge;
  80.   Pole_Locs = new std::complex<double>[Num_Poles];
  81.   for( j=0; j<Num_Poles; j++)
  82.     {
  83.     Pole_Locs[j] = prototype_poles[j] * cutoff_freq;
  84.     //H_Zero *= std::abs<double>(Pole_Locs[j]);
  85.     H_Zero *= cutoff_freq;
  86.     #ifdef _DEBUG
  87.       *DebugFile << "Denorm Pole_Locs[" << j << "] = (" 
  88.                 << std::real(Pole_Locs[j]) << ", "
  89.                 << std::imag(Pole_Locs[j]) << ")" << endl;
  90.     #endif
  91.     }
  92.   #ifdef _DEBUG
  93.     *DebugFile << "after poles, H_Zero = " << H_Zero << endl;
  94.   #endif
  95.   Zero_Locs = new std::complex<double>[Num_Zeros];
  96.   for( j=0; j<Num_Zeros; j++)
  97.     {
  98.     Zero_Locs[j] = prototype_zeros[j] * cutoff_freq;
  99.     //H_Zero /= std::abs<double>(Zero_Locs[j]);
  100.     H_Zero /= cutoff_freq;
  101.     #ifdef _DEBUG
  102.       *DebugFile << "Denorm Zero_Locs[" << j << "] = (" 
  103.                 << std::real(Zero_Locs[j]) << ", "
  104.                 << std::imag(Zero_Locs[j]) << ")" << endl;
  105.     #endif
  106.     }
  107.   #ifdef _DEBUG
  108.     *DebugFile << "after zeros, H_Zero = " << H_Zero << endl;
  109.   #endif
  110. }
  111. //================================================
  112. void DenormalizedPrototype::HighpassDenormalize(void)
  113. {
  114.   //double cutoff_freq;
  115.   int j;
  116.   int num_prototype_zeros;
  117.   std::complex<double> *prototype_poles;
  118.   std::complex<double> *prototype_zeros;
  119.   std::complex<double> cutoff_freq;
  120.   prototype_poles = Lowpass_Proto_Filt->GetPoles();
  121.   prototype_zeros = Lowpass_Proto_Filt->GetZeros();
  122.   Num_Poles = Lowpass_Proto_Filt->GetNumPoles();
  123.   num_prototype_zeros = Lowpass_Proto_Filt->GetNumZeros();
  124.   // highpass will have a zero at s=0 for each
  125.   // prototype zero at infinity
  126.   Num_Zeros = Num_Poles;
  127.   H_Zero = 1.0;
  128.   cutoff_freq = TWO_PI * Passband_Edge;
  129.   //  Divide the cutoff frequency (in rad/s) by the normalized pole
  130.   //  locations to give the desired highpass poles.  This moves the poles
  131.   //  from the unti circle onto a circle of radius cutoff_freq.
  132.   Pole_Locs = new std::complex<double>[Num_Poles];
  133.   for( j=0; j<Num_Poles; j++)
  134.     {
  135.     Pole_Locs[j] = cutoff_freq / prototype_poles[j];
  136.     }
  137.   // Map the finite zeros of prototype (if any) into HP locs
  138.   Zero_Locs = new std::complex<double>[Num_Zeros];
  139.   for( j=0; j<num_prototype_zeros; j++)
  140.     {
  141.     Zero_Locs[j] = cutoff_freq / prototype_zeros[j];
  142.     }
  143.   // Map the infinite zeros of prototype into HP zeros at s=0.
  144.   for( j=num_prototype_zeros; j<Num_Zeros; j++)
  145.     {
  146.     Zero_Locs[j] = 0.0;
  147.     }
  148. }
  149. //============================================================
  150. // The lowpass to bandpass transformation implemented in this 
  151. // function is based on Section 4.4.3 of "Filtering in the Time and
  152. // Frequency Domains" by Herman J. Blinchikoff and Anatol I. Zverev
  153. // (Wiley 1976).
  154. void DenormalizedPrototype::BandpassDenormalize(void)
  155. {
  156.   //double cutoff_freq;
  157.   int i;
  158. //  int num_prototype_zeros;
  159.   int num_prototype_poles;
  160.   double omega_a, omega_b, omega_zero;
  161.   double alpha, beta, gamma;
  162.   double big_a, big_b;
  163.   double little_a, little_b;
  164.   double radical;
  165.   double real_chunk, imag_chunk;
  166.   int pole_num;
  167.   int proto_pole_num;
  168.   double sign;
  169.   std::complex<double> *prototype_poles;
  170. //  std::complex<double> *prototype_zeros;
  171.   prototype_poles = Lowpass_Proto_Filt->GetPoles();
  172.   //prototype_zeros = Lowpass_Proto_Filt->GetZeros();
  173.   num_prototype_poles = Lowpass_Proto_Filt->GetNumPoles();
  174.   Num_Poles = 2 * num_prototype_poles;
  175.   Num_Zeros = num_prototype_poles;
  176.   //num_prototype_zeros = Lowpass_Proto_Filt->GetNumZeros();
  177.   H_Zero = 1.0;
  178.   Pole_Locs = new std::complex<double>[Num_Poles];
  179.   Zero_Locs = new std::complex<double>[Num_Zeros];
  180.   for(i=0; i<Num_Zeros; i++)
  181.     {
  182.     Zero_Locs[i] = 0.0;
  183.     }
  184.   // convert critical frequencies from Hz to rad/sec
  185.   //omega_b = TWO_PI * Passband_Edge_2; // flipped sense of omega_a/b on 11/30/00
  186.   //omega_a = TWO_PI * Passband_Edge;
  187.   omega_a = TWO_PI * Passband_Edge;
  188.   omega_b = TWO_PI * Passband_Edge_2;
  189.   pole_num = -1;
  190.   // compute omega_zero as geometric mean of omega_a and omega_b
  191.   omega_zero = sqrt(omega_a * omega_b);
  192.   // compute the relative bandwidth, gamma
  193.   gamma = (omega_b - omega_a)/omega_zero;
  194.   // For each pole pair of the prototype we
  195.   // will generate 2 pole pairs..
  196.   // If num_prototype poles is odd, then we 
  197.   // will calculate the last two poles which
  198.   // are associated the real-valued prototype
  199.   // pole later on.
  200.   for(  proto_pole_num=1;
  201.         proto_pole_num <= num_prototype_poles/2;
  202.         proto_pole_num++)
  203.     {
  204.     *DebugFile << "working on proto pole " << proto_pole_num-1
  205.               << " at ( " << prototype_poles[proto_pole_num-1].real()
  206.               << ", " << prototype_poles[proto_pole_num-1].imag()
  207.               << " )" << endl;
  208.     //easter alpha = prototype_poles[proto_pole_num-1].real();
  209.     alpha = -prototype_poles[proto_pole_num-1].real();
  210.     beta = fabs(prototype_poles[proto_pole_num-1].imag());
  211.     big_a = 1.0 - (( gamma * gamma / 4.0) *
  212.                 ( alpha * alpha - beta * beta ));
  213.     big_b = -alpha * beta * gamma * gamma / 2.0;
  214.     radical = sqrt( big_a * big_a + big_b * big_b );
  215.     little_a = sqrt( ( radical + big_a ) / 2.0 );
  216.     little_b = sqrt( ( radical - big_a ) / 2.0 );
  217.     // for each prototype pair....
  218.     sign = 1.0;
  219.     for( i=0; i<2; i++)
  220.       {
  221.       real_chunk = omega_zero *
  222.           ((-gamma * alpha / 2.0) + sign * little_b);
  223.       imag_chunk = omega_zero *
  224.           ((gamma * beta / 2.0) - sign * little_a);
  225.           //((gamma * beta / 2.0) + sign * little_a);  // for alpha .lt. 0
  226.           //((gamma * beta / 2.0) - sign * little_a);  // for alpha .gt. 0
  227.       pole_num++;
  228.       Pole_Locs[pole_num] = std::complex<double>(real_chunk, imag_chunk);
  229.       #ifdef _DEBUG
  230.         *DebugFile << "   made new pole at ( " << real_chunk << ", "
  231.                   << imag_chunk << " ) " << endl;
  232.       #endif
  233.     
  234.       pole_num++;
  235.       Pole_Locs[pole_num] = std::complex<double>(real_chunk, (-imag_chunk) );
  236.       #ifdef _DEBUG
  237.         *DebugFile << "   made new pole at ( " << real_chunk << ", "
  238.                   << (-imag_chunk) << " ) " << endl;
  239.       #endif
  240.       sign = -sign;
  241.       }
  242.     }
  243.   //-------------------------------------------------------------
  244.   //  if number of lowpass poles is odd, do special
  245.   //  transformation for the pole on the real axis
  246.   
  247.   if( (num_prototype_poles%2) != 0)
  248.     {
  249.     //alpha = std::real<double>( prototype_poles[ num_prototype_poles/2+1 ] );
  250.     //beta = std::imag<double>( prototype_poles[ num_prototype_poles/2+1 ] );
  251.     alpha = std::real<double>( prototype_poles[ num_prototype_poles/2 ] );
  252.     beta = std::imag<double>( prototype_poles[ num_prototype_poles/2 ] );
  253.     big_a = 1.0 - gamma * gamma * alpha * alpha / 4.0;
  254.     if( fabs(beta) > 0.0000001)
  255.       {
  256.       cout << "middle lowpass pole not on the real axis" << endl;
  257.       cout << "pole at ( " << prototype_poles[ num_prototype_poles/2+1 ].real()
  258.             << ", " << prototype_poles[ num_prototype_poles/2+1 ].imag()
  259.             << " ) " << endl;
  260.       exit(11);
  261.       }
  262.     if( big_a <= 0.0 )
  263.       {
  264.       cout << "error" << endl;
  265.       exit(99);
  266.       }
  267.     else
  268.       {
  269.       real_chunk = alpha * (omega_b - omega_a) / 2.0;
  270.       imag_chunk = omega_zero * sqrt(big_a);
  271.       pole_num++;
  272.       Pole_Locs[pole_num] = std::complex<double>( real_chunk, imag_chunk);
  273.       pole_num++;
  274.       Pole_Locs[pole_num] = std::complex<double>( real_chunk, (-imag_chunk) );
  275.       }
  276.     }
  277.   // calculate H_Zero
  278.   std::complex<double> cmpx_omega_zero;
  279.   cmpx_omega_zero = std::complex<double>(0.0, omega_zero);
  280.   for( i=0; i<Num_Poles; i++)
  281.     {
  282.     H_Zero *= std::abs<double>( Pole_Locs[i] - cmpx_omega_zero );
  283.     }
  284.   for( i=0; i<Num_Zeros; i++)
  285.     {
  286.     H_Zero /= std::abs<double>( Zero_Locs[i] - cmpx_omega_zero );
  287.     }
  288. }
  289. //============================================================
  290. // The lowpass to bandstop transformation implemented in this 
  291. // function is based on Section 4.7.1 of "Filtering in the Time and
  292. // Frequency Domains" by Herman J. Blinchikoff and Anatol I. Zverev
  293. // (Wiley 1976).  Equation (4.7-4) was algebraically manipulated
  294. // to obtain explict expressions for the BS pole pairs that are
  295. // similar to the expressions provided for BP case in (4.4-31)
  296. void DenormalizedPrototype::BandstopDenormalize(void)
  297. {
  298.   int i;
  299.   int num_prototype_poles;
  300.   int pole_num, proto_pole_num;
  301.   double omega_a, omega_b, omega_zero;
  302.   double alpha, beta, gamma;
  303.   double big_a, big_b, big_c, big_c_sqrd;
  304.   double radical, sign;
  305.   double little_a, little_b;
  306.   double real_chunk, imag_chunk;
  307.   std::complex<double> *prototype_poles;
  308.   prototype_poles = Lowpass_Proto_Filt->GetPoles();
  309.   num_prototype_poles = Lowpass_Proto_Filt->GetNumPoles();
  310.   Num_Poles = 2 * num_prototype_poles;
  311.   Num_Zeros = 2 * num_prototype_poles;
  312.   H_Zero = 1.0;
  313.   Pole_Locs = new std::complex<double>[Num_Poles];
  314.   Zero_Locs = new std::complex<double>[Num_Zeros];
  315.   // convert critical frequencies from Hz to rad/sec
  316.   omega_b = TWO_PI * Passband_Edge_2;
  317.   omega_a = TWO_PI * Passband_Edge;
  318.   pole_num = -1;
  319.   // compute omega_zero as geometric mean of omega_a and omega_b
  320.   omega_zero = sqrt(omega_a * omega_b);
  321.   // put N zeros at +(j * omega_zero) and N zeros at -(j * omega_zero)
  322.   for(i=0; i<Num_Zeros/2; i++)
  323.     {
  324.     Zero_Locs[2*i] = std::complex<double>(0.0, omega_zero);
  325.     Zero_Locs[2*i+1] = std::complex<double>(0.0, -omega_zero);
  326.     }
  327.   // compute the relative bandwidth, gamma
  328.   gamma = (omega_b - omega_a)/omega_zero;
  329.   //gamma = (omega_a - omega_b)/omega_zero;
  330.   // For each pole pair of the prototype we 
  331.   // will generate 2 pole pairs..
  332.   // If num_prototype poles is odd, then we
  333.   // will calculate the last two poles which
  334.   // are associated with the real-valued prototype
  335.   // pole later on.
  336.   for(  proto_pole_num = 1;
  337.         proto_pole_num <= num_prototype_poles/2;
  338.         proto_pole_num++)
  339.     {
  340.     #ifdef _DEBUG
  341.       *DebugFile << "working on proto pole " << proto_pole_num-1
  342.                 << " at ( " << prototype_poles[proto_pole_num-1].real()
  343.                 << ", " << prototype_poles[proto_pole_num-1].imag()
  344.                 << " )" << endl;
  345.     #endif
  346.   
  347.     alpha = -prototype_poles[proto_pole_num-1].real();
  348.     beta = fabs(prototype_poles[proto_pole_num-1].imag());
  349.     big_c = -gamma / (2.0 * ( alpha*alpha + beta*beta ));
  350.     big_c_sqrd = big_c * big_c;
  351.   
  352.     big_a = 1.0 - (alpha * alpha * big_c_sqrd) + (beta * beta * big_c_sqrd);
  353.     big_b = -2.0 * alpha * beta * big_c_sqrd;
  354.     radical = sqrt( big_a * big_a + big_b * big_b );
  355.     little_a = sqrt( ( radical + big_a ) / 2.0 );
  356.     little_b = sqrt( ( radical - big_a ) / 2.0 );
  357.     // for each prototype pair...
  358.     sign = 1.0;
  359.     for( i=0; i<2; i++)
  360.       {
  361.       real_chunk = omega_zero * (alpha * big_c + sign * little_b);
  362.       imag_chunk = omega_zero * (beta * big_c + sign * little_a);
  363.       pole_num++;
  364.       Pole_Locs[pole_num] = std::complex<double>(real_chunk, imag_chunk);
  365.       #ifdef _DEBUG
  366.         *DebugFile << "   made new pole at ( " << real_chunk << ", "
  367.                   << imag_chunk << " )" << endl;
  368.       #endif
  369.       pole_num++;
  370.       Pole_Locs[pole_num] = std::complex<double>(real_chunk, (-imag_chunk));
  371.       #ifdef _DEBUG
  372.         *DebugFile << "   made new pole at ( " << real_chunk << ", "
  373.                   << (-imag_chunk) << " )" << endl;
  374.       #endif
  375.       sign = -sign;
  376.       }
  377.     } // end of loop over prototype pole pairs
  378.   //------------------------------------------------
  379.   // if number of lowpass poles is odd, do special
  380.   // transformation for the pole on the real axis
  381.   if( (num_prototype_poles%2) != 0)
  382.     {
  383.     alpha = -prototype_poles[num_prototype_poles/2].real();
  384.     beta = prototype_poles[num_prototype_poles/2].imag();
  385.     big_a = 1.0 - gamma * gamma * alpha * alpha;
  386.     if( fabs(beta) > 0.0000001)
  387.       {
  388.       cout << "middle lowpass pole not on the real axis" << endl;
  389.       cout << "pole at ( " << prototype_poles[num_prototype_poles/2].real()
  390.             << ", " << beta << " )" << endl;
  391.       exit(11);
  392.       }
  393.     else
  394.       {
  395.       real_chunk = alpha;
  396.       }
  397.     }
  398.   //
  399.   // calculate H_Zero
  400. }