Output the audio signal with filtering by IIR filter in the Quad-SPI flash memory using onboard CODEC. QSPI フラッシュメモリのオーディオデータを遮断周波数可変の IIR フィルタを通してボードに搭載されているCODEC で出力するプログラム.
Dependencies: BSP_DISCO_F746NG_patch_fixed F746_GUI LCD_DISCO_F746NG QSPI_DISCO_F746NG TS_DISCO_F746NG mbed
MyClasses_Functions/DesignerDrawer.cpp@0:2eb96a7cf9b9, 2016-04-01 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Fri Apr 01 05:03:20 2016 +0000
- Revision:
- 0:2eb96a7cf9b9
1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:2eb96a7cf9b9 | 1 | //------------------------------------------------------------------------------ |
MikamiUitOpen | 0:2eb96a7cf9b9 | 2 | // IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス |
MikamiUitOpen | 0:2eb96a7cf9b9 | 3 | // |
MikamiUitOpen | 0:2eb96a7cf9b9 | 4 | // 2016/03/31, Copyright (c) 2016 MIKAMI, Naoki |
MikamiUitOpen | 0:2eb96a7cf9b9 | 5 | //------------------------------------------------------------------------------ |
MikamiUitOpen | 0:2eb96a7cf9b9 | 6 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 7 | #include "DesignerDrawer.hpp" |
MikamiUitOpen | 0:2eb96a7cf9b9 | 8 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 9 | namespace Mikami |
MikamiUitOpen | 0:2eb96a7cf9b9 | 10 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 11 | // Constructor |
MikamiUitOpen | 0:2eb96a7cf9b9 | 12 | DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0, |
MikamiUitOpen | 0:2eb96a7cf9b9 | 13 | uint16_t db10, uint16_t fs, int order, |
MikamiUitOpen | 0:2eb96a7cf9b9 | 14 | float fc, uint16_t fL, uint16_t fH, |
MikamiUitOpen | 0:2eb96a7cf9b9 | 15 | BilinearDesign::Type lpHp) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 16 | : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()), ORDER_(order), |
MikamiUitOpen | 0:2eb96a7cf9b9 | 17 | CURSOR_Y0_(y0-db10*6), CURSOR_LENGTH_(db10*6), |
MikamiUitOpen | 0:2eb96a7cf9b9 | 18 | LOWER_F_(fL), HIGHER_F_(fH), |
MikamiUitOpen | 0:2eb96a7cf9b9 | 19 | CURSOR_COLOR_(0xFF00D0D0), CURSOR_TOUCHED_COLOR_(0xFF00FFFF) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 20 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 21 | drawerObj_ = new BiquadFrqRespDrawer( |
MikamiUitOpen | 0:2eb96a7cf9b9 | 22 | FrqRespDrawer::Params(x0, 100.0f, 8000.0f, 150, |
MikamiUitOpen | 0:2eb96a7cf9b9 | 23 | y0, -60, 0, db10, fs)); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 24 | const int16_t OFS = 6; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 25 | drawerObj_->DrawCharX(100, OFS, "0.1"); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 26 | drawerObj_->DrawCharX(300, OFS, "0.3"); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 27 | drawerObj_->DrawCharX(1000, OFS, "1.0"); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 28 | drawerObj_->DrawCharX(3000, OFS, "3.0"); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 29 | drawerObj_->DrawCharX(8000, OFS, "8.0"); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 30 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 31 | Label l_frq(drawerObj_->X(900), y0+20, "Frequency [kHz]", |
MikamiUitOpen | 0:2eb96a7cf9b9 | 32 | Label::CENTER); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 33 | drawerObj_->DrawNumericY(-24, -6, 4, 20, "%3d"); // 縦軸の目盛は 20 dB 間隔 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 34 | Label l_dB(x0-24, y0-db10*6-20, "[dB]"); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 35 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 36 | // 双一次 z 変換による IIR フィルタの設計 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 37 | designObj_ = new BilinearDesign(order, fs); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 38 | coefs_ = new BilinearDesign::Coefs[ORDER_/2]; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 39 | ck_ = (Biquad::Coefs *)coefs_; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 40 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 41 | fC_ = fc; // 最初に与える遮断周波数 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 42 | designObj_->Execute(fC_, lpHp, coefs_, g0_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 43 | drawerObj_->SetParams(ORDER_, g0_, ck_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 44 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 45 | // 周波数特性の描画 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 46 | drawerObj_->DrawAxis(); // 目盛線の描画 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 47 | drawerObj_->DrawGraph(); // 周波数特性のカーブの描画 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 48 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 49 | cursorX_ = drawerObj_->X(fC_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 50 | lcd_->SetTextColor(CURSOR_COLOR_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 51 | lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 52 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 53 | tp_ = new TouchPanelDetectorX( |
MikamiUitOpen | 0:2eb96a7cf9b9 | 54 | drawerObj_->X(LOWER_F_), drawerObj_->X(HIGHER_F_), |
MikamiUitOpen | 0:2eb96a7cf9b9 | 55 | CURSOR_Y0_, y0); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 56 | lblFrq_ = new NumericLabel<int>(110, 30, "Cutoff frequency = %4d Hz", |
MikamiUitOpen | 0:2eb96a7cf9b9 | 57 | (int)fC_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 58 | lp_ = lpHp; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 59 | cursorRedraw_ = false; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 60 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 61 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 62 | // フィルタの再設計と周波数特性の再描画 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 63 | bool DesignerDrawer::ReDesignAndDraw(Biquad::Coefs *ck, float &g0, |
MikamiUitOpen | 0:2eb96a7cf9b9 | 64 | BilinearDesign::Type lpHp) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 65 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 66 | bool changed = (lpHp != lp_) ? true : false; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 67 | bool tch = tp_->IsTouched(cursorX_, cursorX_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 68 | if (tch || changed) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 69 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 70 | int newFc = Frq10(drawerObj_->PosToFrq(cursorX_)); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 71 | newFc = (newFc > HIGHER_F_) ? HIGHER_F_ : newFc; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 72 | if ((abs(newFc - fC_) >= 10) || changed) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 73 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 74 | fC_ = newFc; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 75 | lblFrq_->Draw("Cutoff frequency = %4d Hz", newFc); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 76 | designObj_->Execute(newFc, lpHp, coefs_, g0_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 77 | GetCoefficients(ck, g0); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 78 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 79 | drawerObj_->SetParams(ORDER_, g0_, ck_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 80 | drawerObj_->Erase(); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 81 | drawerObj_->DrawAxis(); // 目盛線の描画 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 82 | drawerObj_->DrawGraph(); // 周波数特性のグラフのカーブを描画する |
MikamiUitOpen | 0:2eb96a7cf9b9 | 83 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 84 | if (tch) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 85 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 86 | lcd_->SetTextColor(CURSOR_TOUCHED_COLOR_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 87 | lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 88 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 89 | cursorRedraw_ = true; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 90 | oldCursorX_ = cursorX_; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 91 | lp_ = lpHp; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 92 | return true; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 93 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 94 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 95 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 96 | if (!tch && cursorRedraw_) // カーソルを元の色に戻す |
MikamiUitOpen | 0:2eb96a7cf9b9 | 97 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 98 | lcd_->SetTextColor(CURSOR_COLOR_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 99 | lcd_->DrawVLine(oldCursorX_, CURSOR_Y0_, CURSOR_LENGTH_); |
MikamiUitOpen | 0:2eb96a7cf9b9 | 100 | cursorRedraw_ = false; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 101 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 102 | return false; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 103 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 104 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 105 | // フィルタ係数の取得 |
MikamiUitOpen | 0:2eb96a7cf9b9 | 106 | void DesignerDrawer::GetCoefficients(Biquad::Coefs *c, float &g0) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 107 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 108 | for (int k=0; k<ORDER_/2; k++) c[k] = ck_[k]; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 109 | g0 = g0_; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 110 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 111 | |
MikamiUitOpen | 0:2eb96a7cf9b9 | 112 | // 周波数を 10, 20, 50, 100 Hz の倍数にする |
MikamiUitOpen | 0:2eb96a7cf9b9 | 113 | int DesignerDrawer::Frq10(float f) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 114 | { |
MikamiUitOpen | 0:2eb96a7cf9b9 | 115 | if (f < 1000) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 116 | return ((int)(f/10.0f + 0.5f))*10; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 117 | if (f < 2000) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 118 | return ((int)(f/20.0f + 0.5f))*20; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 119 | if (f < 3000) |
MikamiUitOpen | 0:2eb96a7cf9b9 | 120 | return ((int)(f/50.0f + 0.5f))*50; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 121 | else |
MikamiUitOpen | 0:2eb96a7cf9b9 | 122 | return ((int)(f/100.0f + 0.5f))*100; |
MikamiUitOpen | 0:2eb96a7cf9b9 | 123 | } |
MikamiUitOpen | 0:2eb96a7cf9b9 | 124 | } |