Advertisement
Guest User

Untitled

a guest
Dec 18th, 2018
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.65 KB | None | 0 0
  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <complex.h>
  6.  
  7. typedef struct {
  8.   float a1;
  9.   float a2;
  10.   float a3;
  11.   float b0;
  12.   float b1;
  13.   float b2;
  14.   float b3;
  15. } BiquadCoeffs;
  16.  
  17.  
  18. /* print array of three complex numbers */
  19. void print_array_len3(char prefix[], float complex ary[3]) {
  20.     printf("%s: array([ %f %fj, %f %fj, %f %fj ])\n",
  21.            prefix,
  22.            creal(ary[0]), cimag(ary[0]),
  23.            creal(ary[1]), cimag(ary[1]),
  24.            creal(ary[2]), cimag(ary[2]));
  25. }
  26.  
  27.  
  28. /* return 3rd order butterworth filter coefficients,
  29.     Wn is the cutoff frequency in rad,
  30.     btype can either be "low" or "high"
  31. */
  32. BiquadCoeffs butter_3rd(float Wn, char* btype) {
  33.     BiquadCoeffs coeffs = { 0, 0, 0, 0, 0, 0, 0 };
  34.     int idx;
  35.     float complex p_proto[3];    // array of the three analog prototype poles
  36.     float warped;                // warped cutoff frequency
  37.     float complex z_analog[3];   // array of the three analog zeroes
  38.     float complex z_digital[3];  // array of the three digital zeroes
  39.     float complex p_analog[3];   // array of the three analog poles
  40.     float complex p_digital[3];  // array of the three digital poles
  41.     float k_analog, k_digital;   // analog and digital gain
  42.     float complex tmp1, tmp2;    // temporary variables
  43.    
  44.    
  45.     // calculate poles of the analog prototype filter
  46.     /* python code:
  47.         p_proto = []
  48.         for m in (-2, 0, 2):
  49.             p_proto.append(-numpy.exp(1j * pi * m / 6))
  50.     */
  51.     for (int m = -2; m <= 2; m += 2){
  52.         idx = (m + 2) / 2;
  53.         p_proto[idx] = -1.0 * cexp(0+1i * M_PI * m / 6.0);
  54.     }
  55.     print_array_len3("p_proto", p_proto);
  56.    
  57.    
  58.     // pre-warping factor
  59.     /* python code:
  60.         warped = 4 * tan(pi * Wn / 2)
  61.     */
  62.     warped = 4.0 * tan(M_PI * Wn / 2.0);
  63.     printf("warped: %f\n", warped);
  64.  
  65.  
  66.     // construct high/lowpass zeros and poles according btype
  67.     if (strcmp(btype, "low") == 0) {
  68.         /* python code:
  69.             z_analog = numpy.array([])
  70.             z_digital = numpy.array(-numpy.ones(3))
  71.             p_analog = warped * p
  72.             k_analog = warped ** 3
  73.         */
  74.         // z_analog is not needed later
  75.         for (idx=0; idx<3; idx++)
  76.             z_digital[idx] = -1.0;
  77.         for (idx=0; idx<3; idx++)
  78.             p_analog[idx] = warped * p_proto[idx];
  79.         k_analog = warped * warped * warped;
  80.     } else if (strcmp(btype, "high") == 0) {
  81.         /* python code:
  82.             z_analog = numpy.zeros(3)
  83.             z_digital = numpy.ones(3)
  84.             p_analog = warped / p
  85.             k_analog = 1
  86.         */
  87.         for (idx=0; idx<3; idx++)
  88.             z_analog[idx] = 0.0;
  89.         for (idx=0; idx<3; idx++)
  90.             z_digital[idx] = 1.0;
  91.         for (idx=0; idx<3; idx++)
  92.             p_analog[idx] = warped / p_proto[idx];
  93.         k_analog = 1;
  94.     }
  95.     print_array_len3("z_analog", z_analog);
  96.     print_array_len3("z_digital", z_digital);
  97.     print_array_len3("p_analog", p_analog);
  98.     printf("k_analog: %f\n", k_analog);
  99.  
  100.  
  101.     /* python code:
  102.         p_digital = (4 + p_analog) / (4 - p_analog)
  103.     */
  104.     for (idx=0; idx<3; idx++)
  105.         p_digital[idx] = (4 + p_analog[idx]) / (4 - p_analog[idx]);
  106.     print_array_len3("p_digital", p_digital);
  107.  
  108.     /* python code:
  109.         k_digital = k_analog * numpy.real(numpy.prod(4 - z_analog) / numpy.prod(4 - p_analog))
  110.     */
  111.     if (strcmp(btype, "low") == 0) {
  112.         tmp1 = 1.0; // special case, z_analog is empty in case of lowpass filter
  113.     } else if (strcmp(btype, "high") == 0) {
  114.         tmp1 = 4.0 - z_analog[0];
  115.         for (idx=1; idx<3; idx++)
  116.             tmp1 = tmp1 * (4.0 - z_analog[idx]);
  117.     }
  118.     tmp2 = 4.0 - p_analog[0];
  119.     for (idx=1; idx<3; idx++)
  120.         tmp2 = tmp2 * (4.0 - p_analog[idx]);
  121.     k_digital = k_analog * creal(tmp1 / tmp2);
  122.     printf("k_digital: %f\n", k_digital);
  123.  
  124.  
  125.     // transform to ba form
  126.     /* python code:
  127.         b = k_digital * numpy.poly(z_digital)
  128.         a = numpy.poly(p_digital)
  129.     */
  130.     // NEED HELP!!! :)
  131.  
  132.     return coeffs;
  133. }
  134.  
  135.  
  136. int main() {
  137.     BiquadCoeffs coeffs;
  138.     float Wn = 0.2;
  139.  
  140.     printf("\nlow\n===\n");
  141.     coeffs = butter_3rd(Wn, "low");
  142.     printf("coeffs b: %0.8f %0.8f %0.8f %0.8f\n", coeffs.b0, coeffs.b1, coeffs.b2, coeffs.b3);
  143.     printf("coeffs a: %0.8f %0.8f %0.8f %0.8f\n", 1.0000000, coeffs.a1, coeffs.a2, coeffs.a3);
  144.  
  145.     printf("\nhigh\n====\n");
  146.     coeffs = butter_3rd(Wn, "high");
  147.     printf("coeffs b: %0.8f %0.8f %0.8f %0.8f\n", coeffs.b0, coeffs.b1, coeffs.b2, coeffs.b3);
  148.     printf("coeffs a: %0.8f %0.8f %0.8f %0.8f\n", 1.0000000, coeffs.a1, coeffs.a2, coeffs.a3);
  149. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement