boting ren / Mbed 2 deprecated F746_SD_GraphicEqualizer_ren0620

Dependencies:   BSP_DISCO_F746NG F746_GUI F746_SAI_IO FrequencyResponseDrawer LCD_DISCO_F746NG SDFileSystem_Warning_Fixed TS_DISCO_F746NG mbed

Fork of F746_SD_GraphicEqualizer by 不韋 呂

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Mon May 09 08:54:09 2016 +0000
Parent:
7:be29ba9c83b2
Child:
9:0d5bd1539291
Commit message:
8

Changed in this revision

MyClasses_Functions/BiquadGrEq.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/DesignerDrawer.cpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/DesignerDrawer.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/FileSelectorWav.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/GrEqParamsCalculator.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/GrEqualizerFrqResp.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/MyFunctions.cpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/MyFunctions.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/SD_WavReader.cpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/SD_WavReader.hpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/BiquadGrEq.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,66 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザで使う 1D タイプの 2 次のフィルタ
+//  Biquad filter of 1D type for graphic equalizer
+//      このクラスでは,係数は実行中に書き換えられることを想定している
+//
+//      u[n] = x[n] + a1*u[n-1] + a2*u[n-2]
+//      y[n] = b0*u[n] + b1*u[n-1] + b2*u[n-2]
+//          x[n] :  input signal
+//          y[n] :  output signal
+//
+// 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 BiquadGrEq
+    {
+    public:
+        struct Coefs { float a1, a2, b0, b1, b2; };
+
+        BiquadGrEq() {}     // Default constructore
+
+        BiquadGrEq(const Coefs ck)
+        {
+            SetCoefficients(ck);
+            Clear();
+        }
+        
+        void SetCoefficients(const Coefs ck)
+        {
+            a1_ = ck.a1;
+            a2_ = ck.a2;
+            b0_ = ck.b0;
+            b1_ = ck.b1;
+            b2_ = ck.b2;
+        }
+
+        float Execute(float xn)
+        {
+            float un = xn + a1_*un1_ + a2_*un2_;
+            float yn = b0_*un + b1_*un1_ + b2_*un2_;
+        
+            un2_ = un1_;
+            un1_ = un;
+
+            return yn;
+        }
+
+        void Clear() { un1_ = un2_ = 0; }
+
+    private:
+        float a1_, a2_, b0_, b1_, b2_;
+        float un1_, un2_;
+
+        // disallow copy constructor
+        BiquadGrEq(const BiquadGrEq&);
+    };
+}
+#endif  // IIR_BIQUAD_HPP
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/DesignerDrawer.cpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,76 @@
+//------------------------------------------------------------------------------
+//  イコライザ用フィルタのパラメータを設定し,その周波数特性を描画するためのクラス
+//  
+//  2016/05/09, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#include "DesignerDrawer.hpp"
+
+namespace Mikami
+{
+    // Constructor
+    DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0,
+                                   int bands, float f0, int fs, float db1)
+        : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()),
+          X0_(x0), Y0_(y0), BANDS_(bands), Q_VAL_(1.0f/sqrtf(2.0f))
+    {
+        drawerObj_ = new FrqRespDrawer(x0, 50.0f, 20000.0f, 142,
+                                       y0, -18, 18, db1, 6, fs);
+
+        calculator_ = new GrEqParams(bands, fs);
+        f0_ = new float[bands];
+        for (int n=0; n<bands; n++)
+            f0_[n] = f0*powf(2, n);
+
+        ck_ = new BiquadGrEq::Coefs[bands];
+        for (int n=0; n<bands; n++)
+            ck_[n] = calculator_->Execute(n, f0_[n], 0, Q_VAL_);
+        frqResp_ = new GrEqualizerFrqResp(bands);
+        frqResp_->SetParams(ck_);
+
+        // 周波数特性の描画
+        DrawResponse();
+    }
+
+    DesignerDrawer::~DesignerDrawer()
+    {
+        delete[] frqResp_;
+        delete[] ck_;
+        delete[] f0_;
+        delete calculator_;
+        delete drawerObj_;
+    }
+
+    // 周波数特性の描画
+    void DesignerDrawer::DrawResponse()
+    {
+        drawerObj_->DrawAxis();             // 目盛線の描画        
+        FrqRespDrawer::AxisX_Char numX[] =  // 横軸の目盛値を描画する際に使う構造体の配列
+            {{   50,  "50"}, {  100, "100"}, {  200, "200"}, {  500, "500"}, { 1000, "1k"},
+             { 2000,  "2k"}, { 5000,  "5k"}, {10000, "10k"}, {20000, "20k"}};
+        drawerObj_->DrawNumericX(numX, 9, 6, "Frequency [Hz]"); // 横軸の目盛
+        drawerObj_->DrawNumericY(-24, -6, 6, "%3d");            // 縦軸の目盛値は 6 dB 間隔
+        drawerObj_->DrawGraph(frqResp_);    // 周波数特性のカーブの描画
+    }
+    
+    // 周波数特性の平坦化と描画
+    void DesignerDrawer::DrawFlat()
+    {
+        for (int n=0; n<BANDS_; n++)
+            ck_[n] = calculator_->Execute(n, f0_[n], 0, Q_VAL_);
+        frqResp_->SetParams(ck_);
+        drawerObj_->Erase();
+        drawerObj_->DrawAxis();             // 目盛線の描画
+        drawerObj_->DrawGraph(frqResp_);    // 周波数特性のグラフのカーブを描画する
+    }
+
+    // 特定のバンドのイコライザ用フィルタのパラメータの設定と周波数特性の再描画
+    void DesignerDrawer::DesignAndRedraw(float gainDb, int n)
+    {
+        ck_[n] = calculator_->Execute(n, f0_[n],  gainDb, Q_VAL_);
+        frqResp_->SetParam(ck_[n], n);
+        drawerObj_->Erase();
+        drawerObj_->DrawAxis();             // 目盛線の描画
+        drawerObj_->DrawGraph(frqResp_);    // 周波数特性のグラフのカーブを描画する
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/DesignerDrawer.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,64 @@
+//------------------------------------------------------------------------------
+//  イコライザ用フィルタのパラメータを設定し,その周波数特性を描画するためのクラス -- Header
+//  
+//  2016/05/09, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#ifndef F746_DISIGNER_AND_DRAWER_HPP
+#define F746_DISIGNER_AND_DRAWER_HPP
+
+#include "NumericLabel.hpp"
+#include "FrquencyResponseDrawer.hpp"
+#include "GrEqParamsCalculator.hpp"
+#include "GrEqualizerFrqResp.hpp"
+
+namespace Mikami
+{
+    class DesignerDrawer
+    {
+    public:
+        // Constructor
+        DesignerDrawer(uint16_t x0, uint16_t y0,
+                       int stages, float f0, int fs, float db1);
+
+        ~DesignerDrawer();
+
+        // 周波数特性の描画
+        void DrawResponse();
+
+        // 周波数特性の平坦化と描画
+        void DrawFlat();
+
+        // 特定のバンドのイコライザ用フィルタのパラメータの設定と周波数特性の再描画
+        void DesignAndRedraw(float gainDb, int n);
+
+        void GetCoefficients(BiquadGrEq::Coefs ck[])
+        {   for (int n=0; n<BANDS_; n++) ck[n] = ck_[n]; }
+        
+        BiquadGrEq::Coefs GetCoefficient(int n) { return ck_[n]; }
+
+        uint16_t GetX0()
+        {   return drawerObj_->X(f0_[0]); }
+        
+        uint16_t GetSpaceX()
+        {   return (uint16_t)(drawerObj_->X(f0_[1])
+                            - drawerObj_->X(f0_[0])); }
+
+        int GetStages() { return BANDS_; }
+
+    private:
+        LCD_DISCO_F746NG *lcd_;
+        TS_DISCO_F746NG *ts_;
+
+        const uint16_t X0_, Y0_;
+        const int BANDS_;
+        const float Q_VAL_;
+
+        float *f0_;         // 中心周波数を格納する配列のポインタ
+        GrEqParams *calculator_;
+        GrEqualizerFrqResp *frqResp_;   // フィルタの周波数応答に対応するオブジェクト
+        BiquadGrEq::Coefs *ck_;         // フィルタの係数
+        FrqRespDrawer *drawerObj_;
+    };
+}
+#endif  // F746_DISIGNER_AND_DRAWER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/FileSelectorWav.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,182 @@
+//--------------------------------------------------------------
+//  FileSelector class
+//      SD カード内のファイル名の一覧を表示し,ファイルを選択する
+//
+//  2016/04/18, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef FILE_SELECTOR_HPP
+#define FILE_SELECTOR_HPP
+
+#include "mbed.h"
+#include "Label.hpp"
+#include "ButtonGroup.hpp"
+#include "SD_WavReader.hpp"
+#include "SDFileSystem.h"
+#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_(new string[maxFiles]),
+              sortedFileNames_(new string[maxFiles]),
+              nonString_(NULL), rect_(NULL), fileNameLabels_(NULL),
+              lcd_(GuiBase::GetLcdPtr()),
+              sdReader_(reader), prevFileCount_(0), prev_(-1) {}
+
+        ~FileSelector()
+        {
+            for (int n=0; n<fileCount_; n++)
+                delete fileNameLabels_[n];
+            delete[] fileNameLabels_;
+            delete rect_;
+            delete[] nonString_;
+            delete[] sortedFileNames_;
+            delete[] fileNames_;
+        }
+        
+        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;
+                            fileCount_++;
+                        }
+                        sdReader_.Close();
+                    }
+
+
+                    if (fileCount_ >= MAX_FILES_) break;
+                }
+                closedir(dp); 
+            }
+            else
+                return false;
+                
+            if (fileCount_ == 0) return false;
+
+            if (nonString_ == NULL) delete[] nonString_;
+            nonString_ = new string[fileCount_];
+            for (int n=0; n<fileCount_; n++) nonString_[n] = "";
+            
+            if (rect_ != NULL) delete rect_;
+            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 = sortedFileNames_[n];
+                return true;
+            }
+            else
+                return false;
+        }
+
+        // ファイルの一覧の表示
+        void DisplayFileList(bool sort = true)
+        {
+            for (int n=0; n<fileCount_; n++)
+                sortedFileNames_[n] = fileNames_[n];
+            if (sort)
+                std::sort(sortedFileNames_, sortedFileNames_+fileCount_); 
+            
+            Erase(X_, 0, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 288);
+            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_;
+        
+        string *fileNames_;
+        string *sortedFileNames_;
+        string *nonString_;
+        ButtonGroup *rect_;
+        Label **fileNameLabels_;
+        LCD_DISCO_F746NG *lcd_;
+        SD_WavReader &sdReader_;
+        int fileCount_, prevFileCount_;
+        int prev_;
+
+        // Label を生成
+        void CreateLabels()
+        {
+            if (fileNameLabels_ != NULL)
+            {
+                for (int n=0; n<prevFileCount_; n++)
+                    delete fileNameLabels_[n];
+                delete[] fileNameLabels_;
+            }
+            fileNameLabels_ = new Label *[fileCount_+1];
+            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 = sortedFileNames_[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/MyClasses_Functions/GrEqParamsCalculator.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,86 @@
+//------------------------------------------------------------------------------
+//  Parameters calculator class of buquad unit for graphic equalizer
+//  グラフィックイコライザで使う biquad フィルタの係数を計算するクラス
+//
+//   2016/05/09, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#ifndef GRAPHIC_EQALIZER_PARAMETER_CALCULATOR_HPP
+#define GRAPHIC_EQALIZER_PARAMETER_CALCULATOR_HPP
+
+#include "mbed.h"
+#include "BiquadGrEq.hpp"
+
+namespace Mikami
+{
+    class GrEqParams
+    {
+    public:
+        // Constructor
+        GrEqParams(int bands, float fs) : BANDS_(bands), FS_(fs) {}
+
+        // 係数を計算する
+        BiquadGrEq::Coefs Execute(int band, float f0, float gDb, float qVal)
+        {
+            const float PI = 3.1415926536f;
+            BiquadGrEq::Coefs coefs;
+            
+            float gSqrt = sqrtf(powf(10, gDb/20.0f));
+            float w0 = 2.0f*PI*f0/FS_;
+            
+            if ( (band != 0) && (band != BANDS_-1) )
+            {
+                float alpha = sinf(w0)/(2.0f*qVal);
+                float a0 = 1.0f + alpha/gSqrt;
+                coefs.a1 = 2.0f*cosf(w0)/a0;
+                coefs.a2 = -(1.0f - alpha/gSqrt)/a0;
+                coefs.b0 = (1.0f + alpha*gSqrt)/a0;
+                coefs.b1 = -coefs.a1;
+                coefs.b2 = (1.0f - alpha*gSqrt)/a0;
+            }
+            else
+            {
+                w0 = (band == 0) ? w0*1.414f : w0/1.414f;
+                float alpha = sinf(w0)/sqrtf(2.0f); // Q = 1/sqrt(2)
+                float g_a = sqrtf(gSqrt);
+                float cosW0 = cosf(w0);
+                float gSqrtP1 = gSqrt+1.0f;
+                float gSqrtM1 = gSqrt-1.0f;
+                if (band == 0)
+                {                   
+                    float a0 = gSqrtP1 + gSqrtM1*cosW0
+                               + 2.0f*g_a*alpha;
+                    coefs.a1 = 2.0f*(gSqrtM1 + gSqrtP1*cosW0)/a0;
+                    coefs.a2 = -(gSqrtP1 + gSqrtM1*cosW0
+                               - 2.0f*g_a*alpha)/a0;
+                    coefs.b0 = gSqrt*(gSqrtP1 - gSqrtM1*cosW0
+                               + 2.0f*g_a*alpha)/a0;
+                    coefs.b1 = 2.0f*gSqrt*(gSqrtM1
+                               - gSqrtP1*cosW0)/a0;
+                    coefs.b2 = gSqrt*(gSqrtP1 - gSqrtM1*cosW0
+                               - 2.0f*g_a*alpha)/a0;
+                }
+                else
+                {
+                    float a0 = gSqrtP1 - gSqrtM1*cosW0
+                               + 2.0f*g_a*alpha;
+                    coefs.a1 = -2.0f*(gSqrtM1 - gSqrtP1*cosW0)/a0;
+                    coefs.a2 = -(gSqrtP1 - gSqrtM1*cosW0
+                               - 2.0f*g_a*alpha)/a0;
+                    coefs.b0 = gSqrt*(gSqrtP1 + gSqrtM1*cosW0
+                               + 2.0f*g_a*alpha)/a0;
+                    coefs.b1 = -2.0f*gSqrt*(gSqrtM1 + gSqrtP1*cosW0)/a0;
+                    coefs.b2 = gSqrt*(gSqrtP1 + gSqrtM1*cosW0
+                               - 2.0f*g_a*alpha)/a0;
+                }
+            }
+
+            return coefs;
+        }
+
+    private:
+        const int BANDS_;
+        const float FS_;
+    };
+}
+#endif  // GRAPHIC_EQALIZER_PARAMETER_CALCULATOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/GrEqualizerFrqResp.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------
+//  グラフィックイコライザで使う IIR フィルタの周波数応答
+//  Frequency response for graphic equalizer
+//
+//  2016/04/27, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef GRAPHIC_EQUALIZER_FREQUENCY_RESPONSE_HPP
+#define GRAPHIC_EQUALIZER_FREQUENCY_RESPONSE_HPP
+
+#include "FrequancyResponseBase.hpp"
+#include "BiquadGrEq.hpp"
+
+namespace Mikami
+{
+    class GrEqualizerFrqResp : public FrequencyResponse
+    {
+    public:
+        GrEqualizerFrqResp(int stages) : STAGES_(stages)
+        {   ck_ = new BiquadGrEq::Coefs[stages];  }
+        
+        ~GrEqualizerFrqResp()
+        {   delete[] ck_; }
+
+        // フィルタの係数設定
+        void SetParams(BiquadGrEq::Coefs ck[])
+        {   for (int n=0; n<STAGES_; n++) ck_[n] = ck[n]; }
+        
+        void SetParam(BiquadGrEq::Coefs ck, int n)
+        {   ck_[n] = ck; }
+
+        // 周波数応答の絶対値を返す関数, 引数: z^(-1)
+        virtual float AbsH_z(Complex u)
+        {
+            Complex h = 1;
+            for (int k=0; k<STAGES_; k++)
+            h = h*(ck_[k].b0 + (ck_[k].b1 + ck_[k].b2*u)*u)
+                /((1.0f - (ck_[k].a1 + ck_[k].a2*u)*u));
+            return abs(h);       
+        }
+
+    private:
+        const int STAGES_;
+        float g0_;
+        BiquadGrEq::Coefs *ck_;
+
+        // disallow copy constructor and assignment operator
+        GrEqualizerFrqResp(const GrEqualizerFrqResp&);
+        GrEqualizerFrqResp& operator=(const GrEqualizerFrqResp&);
+    };
+}
+#endif  // GRAPHIC_EQUALIZER_FREQUENCY_RESPONSE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/MyFunctions.cpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,83 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザ付き SD オーディオプレーヤーで使う大域関数
+//
+//  2016/05/09, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "MyFunctions.hpp"
+
+// 1フレーム分の信号処理 (イコライザ) の実行
+void SignalProcessing(SD_WavReader &sdReader, SaiIO &mySai,
+                      int16_t sn[], BiquadGrEq hn[],
+                      int stages, bool on)
+{
+    // 1フレーム分のデータを SD から読み込む
+    sdReader.ReadAndToMono(sn, mySai.GetLength());
+
+    while (!mySai.IsXferred()) {}   // データの転送が終わるまで待つ
+    //--------------------------------------------------------------
+    // 1フレーム分のイコライザ処理を行い,その結果を出力する
+    for (int n=0; n<mySai.GetLength(); n++)
+    {
+        // 縦続形の IIR フィルタ実行
+        float xn = 0.125f*sn[n];    // 0.125 の乗算はブースとしてもクリップ
+                                    // されないようにするため
+        float yn = xn;
+        for (int k=0; k<stages; k++) yn = hn[k].Execute(yn);
+        int16_t value = on ? (int16_t)yn : xn;
+        mySai.Output(value, value); // 音響信号の出力
+    }
+    //--------------------------------------------------------------
+    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("Select file");
+    do
+    {
+        if (selector.Select(selectedName))
+            menu.Activate(1);   // PLAY 有効
+        wait_ms(200);
+    } while (!menu.Touched(1)); // PLAY がタッチされるまで繰り返す
+}
+
+// フィルタの周波数特性の変更
+void ModifyFilter(DesignerDrawer &drawerObj,
+                  SeekbarGroup &myBars, BiquadGrEq hn[],
+                  Button &flat, ButtonGroup &onOff, bool &on)
+{
+
+    // 周波数特性を平坦化
+    if (flat.Touched())
+    {
+        drawerObj.DrawFlat();
+        for (int n=0; n<drawerObj.GetStages(); n++)
+            hn[n] = BiquadGrEq(drawerObj.GetCoefficient(n));
+        myBars.DrawAll(0);  // ツマミの位置を 0 dB に設定する
+        flat.Draw();
+        return;
+    }
+
+    int sw = 0;
+    if (onOff.GetTouchedNumber(sw))
+        on = (sw == 0) ? true : false;
+
+    static int num = 0;
+    if (!myBars.GetSlidedNumber(num)) return;
+    drawerObj.DesignAndRedraw(myBars.GetValue(num), num);
+    hn[num] = BiquadGrEq(drawerObj.GetCoefficient(num));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/MyFunctions.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,38 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザ付き SD オーディオプレーヤーで使う大域関数(ヘッダ)
+//
+//  2016/05/09, 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"
+#include "SeekbarGroup.hpp"
+#include "BiquadGrEq.hpp"
+
+using namespace Mikami;
+
+// 1フレーム分の信号処理 (イコライザ) の実行
+void SignalProcessing(SD_WavReader &sdReader, SaiIO &mySai,
+                      int16_t sn[], BiquadGrEq hn[],
+                      int stages, bool on);
+
+// 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,
+                  SeekbarGroup &myBars, BiquadGrEq hn[],
+                  Button &flat, ButtonGroup &onOff, bool &on);
+
+#endif  // F746_MY_FUNCTIONS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/SD_WavReader.cpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,113 @@
+//--------------------------------------------------------------
+//  SD_WavReader class
+//      SD カードの *.wav ファイルの内容を読み出す
+//      以下のフォーマット以外は扱わない
+//          PCM,16 ビットステレオ,標本化周波数 44.1 kHz
+//
+//  2016/04/19, 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 = new int16_t[bufferSize*2];
+    }
+
+    SD_WavReader::~SD_WavReader()
+    {
+        delete[] buffer;
+        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("open error!!");
+    }
+    
+    
+    // ファイルのヘッダ (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::Read(int16_t data[], uint32_t size)
+    {
+        if (!ok_) ErrorMsg("Get data FAILED");
+        fread(data, sizeof(int16_t), size, fp_);
+    }        
+
+    // ファイルからデータをモノラルに変換しての取得
+    void SD_WavReader::ReadAndToMono(int16_t data[], uint32_t size)
+    {
+        if (!ok_) ErrorMsg("Get data FAILED");
+        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("Get data size FAILED");
+        return size_;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/SD_WavReader.hpp	Mon May 09 08:54:09 2016 +0000
@@ -0,0 +1,72 @@
+//--------------------------------------------------------------
+//  SD_WavReader class ---- Header
+//      SD カードの *.wav ファイルの内容を読み出す
+//      以下のフォーマット以外は扱わない
+//          PCM,16 ビットステレオ,標本化周波数 44.1 kHz
+//
+//  2016/04/19, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef SD_WAV_READER_HPP
+#define SD_WAV_READER_HPP
+
+#include "SDFileSystem.h"
+#include "BlinkLabel.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_); }
+        
+        // ファイルのヘッダ (RIFFxxxxWAVEfm ) 読み込み
+        //      戻り値: *.wav で,16 ビットステレオ,
+        //             標本化周波数:44.1 kHz の場合 true
+        bool IsWavFile();
+
+        // ファイルからデータの取得
+        void Read(int16_t data[], uint32_t size);
+
+        // ファイルからデータをモノラルに変換しての取得
+        void ReadAndToMono(int16_t data[], uint32_t size);
+        
+        // データサイズ(標本化点の数)の取得
+        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;
+        };
+
+        SDFileSystem *sd_;
+        FILE *fp_;
+        
+        bool ok_;
+        int32_t size_;      // モノラルデータのサイズ
+        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