?

Files at this revision

API Documentation at this revision

Comitter:
phungductung
Date:
Tue Jun 04 21:58:08 2019 +0000
Commit message:
?;

Changed in this revision

BilinearDesignLH.cpp Show annotated file Show diff for this revision Revisions of this file
BilinearDesignLH.hpp Show annotated file Show diff for this revision Revisions of this file
Biquad.hpp Show annotated file Show diff for this revision Revisions of this file
DesignerDrawer.cpp Show annotated file Show diff for this revision Revisions of this file
DesignerDrawer.hpp Show annotated file Show diff for this revision Revisions of this file
FileSelectorWav.cpp Show annotated file Show diff for this revision Revisions of this file
FileSelectorWav.hpp Show annotated file Show diff for this revision Revisions of this file
IIR_CascadeFrqResp.hpp Show annotated file Show diff for this revision Revisions of this file
MyFunctions.cpp Show annotated file Show diff for this revision Revisions of this file
MyFunctions.hpp Show annotated file Show diff for this revision Revisions of this file
SD_WavReader.cpp Show annotated file Show diff for this revision Revisions of this file
SD_WavReader.hpp Show annotated file Show diff for this revision Revisions of this file
TouchPanelDetectorX.hpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BilinearDesignLH.cpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,76 @@
+//------------------------------------------------------------------------------
+//  Design of Butterworth LPF and HPF using bilinear transform
+//
+//   2016/03/31, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#include "BilinearDesignLH.hpp"
+
+namespace Mikami
+{
+    // Execute design
+    //      input
+    //          fc: Cutoff frequency
+    //          pb: Passband (LPF or HPF)
+    //      output
+    //          c : Coefficients for cascade structure
+    //          g : Gain factor for cascade structure
+    void BilinearDesign::Execute(float fc, Type pb, Coefs c[], float& g)
+    {
+        Butterworth();
+        Bilinear(fc);
+        ToCascade(pb);
+        GetGain(pb);
+        GetCoefs(c, g);
+    }
+
+    // Get poles for Butterworth characteristics
+    void BilinearDesign::Butterworth()
+    {
+        float pi_2order = PI_/(2.0f*ORDER_);
+        for (int j=0; j<ORDER_/2; j++)  // Pole with imaginary part >= 0
+        {
+            float theta = (2.0f*j + 1.0f)*pi_2order;
+            sP_[j] = Complex(-cosf(theta), sinf(theta));
+        }
+    }
+
+    // Bilinear transform
+    //      fc: Cutoff frequency
+    void BilinearDesign::Bilinear(float fc)
+    {
+        float wc = tanf(fc*PI_FS_);
+        for (int k=0; k<ORDER_/2; k++)
+            zP_[k] = (1.0f + wc*sP_[k])/(1.0f - wc*sP_[k]);
+    }
+
+    // Convert to coefficients for cascade structure
+    void BilinearDesign::ToCascade(Type pb)
+    {
+        for (int j=0; j<ORDER_/2; j++)
+        {
+            ck_[j].a1 = 2.0f*real(zP_[j]);          // a1m
+            ck_[j].a2 = -norm(zP_[j]);              // a2m
+            ck_[j].b1 = (pb == LPF) ? 2.0f : -2.0f; // b1m
+            ck_[j].b2 = 1.0f;                       // b2m
+        }
+    }
+
+    // Calculate gain factor
+    void BilinearDesign::GetGain(Type pb)
+    {
+        float u = (pb == LPF) ? 1.0f : -1.0f;
+        float g0 = 1.0f;
+        for (int k=0; k<ORDER_/2; k++)
+            g0 = g0*(1.0f - (ck_[k].a1 + ck_[k].a2*u)*u)/
+                    (1.0f + (ck_[k].b1 + ck_[k].b2*u)*u);
+        gain_ = g0;
+    }
+
+    // Get coefficients
+    void BilinearDesign::GetCoefs(Coefs c[], float& gain)
+    {
+        for (int k=0; k<ORDER_/2; k++) c[k] = ck_[k];
+        gain = gain_;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BilinearDesignLH.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,60 @@
+//------------------------------------------------------------------------------
+//  Design of Butterworth LPF and HPF using bilinear transform -- Header
+//
+//   2016/03/31, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#ifndef BILINEAR_BUTTERWORTH_HPP
+#define BILINEAR_BUTTERWORTH_HPP
+
+#include "mbed.h"
+#include <complex>  // requisite
+
+namespace Mikami
+{
+    typedef complex<float> Complex; // define "Complex"
+
+    class BilinearDesign
+    {
+    public:
+        struct Coefs { float a1, a2, b1, b2; };
+        enum Type { LPF, HPF };
+
+        // Constructor
+        BilinearDesign(int order, float fs)
+            : PI_FS_(PI_/fs), ORDER_(order)
+        {
+            sP_ = new Complex[order/2];
+            zP_ = new Complex[order/2];
+            ck_ = new Coefs[order/2];
+        }
+
+        // Destractor
+        ~BilinearDesign()
+        {
+            delete[] sP_;
+            delete[] zP_;
+            delete[] ck_;
+        }
+
+        // Execution of design
+        void Execute(float fc, Type pb, Coefs c[], float& g);
+
+    private:
+        static const float PI_ = 3.1415926536f;
+        const float PI_FS_;
+        const int ORDER_;
+
+        Complex* sP_;   // Poles on s-plane
+        Complex* zP_;   // Poles on z-plane
+        Coefs* ck_;     // Coefficients of transfer function for cascade form
+        float gain_;    // Gain factor for cascade form
+
+        void Butterworth();
+        void Bilinear(float fc);
+        void ToCascade(Type pb);
+        void GetGain(Type pb);
+        void GetCoefs(Coefs c[], float& gain);
+    };
+}
+#endif  // BILINEAR_BUTTERWORTH_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Biquad.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,65 @@
+//--------------------------------------------------------------
+//  縦続形 IIR フィルタで使う 1D タイプの 2 次のフィルタ
+//  Biquad filter of 1D type for IIR filter of cascade structure
+//      このクラスでは,係数は実行中に書き換えられることを想定している
+//
+//      u[n] = x[n] + a1*u[n-1] + a2*u[n-2]
+//      y[n] = u[n] + b1*u[n-1] + b2*u[n-2]
+//          x[n] :  input signal
+//          y[n] :  output signal
+//          b0 = 1
+//
+// 2016/03/25, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef IIR_BIQUAD_HPP
+#define IIR_BIQUAD_HPP
+
+#include "mbed.h"
+
+// 2nd order IIR filter
+namespace Mikami
+{
+    class Biquad
+    {
+    public:
+        struct Coefs { float a1, a2, b1, b2; };
+
+        Biquad() {}     // Default constructore
+
+        Biquad(const Coefs ck)
+        {
+            SetCoefficients(ck);
+            Clear();
+        }
+        
+        void SetCoefficients(const Coefs ck)
+        {
+            a1_ = ck.a1;
+            a2_ = ck.a2;
+            b1_ = ck.b1;
+            b2_ = ck.b2;
+        }
+
+        float Execute(float xn)
+        {
+            float un = xn + a1_*un1_ + a2_*un2_;
+            float yn = un + b1_*un1_ + b2_*un2_;
+        
+            un2_ = un1_;
+            un1_ = un;
+
+            return yn;
+        }
+
+        void Clear() { un1_ = un2_ = 0; }
+
+    private:
+        float a1_, a2_, b1_, b2_;
+        float un1_, un2_;
+
+        // disallow copy constructor
+        Biquad(const Biquad&);
+    };
+}
+#endif  // IIR_BIQUAD_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DesignerDrawer.cpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,134 @@
+//------------------------------------------------------------------------------
+//  IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス
+//  
+//  2016/05/01, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#include "DesignerDrawer.hpp"
+
+namespace Mikami
+{
+    // Constructor
+    DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0,
+                                   float db1, 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), ORDER_(order),
+          CURSOR_Y0_(y0+1-db1*60), CURSOR_LENGTH_(db1*60-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, db1, 10, 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_ = new IIR_CascadeFrqResp();
+        frqResp_->SetParams(ORDER_, g0_, ck_);
+
+        // 周波数特性の描画
+        lblFrq_ = new NumericLabel<int>(110, 38);
+        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("Tan So Cat = %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("Tan So Cat = %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, "Tan So [kHz]");    // 横軸の目盛
+        drawerObj_->DrawNumericY(-24, -6, 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;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DesignerDrawer.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,70 @@
+//------------------------------------------------------------------------------
+//  IIR フィルタを双一次 z 変換で設計し,その周波数特性を描画するためのクラス -- Header
+//  
+//  2016/05/01, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#ifndef F746_DISIGNER_AND_DRAWER_HPP
+#define F746_DISIGNER_AND_DRAWER_HPP
+
+#include "NumericLabel.hpp"
+#include "TouchPanelDetectorX.hpp"
+#include "FrquencyResponseDrawer.hpp"
+#include "BilinearDesignLH.hpp"
+#include "IIR_CascadeFrqResp.hpp"
+
+namespace Mikami
+{
+    class DesignerDrawer
+    {
+    public:
+        // Constructor
+        DesignerDrawer(uint16_t x0, uint16_t y0,
+                       float db1, int fs, int order,
+                       float fc, uint16_t fL, uint16_t fH,
+                       BilinearDesign::Type lpHp);
+
+        ~DesignerDrawer();
+
+        // フィルタの再設計と周波数特性の再描画
+        bool ReDesignAndDraw(Biquad::Coefs *ck, float &g0,
+                             BilinearDesign::Type lpHp);
+        
+        // 周波数特性の描画
+        void DrawResponse();
+
+        void GetCoefficients(Biquad::Coefs *ck, float &g0);
+        
+        uint16_t GetOrder() { return ORDER_; }
+
+    private:
+        LCD_DISCO_F746NG *lcd_;
+        TS_DISCO_F746NG *ts_;
+
+        const uint16_t X0_, Y0_;
+        const uint16_t ORDER_;
+        const uint16_t CURSOR_Y0_, CURSOR_LENGTH_;
+        const uint16_t LOWER_F_, HIGHER_F_;
+        const uint32_t CURSOR_COLOR_, CURSOR_TOUCHED_COLOR_;
+
+        IIR_CascadeFrqResp *frqResp_;   // IIR フィルタの周波数応答に対応するオブジェクト
+        BilinearDesign::Coefs *coefs_;  // 設計された係数
+        Biquad::Coefs *ck_;
+        float g0_;                      // 設計された係数(利得定数)
+        
+        int fC_;    // 遮断周波数
+
+        uint16_t cursorX_, oldCursorX_;
+        bool cursorRedraw_;
+        BilinearDesign::Type lp_;
+        
+        FrqRespDrawer *drawerObj_;
+        BilinearDesign *designObj_;
+        TouchPanelDetectorX *tp_;
+        NumericLabel<int> *lblFrq_; // 遮断周波数表示用
+        
+        // 周波数を 10, 20, 50, 100 Hz の倍数にする
+        int Frq10(float f);
+    };
+}
+#endif  // F746_DISIGNER_AND_DRAWER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSelectorWav.cpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,114 @@
+//--------------------------------------------------------------
+//  FileSelector class
+//      SD カード内のファイル名の一覧を表示し,ファイルを選択する
+//
+//  2016/06/30, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "FileSelectorWav.hpp"
+
+namespace Mikami
+{
+    bool FileSelector::CreateTable()
+    {
+        DIR* dp = opendir("/sd");
+        fileCount_ = 0; 
+        if (dp != NULL)
+        {
+            dirent* entry;
+            for (int n=0; n<256; n++)
+            {
+                entry = readdir(dp);
+                if (entry == NULL) break;
+
+                string strName = entry->d_name;
+                if ( (strName.find(".wav") != string::npos) ||
+                     (strName.find(".WAV") != string::npos) )
+                {
+                    sdReader_.Open(strName);        // ファイルオープン
+
+                    // PCM,16 ビットステレオ,標本化周波数 44.1 kHz 以外のファイルは除外
+                    if (sdReader_.IsWavFile())
+                        fileNames_[fileCount_++] = strName;
+                    sdReader_.Close();
+                }
+
+                if (fileCount_ >= MAX_FILES_) break;
+            }
+            closedir(dp); 
+        }
+        else
+            return false;
+
+        if (fileCount_ == 0) return false;
+
+        if (rect_ != NULL) delete rect_;
+        Array<string> nonString(fileCount_, "");
+        rect_ = new ButtonGroup(X_, Y_, W_H_, W_H_, fileCount_,
+                                nonString, 0, V_L_-W_H_, 1,
+                                -1, Font12, 0, GuiBase::ENUM_BACK,
+                                BASE_COLOR_, TOUCHED_COLOR_);
+        for (int n=0; n<fileCount_; n++) rect_->Erase(n);
+        CreateLabels();   
+        prevFileCount_ = fileCount_;
+        return true;
+    }
+
+    // ファイルを選択する
+    bool FileSelector::Select(string &fileName)
+    {
+        int n;
+        if (rect_->GetTouchedNumber(n))
+        {
+            fileNameLabels_[n]->Draw(GetFileNameNoExt(n), TOUCHED_COLOR_);
+            if ((prev_ >= 0) && (prev_ != n))
+                fileNameLabels_[prev_]->Draw(GetFileNameNoExt(prev_));
+            prev_ = n;
+            fileName = fileNames_[n];
+            return true;
+        }
+        else
+            return false;
+    }
+
+    // ファイルの一覧の表示
+    void FileSelector::DisplayFileList(bool sortEnable)
+    {
+        if (sortEnable)
+            std::sort((string *)fileNames_,
+                      (string *)fileNames_+fileCount_); 
+        
+        Erase(X_, Y_, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 272-Y_);
+        rect_->DrawAll();
+        for (int n=0; n<fileCount_; n++)
+            fileNameLabels_[n]->Draw(GetFileNameNoExt(n));
+    }
+
+    // ファイルの一覧の消去
+    void FileSelector::Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
+               uint32_t color)
+    {
+        lcd_->SetTextColor(color);
+        lcd_->FillRect(x, y, width, height);
+    }
+
+    // Label を生成
+    void FileSelector::CreateLabels()
+    {
+        fileNameLabels_.SetSize(fileCount_);
+                    
+        for (int n=0; n<fileCount_; n++)
+            fileNameLabels_[n] = new Label(X_+30, Y_+5+V_L_*n, "",
+                                           Label::LEFT, Font16,
+                                           BASE_COLOR_);
+    }
+
+    // 拡張子を削除した文字列を取得
+    string FileSelector::GetFileNameNoExt(int n)
+    {
+        string name = fileNames_[n];
+        name.erase(name.find("."));
+        return name.substr(0, MAX_NAME_LENGTH_);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FileSelectorWav.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,214 @@
+//--------------------------------------------------------------
+//  FileSelector class ---- Header ----
+//      SD カード内のファイル名の一覧を表示し,ファイルを選択する
+//
+//  2016/06/30, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef FILE_SELECTOR_HPP
+#define FILE_SELECTOR_HPP
+
+#include "Label.hpp"
+#include "ButtonGroup.hpp"
+#include "SD_WavReader.hpp"
+#include <algorithm>    // sort() で使用
+#include <string>
+
+namespace Mikami
+{
+    class FileSelector
+    {
+    public:
+        FileSelector(uint8_t x0, uint8_t y0, int maxFiles,
+                     int maxNameLength, SD_WavReader &reader)
+            : X_(x0), Y_(y0), W_H_(24), V_L_(36),
+              MAX_FILES_(maxFiles), MAX_NAME_LENGTH_(maxNameLength),
+              BASE_COLOR_(0xFF80FFA0), TOUCHED_COLOR_(0xFF80FFFF),
+              fileNames_(maxFiles),
+              rect_(NULL), lcd_(GuiBase::GetLcdPtr()),
+              sdReader_(reader), prevFileCount_(0), prev_(-1) {}
+
+        ~FileSelector()
+        {   delete rect_; }
+        
+        bool CreateTable();
+
+        // ファイルを選択する
+        bool Select(string &fileName);
+
+        // ファイルの一覧の表示
+        void DisplayFileList(bool sortEnable = true);
+
+        // ファイルの一覧の消去
+        void Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
+                   uint32_t color = GuiBase::ENUM_BACK);
+
+    private:
+        const uint8_t X_, Y_, W_H_, V_L_;
+        const int MAX_FILES_;
+        const int MAX_NAME_LENGTH_;
+        const uint32_t BASE_COLOR_;
+        const uint32_t TOUCHED_COLOR_;
+        
+        Array<string> fileNames_;
+        ButtonGroup *rect_;
+        Array<Label *> fileNameLabels_;
+        LCD_DISCO_F746NG *lcd_;
+        SD_WavReader &sdReader_;
+        int fileCount_, prevFileCount_;
+        int prev_;
+
+        // Label を生成
+        void CreateLabels();
+
+        // 拡張子を削除した文字列を取得
+        string GetFileNameNoExt(int n);
+
+        // disallow copy constructor and assignment operator
+        FileSelector(const FileSelector&);
+        FileSelector& operator=(const FileSelector&);
+    };
+}
+/*
+namespace Mikami
+{
+    class FileSelector
+    {
+    public:
+        FileSelector(uint8_t x0, uint8_t y0, int maxFiles,
+                     int maxNameLength, SD_WavReader &reader)
+            : X_(x0), Y_(y0), W_H_(24), V_L_(36),
+              MAX_FILES_(maxFiles), MAX_NAME_LENGTH_(maxNameLength),
+              BASE_COLOR_(0xFF80FFA0), TOUCHED_COLOR_(0xFF80FFFF),
+              fileNames_(maxFiles),
+              rect_(NULL), lcd_(GuiBase::GetLcdPtr()),
+              sdReader_(reader), prevFileCount_(0), prev_(-1) {}
+
+        ~FileSelector()
+        {   delete rect_; }
+        
+        bool CreateTable()
+        {
+            DIR* dp = opendir("/sd");
+            fileCount_ = 0; 
+            if (dp != NULL)
+            {
+                dirent* entry;
+                for (int n=0; n<256; n++)
+                {
+                    entry = readdir(dp);
+                    if (entry == NULL) break;
+
+                    string strName = entry->d_name;
+                    if ( (strName.find(".wav") != string::npos) ||
+                         (strName.find(".WAV") != string::npos) )
+                    {
+                        sdReader_.Open(strName);        // ファイルオープン
+
+                        // PCM,16 ビットステレオ,標本化周波数 44.1 kHz 以外のファイルは除外
+                        if (sdReader_.IsWavFile())
+                            fileNames_[fileCount_++] = strName;
+                        sdReader_.Close();
+                    }
+
+                    if (fileCount_ >= MAX_FILES_) break;
+                }
+                closedir(dp); 
+            }
+            else
+                return false;
+
+            if (fileCount_ == 0) return false;
+
+            if (rect_ != NULL) delete rect_;
+            Array<string> nonString(fileCount_, "");
+            rect_ = new ButtonGroup(X_, Y_, W_H_, W_H_, fileCount_,
+                                    nonString, 0, V_L_-W_H_, 1,
+                                    -1, Font12, 0, GuiBase::ENUM_BACK,
+                                    BASE_COLOR_, TOUCHED_COLOR_);
+            for (int n=0; n<fileCount_; n++) rect_->Erase(n);
+            CreateLabels();   
+            prevFileCount_ = fileCount_;
+            return true;
+        }
+
+        // ファイルを選択する
+        bool Select(string &fileName)
+        {
+            int n;
+            if (rect_->GetTouchedNumber(n))
+            {
+                fileNameLabels_[n]->Draw(GetFileNameNoExt(n), TOUCHED_COLOR_);
+                if ((prev_ >= 0) && (prev_ != n))
+                    fileNameLabels_[prev_]->Draw(GetFileNameNoExt(prev_));
+                prev_ = n;
+                fileName = fileNames_[n];
+                return true;
+            }
+            else
+                return false;
+        }
+
+        // ファイルの一覧の表示
+        void DisplayFileList(bool sortEnable = true)
+        {
+            if (sortEnable)
+                std::sort((string *)fileNames_,
+                          (string *)fileNames_+fileCount_); 
+            
+            Erase(X_, Y_, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 272-Y_);
+            rect_->DrawAll();
+            for (int n=0; n<fileCount_; n++)
+                fileNameLabels_[n]->Draw(GetFileNameNoExt(n));
+        }
+
+        // ファイルの一覧の消去
+        void Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
+                   uint32_t color = GuiBase::ENUM_BACK)
+        {
+            lcd_->SetTextColor(color);
+            lcd_->FillRect(x, y, width, height);
+        }
+
+    private:
+        const uint8_t X_, Y_, W_H_, V_L_;
+        const int MAX_FILES_;
+        const int MAX_NAME_LENGTH_;
+        const uint32_t BASE_COLOR_;
+        const uint32_t TOUCHED_COLOR_;
+        
+        Array<string> fileNames_;
+        ButtonGroup *rect_;
+        Array<Label *> fileNameLabels_;
+        LCD_DISCO_F746NG *lcd_;
+        SD_WavReader &sdReader_;
+        int fileCount_, prevFileCount_;
+        int prev_;
+
+        // Label を生成
+        void CreateLabels()
+        {
+            fileNameLabels_.SetSize(fileCount_);
+                        
+            for (int n=0; n<fileCount_; n++)
+                fileNameLabels_[n] = new Label(X_+30, Y_+5+V_L_*n, "",
+                                               Label::LEFT, Font16,
+                                               BASE_COLOR_);
+        }
+
+        // 拡張子を削除した文字列を取得
+        string GetFileNameNoExt(int n)
+        {
+            string name = fileNames_[n];
+            name.erase(name.find("."));
+            return name.substr(0, MAX_NAME_LENGTH_);
+        }
+
+        // disallow copy constructor and assignment operator
+        FileSelector(const FileSelector&);
+        FileSelector& operator=(const FileSelector&);
+    };
+}
+*/
+#endif  // FILE_SELECTOR_HPP
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IIR_CascadeFrqResp.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,48 @@
+//-----------------------------------------------------------
+//  Frequency response for IIR filter of cascade form
+//
+//  2016/04/16, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef IIR_CASCADE_FREQUENCY_RESPONSE_HPP
+#define IIR_CASCADE_FREQUENCY_RESPONSE_HPP
+
+#include "FrequancyResponseBase.hpp"
+#include "Biquad.hpp"
+
+namespace Mikami
+{
+    class IIR_CascadeFrqResp : public FrequencyResponse
+    {
+    public:
+        IIR_CascadeFrqResp() {}
+
+        // 次数とフィルタの係数設定
+        void SetParams(int order, float g0, Biquad::Coefs ck[])
+        {
+            order_ = order;
+            g0_ = g0;
+            ck_ = ck;
+        }
+
+        // 周波数応答の絶対値を返す関数, 引数: z^(-1)
+        virtual float AbsH_z(Complex u)
+        {
+            Complex h = g0_;
+            for (int k=0; k<order_/2; k++)
+            h = h*(1.0f + (ck_[k].b1 + ck_[k].b2*u)*u)
+                /((1.0f - (ck_[k].a1 + ck_[k].a2*u)*u));
+            return abs(h);       
+        }
+        
+    private:
+        int order_;
+        float g0_;
+        Biquad::Coefs *ck_;
+
+        // disallow copy constructor and assignment operator
+        IIR_CascadeFrqResp(const IIR_CascadeFrqResp&);
+        IIR_CascadeFrqResp& operator=(const IIR_CascadeFrqResp&);
+    };
+}
+#endif  // IIR_CASCADE_FREQUENCY_RESPONSE_HPP
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFunctions.cpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,84 @@
+//--------------------------------------------------------------
+//  フィルタ処理付き SD オーディオプレーヤーで使う大域関数(ヘッダ)
+//
+//  2016/07/04, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "MyFunctions.hpp"
+
+// 1フレーム分の信号処理 (IIR フィルタ) の実行
+void IIR_Filtering(SD_WavReader &sdReader, SaiIO &mySai,
+                   float g0, Biquad hn[],
+                   int order, bool filterOn)
+{
+    static int32_t frameSize = mySai.GetLength();
+    static Array<int16_t> sn(frameSize);    // フレームバッファ
+
+    // 1フレーム分のデータを SD から読み込む
+    sdReader.ReadAndToMono(sn);
+
+    while (!mySai.IsXferred()) {}  // データの転送が終わるまで待つ
+    //--------------------------------------------------------------
+    // 1フレーム分の信号処理を行い,その結果を出力する
+    for (int n=0; n<frameSize; n++)
+    {
+        // 縦続形の IIR フィルタ
+        float yn = g0*sn[n];
+        for (int k=0; k<order/2; k++) yn = hn[k].Execute(yn);
+
+        int16_t value = filterOn ? (int16_t)yn : sn[n];
+
+        // 音響信号の出力,右チャンネルには出力しない
+        mySai.Output(value, 0);
+    }
+    //--------------------------------------------------------------
+    mySai.ResetXferred();   // 次のデータ転送に備える
+}
+
+// SD カードのファイルのオープン
+int32_t SD_Open(SD_WavReader &sdReader,
+                string fileName, int32_t frameSize)
+{
+    sdReader.Open(fileName);
+    sdReader.IsWavFile();
+    return sdReader.GetSize()/frameSize;
+}
+
+// ファイルの選択
+//      selectedName:   選択されたファイル名
+void SelectFile(ButtonGroup &menu, FileSelector &selector,
+                Label &msg, string &selectedName)
+{
+    selector.DisplayFileList();   
+    msg.Draw("Chon File");
+    do
+    {
+        if (selector.Select(selectedName))
+            menu.Activate(1);   // PLAY 有効
+        wait_ms(200);
+    } while (!menu.Touched(1)); // PLAY がタッチされるまで繰り返す
+}
+
+// フィルタの変更
+void ModifyFilter(DesignerDrawer &drawerObj,
+                  ButtonGroup &lpHp, ButtonGroup &onOff,
+                  Biquad hn[], Biquad::Coefs ck[],
+                  float &g0, bool &filterOn)
+{
+    // フィルタ処理の有効/無効切り替え
+    int sw = 0;
+    if (onOff.GetTouchedNumber(sw))
+        filterOn = (sw == 0) ? true : false;
+
+    // フィルタの周波数特性の変更
+    static int num = 0;
+    lpHp.GetTouchedNumber(num);
+    BilinearDesign::Type typeLH = (BilinearDesign::Type)num;
+    if (drawerObj.ReDesignAndDraw(ck, g0, typeLH))
+        for (int k=0; k<drawerObj.GetOrder()/2; k++)
+        {
+            hn[k].SetCoefficients(ck[k]);
+            hn[k].Clear();
+        }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyFunctions.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,37 @@
+//--------------------------------------------------------------
+//  フィルタ処理付き SD オーディオプレーヤーで使う大域関数(ヘッダ)
+//
+//  2016/07/04, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef F746_MY_FUNCTIONS_HPP
+#define F746_MY_FUNCTIONS_HPP
+
+#include "SAI_InOut.hpp"
+#include "ButtonGroup.hpp"
+#include "FileSelectorWav.hpp"
+#include "DesignerDrawer.hpp"
+#include "SD_WavReader.hpp"
+
+using namespace Mikami;
+
+// 1フレーム分の信号処理 (IIR フィルタ) の実行
+void IIR_Filtering(SD_WavReader &sdReader, SaiIO &mySai,
+                   float g0, Biquad hn[],
+                   int order, bool filterOn);
+
+// SD カードのファイルのオープン
+int32_t SD_Open(SD_WavReader &sdReader,
+             string fileName, int32_t frameSize);
+
+// ファイルの選択
+void SelectFile(ButtonGroup &menu, FileSelector &selector,
+                Label &msg, string &selectedName);
+
+// フィルタの変更
+void ModifyFilter(DesignerDrawer &drawerObj,
+                  ButtonGroup &lpHp, ButtonGroup &onOff,
+                  Biquad hn[], Biquad::Coefs ck[],
+                  float &g0, bool &filterOn);
+
+#endif  // F746_MY_FUNCTIONS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SD_WavReader.cpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,119 @@
+//--------------------------------------------------------------
+//  SD_WavReader class
+//      SD カードの *.wav ファイルの内容を読み出す
+//      以下のフォーマット以外は扱わない
+//          PCM,16 ビットステレオ,標本化周波数 44.1 kHz
+//
+//  2016/06/17, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "SD_WavReader.hpp"
+
+namespace Mikami
+{
+    SD_WavReader::SD_WavReader(int32_t bufferSize)
+        : STR_("sd"), ok_(false)
+    {
+        sd_ = new SDFileSystem(STR_.c_str());
+        sd_->mount();      
+        buffer.SetSize(bufferSize*2);
+    }
+
+    SD_WavReader::~SD_WavReader()
+    {
+        sd_->unmount();
+        delete sd_;
+    }
+    
+    void SD_WavReader::Open(const string fileName)
+    {
+        string name = (string)"/" + STR_ + "/" + fileName;
+        fp_ = fopen(name.c_str(), "rb");
+        if (fp_ == NULL) ErrorMsg("Khong the mo!!");
+    }
+    
+    
+    // ファイルのヘッダ (RIFFxxxxWAVEfm ) 読み込み
+    //      戻り値: *.wav で,16 ビットステレオ,
+    //             標本化周波数:44.1 kHz の場合 true
+    bool SD_WavReader::IsWavFile()
+    {
+        char data[17];
+        fread(data, 1, 16, fp_);
+        string strRead = "";
+        for (int n=0; n<4; n++) strRead += data[n];
+        for (int n=8; n<16; n++) strRead += data[n];
+
+        // "RIFF", "WAVE", "fmt " が存在することを確認
+        if (strRead != "RIFFWAVEfmt ") return false;
+
+        // fmt chunck のサイズを取得
+        uint32_t fmtChunkSize;
+        fread(&fmtChunkSize, sizeof(uint32_t), 1, fp_);
+
+        // PCM, Stereo, 44.1 kHz, 16 bit であることを確認
+        WaveFormatEx fmtData;
+        fread(&fmtData, fmtChunkSize, 1, fp_);
+        if ((fmtData.wFormatTag     != 1)     ||
+            (fmtData.nChannels      != 2)     ||
+            (fmtData.nSamplesPerSec != 44100) ||
+            (fmtData.wBitsPerSample != 16)    
+           ) return false;
+
+        // data chunk を探す
+        char dataId[5];
+        dataId[4] = 0;
+        fread(dataId, 1, 4, fp_);
+        if ("data" != (string)dataId)
+            for (int n=0; n<100; n++)
+            {
+                char oneByte;
+                fread(&oneByte, 1, 1, fp_);
+                for (int k=0; k<3; k++)
+                    dataId[k] = dataId[k+1];
+                dataId[3] = oneByte;
+                if ("data" == (string)dataId) break;
+                
+                if (n == 99) return false;
+            }
+
+        // データサイズ (byte) を取得
+        int32_t sizeByte;
+        fread(&sizeByte, sizeof(int32_t), 1, fp_);
+        size_ = sizeByte/4;
+
+        ok_ = true;
+        return true;
+    }
+
+    // ファイルからステレオデータの取得
+    void SD_WavReader::ReadStereo(Array<int16_t>& dataL,
+                                  Array<int16_t>& dataR)
+    {
+        if (!ok_) ErrorMsg("Lay du lieu that bai");
+        uint32_t size = dataL.Length();
+        fread(buffer, sizeof(int16_t), size*2, fp_);       
+        for (int n=0; n<size; n++)
+        {
+            dataL[n] = buffer[2*n];
+            dataR[n] = buffer[2*n+1];
+        }
+    }
+
+    // ファイルからデータをモノラルに変換しての取得
+    void SD_WavReader::ReadAndToMono(Array<int16_t>& data)
+    {
+        if (!ok_) ErrorMsg("Lay du lieu that bai");
+        uint32_t size = data.Length();
+        fread(buffer, sizeof(int16_t), size*2, fp_);
+        for (int n=0; n<size; n++)
+            data[n] = (buffer[2*n] + buffer[2*n+1])/2;
+    }        
+    
+    // データサイズ(標本化点の数)の取得
+    int32_t SD_WavReader::GetSize()
+    {
+        if (!ok_) ErrorMsg("Loi dung luong du lieu");
+        return size_;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SD_WavReader.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,74 @@
+//--------------------------------------------------------------
+//  SD_WavReader class ---- Header
+//      SD カードの *.wav ファイルの内容を読み出す
+//      以下のフォーマット以外は扱わない
+//          PCM,16 ビットステレオ,標本化周波数 44.1 kHz
+//
+//  2016/06/17, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef SD_WAV_READER_HPP
+#define SD_WAV_READER_HPP
+
+#include "SDFileSystem.h"
+#include "BlinkLabel.hpp"
+#define DEBUG_ARRAY_CHECK
+#include "Array.hpp"
+#include <string>
+
+namespace Mikami
+{
+    class SD_WavReader
+    {
+    public:
+        SD_WavReader(int32_t bufferSize);
+        ~SD_WavReader();
+
+        void Open(const string fileName);
+        
+        void Close() { fclose(fp_); }
+        
+        // ファイルのヘッダ読み込み
+        //      戻り値: *.wav で,16 ビットステレオ,
+        //             標本化周波数:44.1 kHz の場合 true
+        bool IsWavFile();
+
+        // ファイルからステレオデータの取得
+        void ReadStereo(Array<int16_t>& dataL, Array<int16_t>& dataR);
+
+        // ファイルからデータをモノラルに変換しての取得
+        void ReadAndToMono(Array<int16_t>& data);
+        
+        // データサイズ(標本化点の数)の取得
+        int32_t GetSize();
+
+    private:
+        const string STR_;
+        
+        struct WaveFormatEx
+        {
+            uint16_t wFormatTag;        // 1: PCM
+            uint16_t nChannels;         // 1:モノラル,2: ステレオ
+            uint32_t nSamplesPerSec;    // 標本化周波数 (Hz)
+            uint32_t nAvgBytesPerSec;   // 転送速度 (bytes/s)
+            uint16_t nBlockAlign;       // 4: 16ビットステレオの場合
+            uint16_t wBitsPerSample;    // データのビット数,8 または 16
+            uint16_t cbSize;            // PCM の場合使わない
+        };
+
+        SDFileSystem *sd_;
+        FILE *fp_;
+        
+        bool ok_;
+        int32_t size_;          // データサイズ(標本化点の数)
+        Array<int16_t> buffer;  // ステレオをモノラルに変換する際の作業領域
+        
+        void ErrorMsg(char msg[])
+        {   BlinkLabel errLabel(240, 100, msg, Label::CENTER); }
+
+        // disallow copy constructor and assignment operator
+        SD_WavReader(const SD_WavReader&);
+        SD_WavReader& operator=(const SD_WavReader&);
+    };
+}
+#endif  // SD_BINARY_READER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TouchPanelDetectorX.hpp	Tue Jun 04 21:58:08 2019 +0000
@@ -0,0 +1,46 @@
+//------------------------------------------------------
+//  Touch panel detector for x axis class
+//
+//  2016/03/31, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------
+
+#ifndef F746_TOUCH_PANELDETECTORX_HPP
+#define F746_TOUCH_PANELDETECTORX_HPP
+
+#include "GuiBase.hpp"
+
+namespace Mikami
+{
+    class TouchPanelDetectorX : public GuiBase
+    {
+    public:
+        // Constructor
+        TouchPanelDetectorX(uint16_t x1, uint16_t x2,
+                            uint16_t y1, uint16_t y2)
+            : X1_(x1), X2_(x2), Y1_(y1), Y2_(y2) {}
+
+        bool IsTouched(uint16_t xIn, uint16_t &xOut)
+        {
+            GetTsState();
+            
+            if (!state_.touchDetected) return false;
+            
+            uint16_t x = state_.touchX[0];
+            uint16_t y = state_.touchY[0];
+
+            if ( (x < X1_) || (x > X2_) || (y < Y1_) || (y > Y2_) )
+                return false;
+
+            const int WD = 8;
+            if ( (x < xIn-WD) || (x > xIn+WD) ) return false;
+            
+            xOut = (x >= X1_) ? x : X1_;
+            xOut = (x <= X2_) ? x : X2_;
+            return true;
+        }
+
+    private:
+        const uint16_t X1_, X2_, Y1_, Y2_;
+    };
+}   
+#endif  // F746_TOUCH_PANELDETECTORX_HPP