Output the audio signal with filtering by IIR filter in the *.wav file on the SD card using onboard CODEC. SD カードの *.wav ファイルのオーディオ信号を遮断周波数可変の IIR フィルタを通して,ボードに搭載されているCODEC で出力する.

Dependencies:   BSP_DISCO_F746NG F746_GUI LCD_DISCO_F746NG SDFileSystem_Warning_Fixed TS_DISCO_F746NG mbed FrequencyResponseDrawer F746_SAI_IO Array_Matrix

Revision:
0:04b43b777fae
Child:
2:2478e7a8e8d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/DesignerDrawer.cpp	Tue Apr 19 09:46:11 2016 +0000
@@ -0,0 +1,133 @@
+//------------------------------------------------------------------------------
+//  IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス
+//  
+//  2016/04/19, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#include "DesignerDrawer.hpp"
+
+namespace Mikami
+{
+    // Constructor
+    DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0,
+                                   uint16_t db10, int fs, int order,
+                                   float fc, uint16_t fL, uint16_t fH,
+                                   BilinearDesign::Type lpHp)
+        : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()),
+          X0_(x0), Y0_(y0), DB10_(db10), ORDER_(order),
+          CURSOR_Y0_(y0+1-db10*6), CURSOR_LENGTH_(db10*6-1),
+          LOWER_F_(fL), HIGHER_F_(fH),
+          CURSOR_COLOR_(0xFFE000D0), CURSOR_TOUCHED_COLOR_(0xFFFF80FF)
+    {
+        drawerObj_ = new FrqRespDrawer(x0, 100.0f, 20000.0f, 140,
+                                       y0, -60, 0, db10, fs);
+
+        // 双一次 z 変換による IIR フィルタの設計
+        designObj_ = new BilinearDesign(order, fs);
+        coefs_ = new BilinearDesign::Coefs[order/2];
+        ck_ = (Biquad::Coefs *)coefs_;
+       
+        fC_ = fc;               // 最初に与える遮断周波数
+        designObj_->Execute(fC_, lpHp, coefs_, g0_);
+        frqResp_.SetParams(ORDER_, g0_, ck_);
+
+        // 周波数特性の描画
+        lblFrq_ = new NumericLabel<int>(110, 30);
+        DrawResponse();
+        tp_ = new TouchPanelDetectorX(
+                drawerObj_->X(LOWER_F_), drawerObj_->X(HIGHER_F_),
+                CURSOR_Y0_, y0);
+        lp_ = lpHp;
+        cursorRedraw_ = false;
+    }
+
+    DesignerDrawer::~DesignerDrawer()
+    {
+        delete tp_;
+        delete lblFrq_;
+        delete coefs_;
+        delete designObj_;
+        delete drawerObj_;
+    }
+
+    // フィルタの再設計と周波数特性の再描画
+    bool DesignerDrawer::ReDesignAndDraw(Biquad::Coefs *ck, float &g0,
+                                         BilinearDesign::Type lpHp)
+    {
+        bool changed = (lpHp != lp_) ? true : false;
+        bool tch = tp_->IsTouched(cursorX_, cursorX_);
+        if (tch || changed)
+        {
+            int newFc = Frq10(drawerObj_->PosToFrq(cursorX_));
+            newFc = (newFc > HIGHER_F_) ? HIGHER_F_ : newFc;
+            if ((abs(newFc - fC_) >= 10) || changed)
+            {
+                fC_ = newFc;
+                lblFrq_->Draw("Cutoff frequency = %4d Hz", newFc);
+                designObj_->Execute(newFc, lpHp, coefs_, g0_);
+                GetCoefficients(ck, g0);
+
+                frqResp_.SetParams(ORDER_, g0_, ck_);
+                drawerObj_->Erase();
+                drawerObj_->DrawAxis();             // 目盛線の描画
+                drawerObj_->DrawGraph(frqResp_);    // 周波数特性のグラフのカーブを描画する
+
+                if (tch)    // カーソルの移動
+                {
+                    lcd_->SetTextColor(CURSOR_TOUCHED_COLOR_);
+                    lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_);
+                }
+                cursorRedraw_ = true;
+                oldCursorX_ = cursorX_;
+                lp_ = lpHp;
+                return true;
+            }
+        }
+        
+        if (!tch && cursorRedraw_)   // カーソルを元の色に戻す
+        {
+            lcd_->SetTextColor(CURSOR_COLOR_);
+            lcd_->DrawVLine(oldCursorX_, CURSOR_Y0_, CURSOR_LENGTH_);
+            cursorRedraw_ = false;
+        }
+        return false;
+    }
+
+    // 周波数特性の描画
+    void DesignerDrawer::DrawResponse()
+    {
+        lblFrq_->Draw("Cutoff frequency = %4d Hz", fC_);
+        drawerObj_->DrawAxis();             // 目盛線の描画
+        FrqRespDrawer::AxisX_Char numX[] =  // 横軸の目盛値を描画する際に使う構造体の配列
+            {{  100, "0.1"}, {  200, "0.2"}, {  500, "0.5"}, { 1000,  "1"},
+             { 2000,   "2"}, { 5000,   "5"}, {10000,  "10"}, {20000, "20"}};
+        drawerObj_->DrawNumericX(numX, 8, 6, "Frequency [kHz]"); // 横軸の目盛
+        drawerObj_->DrawNumericY(-24, -6, 4, 20, "%3d");         // 縦軸の目盛は 20 dB 間隔
+        drawerObj_->DrawGraph(frqResp_);    // 周波数特性のカーブの描画
+
+        cursorX_ = drawerObj_->X(fC_);
+        lcd_->SetTextColor(CURSOR_COLOR_);
+        lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_);
+    }
+
+    // フィルタ係数の取得
+    void DesignerDrawer::GetCoefficients(Biquad::Coefs *c, float &g0)
+    {
+        for (int k=0; k<ORDER_/2; k++) c[k] = ck_[k];
+        g0 = g0_;
+    }
+    
+    // 周波数を 10, 20, 50, 100 Hz の倍数にする
+    int DesignerDrawer::Frq10(float f)
+    {
+        if (f < 1000)
+            return ((int)(f/10.0f + 0.5f))*10;
+        if (f < 2000)
+            return ((int)(f/20.0f + 0.5f))*20;
+        if (f < 3000)
+            return ((int)(f/50.0f + 0.5f))*50;           
+        else
+            return ((int)(f/100.0f + 0.5f))*100;
+    }
+}
+