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

Committer:
MikamiUitOpen
Date:
2016-04-07
Revision:
1:a1be09c2533a
Parent:
0:2eb96a7cf9b9

File content as of revision 1:a1be09c2533a:

//------------------------------------------------------------------------------
//  IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス
//  
//  2016/03/31, Copyright (c) 2016 MIKAMI, Naoki
//------------------------------------------------------------------------------

#include "DesignerDrawer.hpp"

namespace Mikami
{
    // Constructor
    DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0,
                                   uint16_t db10, uint16_t fs, int order,
                                   float fc, uint16_t fL, uint16_t fH,
                                   BilinearDesign::Type lpHp)
        : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()), ORDER_(order),
          CURSOR_Y0_(y0-db10*6), CURSOR_LENGTH_(db10*6),
          LOWER_F_(fL), HIGHER_F_(fH),
          CURSOR_COLOR_(0xFF00D0D0), CURSOR_TOUCHED_COLOR_(0xFF00FFFF)
    {
        drawerObj_ = new BiquadFrqRespDrawer(
                        FrqRespDrawer::Params(x0, 100.0f, 8000.0f, 150,
                                              y0, -60, 0, db10, fs));
        const int16_t OFS = 6;
        drawerObj_->DrawCharX(100,  OFS, "0.1");
        drawerObj_->DrawCharX(300,  OFS, "0.3");
        drawerObj_->DrawCharX(1000, OFS, "1.0");
        drawerObj_->DrawCharX(3000, OFS, "3.0");
        drawerObj_->DrawCharX(8000, OFS, "8.0");

        Label l_frq(drawerObj_->X(900), y0+20, "Frequency [kHz]",
                    Label::CENTER);
        drawerObj_->DrawNumericY(-24, -6, 4, 20, "%3d");  // 縦軸の目盛は 20 dB 間隔
        Label l_dB(x0-24, y0-db10*6-20, "[dB]");

        // 双一次 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_);
        drawerObj_->SetParams(ORDER_, g0_, ck_);

        // 周波数特性の描画
        drawerObj_->DrawAxis();     // 目盛線の描画
        drawerObj_->DrawGraph();    // 周波数特性のカーブの描画

        cursorX_ = drawerObj_->X(fC_);
        lcd_->SetTextColor(CURSOR_COLOR_);
        lcd_->DrawVLine(cursorX_, CURSOR_Y0_, CURSOR_LENGTH_);

        tp_ = new TouchPanelDetectorX(
                drawerObj_->X(LOWER_F_), drawerObj_->X(HIGHER_F_),
                CURSOR_Y0_, y0);
        lblFrq_ = new NumericLabel<int>(110, 30, "Cutoff frequency = %4d Hz",
                                        (int)fC_);
        lp_ = lpHp;
        cursorRedraw_ = false;
    }

    // フィルタの再設計と周波数特性の再描画
    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);

                drawerObj_->SetParams(ORDER_, g0_, ck_);
                drawerObj_->Erase();
                drawerObj_->DrawAxis();   // 目盛線の描画
                drawerObj_->DrawGraph();  // 周波数特性のグラフのカーブを描画する

                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::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;
    }
}