?
DesignerDrawer.cpp@0:cacfc9e25452, 2019-06-04 (annotated)
- Committer:
- phungductung
- Date:
- Tue Jun 04 21:58:08 2019 +0000
- Revision:
- 0:cacfc9e25452
?;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
phungductung | 0:cacfc9e25452 | 1 | //------------------------------------------------------------------------------ |
phungductung | 0:cacfc9e25452 | 2 | // IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス |
phungductung | 0:cacfc9e25452 | 3 | // |
phungductung | 0:cacfc9e25452 | 4 | // 2016/05/01, Copyright (c) 2016 MIKAMI, Naoki |
phungductung | 0:cacfc9e25452 | 5 | //------------------------------------------------------------------------------ |
phungductung | 0:cacfc9e25452 | 6 | |
phungductung | 0:cacfc9e25452 | 7 | #include "DesignerDrawer.hpp" |
phungductung | 0:cacfc9e25452 | 8 | |
phungductung | 0:cacfc9e25452 | 9 | namespace Mikami |
phungductung | 0:cacfc9e25452 | 10 | { |
phungductung | 0:cacfc9e25452 | 11 | // Constructor |
phungductung | 0:cacfc9e25452 | 12 | DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0, |
phungductung | 0:cacfc9e25452 | 13 | float db1, int fs, int order, |
phungductung | 0:cacfc9e25452 | 14 | float fc, uint16_t fL, uint16_t fH, |
phungductung | 0:cacfc9e25452 | 15 | BilinearDesign::Type lpHp) |
phungductung | 0:cacfc9e25452 | 16 | : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()), |
phungductung | 0:cacfc9e25452 | 17 | X0_(x0), Y0_(y0), ORDER_(order), |
phungductung | 0:cacfc9e25452 | 18 | CURSOR_Y0_(y0+1-db1*60), CURSOR_LENGTH_(db1*60-1), |
phungductung | 0:cacfc9e25452 | 19 | LOWER_F_(fL), HIGHER_F_(fH), |
phungductung | 0:cacfc9e25452 | 20 | CURSOR_COLOR_(0xFFE000D0), CURSOR_TOUCHED_COLOR_(0xFFFF80FF) |
phungductung | 0:cacfc9e25452 | 21 | { |
phungductung | 0:cacfc9e25452 | 22 | drawerObj_ = new FrqRespDrawer(x0, 100.0f, 20000.0f, 140, |
phungductung | 0:cacfc9e25452 | 23 | y0, -60, 0, db1, 10, fs); |
phungductung | 0:cacfc9e25452 | 24 | |
phungductung | 0:cacfc9e25452 | 25 | // 双一次 z 変換による IIR フィルタの設計 |
phungductung | 0:cacfc9e25452 | 26 | designObj_ = new BilinearDesign(order, fs); |
phungductung | 0:cacfc9e25452 | 27 | coefs_ = new BilinearDesign::Coefs[order/2]; |
phungductung | 0:cacfc9e25452 | 28 | ck_ = (Biquad::Coefs *)coefs_; |
phungductung | 0:cacfc9e25452 | 29 | |
phungductung | 0:cacfc9e25452 | 30 | fC_ = fc; // 最初に与える遮断周波数 |
phungductung | 0:cacfc9e25452 | 31 | designObj_->Execute(fC_, lpHp, coefs_, g0_); |
phungductung | 0:cacfc9e25452 | 32 | frqResp_ = new IIR_CascadeFrqResp(); |
phungductung | 0:cacfc9e25452 | 33 | frqResp_->SetParams(ORDER_, g0_, ck_); |
phungductung | 0:cacfc9e25452 | 34 | |
phungductung | 0:cacfc9e25452 | 35 | // 周波数特性の描画 |
phungductung | 0:cacfc9e25452 | 36 | lblFrq_ = new NumericLabel<int>(110, 38); |
phungductung | 0:cacfc9e25452 | 37 | DrawResponse(); |
phungductung | 0:cacfc9e25452 | 38 | tp_ = new TouchPanelDetectorX( |
phungductung | 0:cacfc9e25452 | 39 | drawerObj_->X(LOWER_F_), drawerObj_->X(HIGHER_F_), |
phungductung | 0:cacfc9e25452 | 40 | CURSOR_Y0_, y0); |
phungductung | 0:cacfc9e25452 | 41 | lp_ = lpHp; |
phungductung | 0:cacfc9e25452 | 42 | cursorRedraw_ = false; |
phungductung | 0:cacfc9e25452 | 43 | } |
phungductung | 0:cacfc9e25452 | 44 | |
phungductung | 0:cacfc9e25452 | 45 | DesignerDrawer::~DesignerDrawer() |
phungductung | 0:cacfc9e25452 | 46 | { |
phungductung | 0:cacfc9e25452 | 47 | delete tp_; |
phungductung | 0:cacfc9e25452 | 48 | delete lblFrq_; |
phungductung | 0:cacfc9e25452 | 49 | delete coefs_; |
phungductung | 0:cacfc9e25452 | 50 | delete designObj_; |
phungductung | 0:cacfc9e25452 | 51 | delete drawerObj_; |
phungductung | 0:cacfc9e25452 | 52 | } |
phungductung | 0:cacfc9e25452 | 53 | |
phungductung | 0:cacfc9e25452 | 54 | // フィルタの再設計と周波数特性の再描画 |
phungductung | 0:cacfc9e25452 | 55 | bool DesignerDrawer::ReDesignAndDraw(Biquad::Coefs *ck, float &g0, |
phungductung | 0:cacfc9e25452 | 56 | BilinearDesign::Type lpHp) |
phungductung | 0:cacfc9e25452 | 57 | { |
phungductung | 0:cacfc9e25452 | 58 | bool changed = (lpHp != lp_) ? true : false; |
phungductung | 0:cacfc9e25452 | 59 | bool tch = tp_->IsTouched(cursorX_, cursorX_); |
phungductung | 0:cacfc9e25452 | 60 | if (tch || changed) |
phungductung | 0:cacfc9e25452 | 61 | { |
phungductung | 0:cacfc9e25452 | 62 | int newFc = Frq10(drawerObj_->PosToFrq(cursorX_)); |
phungductung | 0:cacfc9e25452 | 63 | newFc = (newFc > HIGHER_F_) ? HIGHER_F_ : newFc; |
phungductung | 0:cacfc9e25452 | 64 | if ((abs(newFc - fC_) >= 10) || changed) |
phungductung | 0:cacfc9e25452 | 65 | { |
phungductung | 0:cacfc9e25452 | 66 | fC_ = newFc; |
phungductung | 0:cacfc9e25452 | 67 | lblFrq_->Draw("Tan So Cat = %4d Hz", newFc); |
phungductung | 0:cacfc9e25452 | 68 | designObj_->Execute(newFc, lpHp, coefs_, g0_); |
phungductung | 0:cacfc9e25452 | 69 | GetCoefficients(ck, g0); |
phungductung | 0:cacfc9e25452 | 70 | |
phungductung | 0:cacfc9e25452 | 71 | frqResp_->SetParams(ORDER_, g0_, ck_); |
phungductung | 0:cacfc9e25452 | 72 | drawerObj_->Erase(); |
phungductung | 0:cacfc9e25452 | 73 | drawerObj_->DrawAxis(); // 目盛線の描画 |
phungductung | 0:cacfc9e25452 | 74 | drawerObj_->DrawGraph(frqResp_); // 周波数特性のグラフのカーブを描画する |
phungductung | 0:cacfc9e25452 | 75 | |
phungductung | 0:cacfc9e25452 | 76 | if (tch) // カーソルの移動 |
phungductung | 0:cacfc9e25452 | 77 | { |
phungductung | 0:cacfc9e25452 | 78 | lcd_->SetTextColor(CURSOR_TOUCHED_COLOR_); |
phungductung | 0:cacfc9e25452 | 79 | lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_); |
phungductung | 0:cacfc9e25452 | 80 | } |
phungductung | 0:cacfc9e25452 | 81 | cursorRedraw_ = true; |
phungductung | 0:cacfc9e25452 | 82 | oldCursorX_ = cursorX_; |
phungductung | 0:cacfc9e25452 | 83 | lp_ = lpHp; |
phungductung | 0:cacfc9e25452 | 84 | return true; |
phungductung | 0:cacfc9e25452 | 85 | } |
phungductung | 0:cacfc9e25452 | 86 | } |
phungductung | 0:cacfc9e25452 | 87 | |
phungductung | 0:cacfc9e25452 | 88 | if (!tch && cursorRedraw_) // カーソルを元の色に戻す |
phungductung | 0:cacfc9e25452 | 89 | { |
phungductung | 0:cacfc9e25452 | 90 | lcd_->SetTextColor(CURSOR_COLOR_); |
phungductung | 0:cacfc9e25452 | 91 | lcd_->DrawVLine(oldCursorX_, CURSOR_Y0_, CURSOR_LENGTH_); |
phungductung | 0:cacfc9e25452 | 92 | cursorRedraw_ = false; |
phungductung | 0:cacfc9e25452 | 93 | } |
phungductung | 0:cacfc9e25452 | 94 | return false; |
phungductung | 0:cacfc9e25452 | 95 | } |
phungductung | 0:cacfc9e25452 | 96 | |
phungductung | 0:cacfc9e25452 | 97 | // 周波数特性の描画 |
phungductung | 0:cacfc9e25452 | 98 | void DesignerDrawer::DrawResponse() |
phungductung | 0:cacfc9e25452 | 99 | { |
phungductung | 0:cacfc9e25452 | 100 | lblFrq_->Draw("Tan So Cat = %4d Hz", fC_); |
phungductung | 0:cacfc9e25452 | 101 | drawerObj_->DrawAxis(); // 目盛線の描画 |
phungductung | 0:cacfc9e25452 | 102 | FrqRespDrawer::AxisX_Char numX[] = // 横軸の目盛値を描画する際に使う構造体の配列 |
phungductung | 0:cacfc9e25452 | 103 | {{ 100, "0.1"}, { 200, "0.2"}, { 500, "0.5"}, { 1000, "1"}, |
phungductung | 0:cacfc9e25452 | 104 | { 2000, "2"}, { 5000, "5"}, {10000, "10"}, {20000, "20"}}; |
phungductung | 0:cacfc9e25452 | 105 | drawerObj_->DrawNumericX(numX, 8, 6, "Tan So [kHz]"); // 横軸の目盛 |
phungductung | 0:cacfc9e25452 | 106 | drawerObj_->DrawNumericY(-24, -6, 20, "%3d"); // 縦軸の目盛は 20 dB 間隔 |
phungductung | 0:cacfc9e25452 | 107 | drawerObj_->DrawGraph(frqResp_); // 周波数特性のカーブの描画 |
phungductung | 0:cacfc9e25452 | 108 | |
phungductung | 0:cacfc9e25452 | 109 | cursorX_ = drawerObj_->X(fC_); |
phungductung | 0:cacfc9e25452 | 110 | lcd_->SetTextColor(CURSOR_COLOR_); |
phungductung | 0:cacfc9e25452 | 111 | lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_); |
phungductung | 0:cacfc9e25452 | 112 | } |
phungductung | 0:cacfc9e25452 | 113 | |
phungductung | 0:cacfc9e25452 | 114 | // フィルタ係数の取得 |
phungductung | 0:cacfc9e25452 | 115 | void DesignerDrawer::GetCoefficients(Biquad::Coefs *c, float &g0) |
phungductung | 0:cacfc9e25452 | 116 | { |
phungductung | 0:cacfc9e25452 | 117 | for (int k=0; k<ORDER_/2; k++) c[k] = ck_[k]; |
phungductung | 0:cacfc9e25452 | 118 | g0 = g0_; |
phungductung | 0:cacfc9e25452 | 119 | } |
phungductung | 0:cacfc9e25452 | 120 | |
phungductung | 0:cacfc9e25452 | 121 | // 周波数を 10, 20, 50, 100 Hz の倍数にする |
phungductung | 0:cacfc9e25452 | 122 | int DesignerDrawer::Frq10(float f) |
phungductung | 0:cacfc9e25452 | 123 | { |
phungductung | 0:cacfc9e25452 | 124 | if (f < 1000) |
phungductung | 0:cacfc9e25452 | 125 | return ((int)(f/10.0f + 0.5f))*10; |
phungductung | 0:cacfc9e25452 | 126 | if (f < 2000) |
phungductung | 0:cacfc9e25452 | 127 | return ((int)(f/20.0f + 0.5f))*20; |
phungductung | 0:cacfc9e25452 | 128 | if (f < 3000) |
phungductung | 0:cacfc9e25452 | 129 | return ((int)(f/50.0f + 0.5f))*50; |
phungductung | 0:cacfc9e25452 | 130 | else |
phungductung | 0:cacfc9e25452 | 131 | return ((int)(f/100.0f + 0.5f))*100; |
phungductung | 0:cacfc9e25452 | 132 | } |
phungductung | 0:cacfc9e25452 | 133 | } |
phungductung | 0:cacfc9e25452 | 134 |