![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Cutoff frequency variable LPF, HPF, BPF, and BRF by FIR 160th-order filter.
Dependencies: UIT_ACM1602NI UITDSP_ADDA mbed UIT_AQM1602
WindowingDesign/WindowingDesign.cpp@3:24b6aa1a19ba, 2015-07-25 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Sat Jul 25 06:36:06 2015 +0000
- Revision:
- 3:24b6aa1a19ba
- Parent:
- 0:ca94cfc90365
4
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:ca94cfc90365 | 1 | //------------------------------------------------------------------------------ |
MikamiUitOpen | 0:ca94cfc90365 | 2 | // Design of FIR filter of 4 type passbands using window method |
MikamiUitOpen | 0:ca94cfc90365 | 3 | // |
MikamiUitOpen | 0:ca94cfc90365 | 4 | // 2014/12/07, Copyright (c) 2014 MIKAMI, Naoki |
MikamiUitOpen | 0:ca94cfc90365 | 5 | //------------------------------------------------------------------------------ |
MikamiUitOpen | 0:ca94cfc90365 | 6 | |
MikamiUitOpen | 0:ca94cfc90365 | 7 | #include "WindowingDesign.hpp" |
MikamiUitOpen | 0:ca94cfc90365 | 8 | |
MikamiUitOpen | 0:ca94cfc90365 | 9 | namespace Mikami |
MikamiUitOpen | 0:ca94cfc90365 | 10 | { |
MikamiUitOpen | 0:ca94cfc90365 | 11 | WindowingDesign::WindowingDesign(int order, float fs) |
MikamiUitOpen | 0:ca94cfc90365 | 12 | : FS_(fs), PI_FS_(3.1415926536f/fs) |
MikamiUitOpen | 0:ca94cfc90365 | 13 | { |
MikamiUitOpen | 0:ca94cfc90365 | 14 | order_ = order; |
MikamiUitOpen | 0:ca94cfc90365 | 15 | if ((order % 2) != 0) |
MikamiUitOpen | 0:ca94cfc90365 | 16 | { |
MikamiUitOpen | 0:ca94cfc90365 | 17 | fprintf(stderr, "order must be even."); |
MikamiUitOpen | 0:ca94cfc90365 | 18 | return; |
MikamiUitOpen | 0:ca94cfc90365 | 19 | } |
MikamiUitOpen | 0:ca94cfc90365 | 20 | hm_ = new float[order/2+1]; |
MikamiUitOpen | 0:ca94cfc90365 | 21 | wn_ = new float[order/2+1]; |
MikamiUitOpen | 0:ca94cfc90365 | 22 | |
MikamiUitOpen | 0:ca94cfc90365 | 23 | HammWindow(); |
MikamiUitOpen | 0:ca94cfc90365 | 24 | } |
MikamiUitOpen | 0:ca94cfc90365 | 25 | |
MikamiUitOpen | 0:ca94cfc90365 | 26 | void WindowingDesign::Design(int order, Type pb, |
MikamiUitOpen | 0:ca94cfc90365 | 27 | float fc1, float fc2, |
MikamiUitOpen | 0:ca94cfc90365 | 28 | float hk[]) |
MikamiUitOpen | 0:ca94cfc90365 | 29 | { |
MikamiUitOpen | 0:ca94cfc90365 | 30 | if (pb == LPF) fC_ = fc1; |
MikamiUitOpen | 0:ca94cfc90365 | 31 | if (pb == HPF) fC_ = 0.5f*FS_ - fc1; |
MikamiUitOpen | 0:ca94cfc90365 | 32 | |
MikamiUitOpen | 0:ca94cfc90365 | 33 | float w0 = PI_FS_*(fc1 + fc2); |
MikamiUitOpen | 3:24b6aa1a19ba | 34 | if ((pb == BPF) || (pb == BRF)) |
MikamiUitOpen | 0:ca94cfc90365 | 35 | fC_ = 0.5f*fabs(fc2 - fc1); |
MikamiUitOpen | 0:ca94cfc90365 | 36 | |
MikamiUitOpen | 0:ca94cfc90365 | 37 | if (order != order_) |
MikamiUitOpen | 0:ca94cfc90365 | 38 | { |
MikamiUitOpen | 0:ca94cfc90365 | 39 | order_ = order_; |
MikamiUitOpen | 0:ca94cfc90365 | 40 | if (hm_ != NULL) delete[] hm_; |
MikamiUitOpen | 0:ca94cfc90365 | 41 | hm_ = new float[order/2+1]; |
MikamiUitOpen | 0:ca94cfc90365 | 42 | if (wn_ != NULL) delete[] wn_; |
MikamiUitOpen | 0:ca94cfc90365 | 43 | wn_ = new float[order/2+1]; |
MikamiUitOpen | 0:ca94cfc90365 | 44 | HammWindow(); |
MikamiUitOpen | 0:ca94cfc90365 | 45 | } |
MikamiUitOpen | 0:ca94cfc90365 | 46 | |
MikamiUitOpen | 0:ca94cfc90365 | 47 | // Calculate coefficients for LPF |
MikamiUitOpen | 0:ca94cfc90365 | 48 | LpfCoefficients(); |
MikamiUitOpen | 0:ca94cfc90365 | 49 | // If not LPF, transform coefficients |
MikamiUitOpen | 0:ca94cfc90365 | 50 | if (pb != LPF) Transform(pb, w0); |
MikamiUitOpen | 0:ca94cfc90365 | 51 | |
MikamiUitOpen | 0:ca94cfc90365 | 52 | for (int k=0; k<=order/2; k++) |
MikamiUitOpen | 0:ca94cfc90365 | 53 | hk[k] = hm_[order/2-k]; |
MikamiUitOpen | 0:ca94cfc90365 | 54 | } |
MikamiUitOpen | 0:ca94cfc90365 | 55 | |
MikamiUitOpen | 0:ca94cfc90365 | 56 | // Calculation of coefficients for LPF |
MikamiUitOpen | 0:ca94cfc90365 | 57 | void WindowingDesign::LpfCoefficients() |
MikamiUitOpen | 0:ca94cfc90365 | 58 | { |
MikamiUitOpen | 0:ca94cfc90365 | 59 | float w = 2.0f*PI_FS_*fC_; |
MikamiUitOpen | 0:ca94cfc90365 | 60 | hm_[0] = 2.0f*fC_/FS_; |
MikamiUitOpen | 0:ca94cfc90365 | 61 | for (int k=1; k<=order_/2; k++) |
MikamiUitOpen | 0:ca94cfc90365 | 62 | hm_[k] = (sinf(k*w)/(PI_*k))*wn_[k]; |
MikamiUitOpen | 0:ca94cfc90365 | 63 | } |
MikamiUitOpen | 0:ca94cfc90365 | 64 | |
MikamiUitOpen | 0:ca94cfc90365 | 65 | // Transform LPF to HPF, BPF, or BRF |
MikamiUitOpen | 0:ca94cfc90365 | 66 | void WindowingDesign::Transform(Type pb, float w0) |
MikamiUitOpen | 0:ca94cfc90365 | 67 | { |
MikamiUitOpen | 0:ca94cfc90365 | 68 | if (pb == HPF) // To HPF |
MikamiUitOpen | 0:ca94cfc90365 | 69 | for (int k=1; k<=order_/2; k+=2) |
MikamiUitOpen | 0:ca94cfc90365 | 70 | hm_[k] = -hm_[k]; |
MikamiUitOpen | 0:ca94cfc90365 | 71 | |
MikamiUitOpen | 0:ca94cfc90365 | 72 | if (pb == BPF) // To BPF |
MikamiUitOpen | 0:ca94cfc90365 | 73 | for (int k=0; k<=order_/2; k++) |
MikamiUitOpen | 0:ca94cfc90365 | 74 | hm_[k] = 2.0f*cosf(w0*k)*hm_[k]; |
MikamiUitOpen | 0:ca94cfc90365 | 75 | |
MikamiUitOpen | 0:ca94cfc90365 | 76 | if (pb == BRF) // To BRF |
MikamiUitOpen | 0:ca94cfc90365 | 77 | { |
MikamiUitOpen | 0:ca94cfc90365 | 78 | hm_[0] = 1.0f - 2.0f*hm_[0]; |
MikamiUitOpen | 0:ca94cfc90365 | 79 | for (int k=1; k<=order_/2; k++) |
MikamiUitOpen | 0:ca94cfc90365 | 80 | hm_[k] = -2.0*cosf(w0*k)*hm_[k]; |
MikamiUitOpen | 0:ca94cfc90365 | 81 | } |
MikamiUitOpen | 0:ca94cfc90365 | 82 | } |
MikamiUitOpen | 0:ca94cfc90365 | 83 | |
MikamiUitOpen | 0:ca94cfc90365 | 84 | // Hamming window |
MikamiUitOpen | 0:ca94cfc90365 | 85 | void WindowingDesign::HammWindow() |
MikamiUitOpen | 0:ca94cfc90365 | 86 | { |
MikamiUitOpen | 0:ca94cfc90365 | 87 | float pi2OvM = 2.0f*PI_/(float)(order_ + 1); |
MikamiUitOpen | 0:ca94cfc90365 | 88 | for (int n=0; n<=order_/2; n++) |
MikamiUitOpen | 0:ca94cfc90365 | 89 | wn_[n] = 0.54f + 0.46f*cosf(pi2OvM*n); |
MikamiUitOpen | 0:ca94cfc90365 | 90 | } |
MikamiUitOpen | 0:ca94cfc90365 | 91 | } |