SD card player with variable cotoff frequency lowpass and highpass IIR filter. SD カードの *.wav ファイルのオーディオ信号を,遮断周波数可変 IIR 低域通過および高域通過フィルタを通して,ボードに搭載されているCODEC で出力する.このプログラムについては,CQ出版社インターフェース誌 2018年8月号で解説している.

Dependencies:   F746_GUI F746_SAI_IO FrequencyResponseDrawer SD_PlayerSkeleton

Committer:
MikamiUitOpen
Date:
Mon Apr 10 01:44:22 2017 +0000
Revision:
11:399670d24ed9
Parent:
10:3532c05aa1a9
12

Who changed what in which revision?

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