revised version of F746_SD_GraphicEqualizer

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:
Wed Apr 27 13:56:39 2016 +0000
Child:
1:a5837720e14a
Commit message:
1

Changed in this revision

BSP_DISCO_F746NG.lib Show annotated file Show diff for this revision Revisions of this file
F746_GUI.lib Show annotated file Show diff for this revision Revisions of this file
LCD_DISCO_F746NG.lib Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/BSP_AudioOut_Overwrite.cpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/BSP_AudioOut_Overwrite.hpp Show annotated file Show diff for this revision Revisions of this file
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/FrequancyResponseBase.hpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/FrquencyResponseDrawer.cpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/FrquencyResponseDrawer.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/SAI_Output.cpp Show annotated file Show diff for this revision Revisions of this file
MyClasses_Functions/SAI_Output.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
SDFileSystem_Warning_Fixed.lib Show annotated file Show diff for this revision Revisions of this file
TS_DISCO_F746NG.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BSP_DISCO_F746NG.lib	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/ST/code/BSP_DISCO_F746NG/#458ab1edf6b2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F746_GUI.lib	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/MikamiUitOpen/code/F746_GUI/#7debdaa7b503
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LCD_DISCO_F746NG.lib	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/ST/code/LCD_DISCO_F746NG/#d44525b1de98
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/BSP_AudioOut_Overwrite.cpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,112 @@
+//--------------------------------------------------------------
+//  Overwrite functuions and define calback functions
+//  for functions in stm32746g_discovery_audio.cpp
+//--------------------------------------------------------------
+#include "BSP_AudioOut_Overwrite.hpp"
+
+// These three callback functions are modyfied by Mikami
+void BSP_AUDIO_OUT_HalfTransfer_CallBack()
+{
+    Mikami::SaiIO_O::FillBuffer1st();
+}
+
+void BSP_AUDIO_OUT_TransferComplete_CallBack()
+{
+    Mikami::SaiIO_O::FillBuffer2nd();
+}
+
+void BSP_AUDIO_OUT_Error_CallBack()
+{
+    Mikami::SaiIO_O::ErrorTrap();
+}
+
+//--------------------------------------------------------------
+//  Followings are original by Nanase
+//--------------------------------------------------------------
+
+DMA_HandleTypeDef hdma_sai_tx;
+
+void AUDIO_OUT_SAIx_DMAx_IRQHandler()
+{
+    HAL_DMA_IRQHandler(&hdma_sai_tx);
+}
+
+void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
+{
+    //static DMA_HandleTypeDef hdma_sai_tx;
+    GPIO_InitTypeDef  gpio_init_structure;
+
+    /* Enable SAI clock */
+    AUDIO_OUT_SAIx_CLK_ENABLE();
+
+    /* Enable GPIO clock */
+    AUDIO_OUT_SAIx_MCLK_ENABLE();
+    AUDIO_OUT_SAIx_SCK_SD_ENABLE();
+    AUDIO_OUT_SAIx_FS_ENABLE();
+
+    /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
+    gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN;
+    gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+    gpio_init_structure.Pull = GPIO_NOPULL;
+    gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+    gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF;
+    HAL_GPIO_Init(AUDIO_OUT_SAIx_FS_GPIO_PORT, &gpio_init_structure);
+
+    gpio_init_structure.Pin = AUDIO_OUT_SAIx_SCK_PIN;
+    gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+    gpio_init_structure.Pull = GPIO_NOPULL;
+    gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+    gpio_init_structure.Alternate = AUDIO_OUT_SAIx_SCK_AF;
+    HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
+
+    gpio_init_structure.Pin =  AUDIO_OUT_SAIx_SD_PIN;
+    gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+    gpio_init_structure.Pull = GPIO_NOPULL;
+    gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+    gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF;
+    HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
+
+    gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
+    gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+    gpio_init_structure.Pull = GPIO_NOPULL;
+    gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+    gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF;
+    HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
+
+    /* Enable the DMA clock */
+    AUDIO_OUT_SAIx_DMAx_CLK_ENABLE();
+
+    if(hsai->Instance == AUDIO_OUT_SAIx)
+    {
+        /* Configure the hdma_saiTx handle parameters */
+        hdma_sai_tx.Init.Channel             = AUDIO_OUT_SAIx_DMAx_CHANNEL;
+        hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
+        hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
+        hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
+        hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE;
+        hdma_sai_tx.Init.MemDataAlignment    = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE;
+        hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
+        hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
+        hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
+        hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+        hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
+        hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE;
+
+        hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM;
+
+        /* Associate the DMA handle */
+        __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
+
+        /* Deinitialize the Stream for new transfer */
+        HAL_DMA_DeInit(&hdma_sai_tx);
+
+        /* Configure the DMA Stream */
+        HAL_DMA_Init(&hdma_sai_tx);
+    }
+    
+    /* SAI DMA IRQ Channel configuration */
+    HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
+    HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/BSP_AudioOut_Overwrite.hpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,14 @@
+//--------------------------------------------------------------
+//  Overwrite functuions and define calback function (Header)
+//  for functions in stm32746g_discovery_audio.cpp
+//--------------------------------------------------------------
+
+#ifndef F746_AUDIO_OUT_OVERWRITE_HPP
+#define F746_AUDIO_OUT_OVERWRITE_HPP
+
+#include "stm32746g_discovery_audio.h"
+#include "SAI_Output.hpp"
+
+void AUDIO_OUT_SAIx_DMAx_IRQHandler();
+
+#endif  // F746_AUDIO_OUT_OVERWRITE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/BiquadGrEq.hpp	Wed Apr 27 13:56:39 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	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,81 @@
+//------------------------------------------------------------------------------
+//  イコライザ用フィルタのパラメータを設定し,その周波数特性を描画するためのクラス
+//  
+//  2016/04/27, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------------------------------
+
+#include "DesignerDrawer.hpp"
+
+namespace Mikami
+{
+    // Constructor
+    DesignerDrawer::DesignerDrawer(uint16_t x0, uint16_t y0,
+                                   int stages, float f0, int fs, uint16_t db1)
+        : lcd_(GuiBase::GetLcdPtr()), ts_(GuiBase::GetTsPtr()),
+          X0_(x0), Y0_(y0), STAGES_(stages), DB1_(db1), Q_VAL_(1.5f)
+    {
+        drawerObj_ = new FrqRespDrawer(x0, 50.0f, 20000.0f, 142,
+                                       y0, -12, 12, db1, 3, fs);
+
+        calculator_ = new GrEqParamsCalculator(fs);
+        f0_ = new float[STAGES_];
+        for (int n=0; n<STAGES_; n++)
+            f0_[n] = f0*powf(2, n);
+
+        ck_ = new BiquadGrEq::Coefs[STAGES_];
+        Flatten();
+        frqResp_ = new GrEqualizerFrqResp(STAGES_);
+        frqResp_->SetParams(ck_);
+
+        // 周波数特性の描画
+        DrawResponse();
+    }
+
+    DesignerDrawer::~DesignerDrawer()
+    {
+        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::DesignAndRedraw(float gainDb, int n)
+    {
+        ck_[n] = calculator_->Execute(f0_[n],  gainDb, Q_VAL_);
+        frqResp_->SetParam(ck_[n], n);
+        drawerObj_->Erase();
+        drawerObj_->DrawAxis();             // 目盛線の描画
+        drawerObj_->DrawGraph(frqResp_);    // 周波数特性のグラフのカーブを描画する
+    }
+
+    // 周波数特性をフラットにし,その周波数特性を再描画
+    void DesignerDrawer::DesignAndRedraw()
+    {
+        Flatten();
+        frqResp_->SetParams(ck_);
+        drawerObj_->Erase();
+        drawerObj_->DrawAxis();             // 目盛線の描画
+        drawerObj_->DrawGraph(frqResp_);    // 周波数特性のグラフのカーブを描画する
+    }
+
+    // イコライザ用フィルタの周波数特性をフラットにする
+    void DesignerDrawer::Flatten()
+    {
+        for (int n=0; n<STAGES_; n++)
+            ck_[n] = calculator_->Execute(f0_[n], 0, Q_VAL_);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/DesignerDrawer.hpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,68 @@
+//------------------------------------------------------------------------------
+//  イコライザ用フィルタのパラメータを設定し,その周波数特性を描画するためのクラス -- Header
+//  
+//  2016/04/27, 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, uint16_t db1);
+
+        ~DesignerDrawer();
+
+        // 周波数特性の描画
+        void DrawResponse();
+
+        // 特定のバンドのイコライザ用フィルタのパラメータの設定と周波数特性の再描画
+        void DesignAndRedraw(float gainDb, int n);
+        
+        // 周波数特性をフラットにし,その周波数特性を再描画
+        void DesignAndRedraw();
+
+        // イコライザ用フィルタの周波数特性をフラットにする
+        void Flatten();
+
+        void GetCoefficients(BiquadGrEq::Coefs ck[])
+        {   for (int n=0; n<STAGES_; 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 STAGES_; }
+
+    private:
+        LCD_DISCO_F746NG *lcd_;
+        TS_DISCO_F746NG *ts_;
+
+        const uint16_t X0_, Y0_;
+        const int STAGES_;
+        const uint16_t DB1_;
+        const float Q_VAL_;
+
+        float *f0_;
+        GrEqParamsCalculator *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	Wed Apr 27 13:56:39 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(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 width, uint16_t height,
+                   uint32_t color = GuiBase::ENUM_BACK)
+        {
+            lcd_->SetTextColor(color);
+            lcd_->FillRect(0, 0, 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/FrequancyResponseBase.hpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,27 @@
+//------------------------------------------------------
+//  FrqRespDrawer クラスで周波数特性を描画する際に使う
+//  周波数応答に対応するクラスの抽象基底クラス
+//
+//  2016/04/27, Copyright (c) 2016 MIKAMI, Naoki
+//------------------------------------------------------
+
+#ifndef FREQUENCY_RESPONSE_BASE_HPP
+#define FREQUENCY_RESPONSE_BASE_HPP
+
+#include <complex>  // requisite for complex
+
+namespace Mikami
+{
+    typedef complex<float> Complex; // define "Complex"
+
+    class FrequencyResponse
+    {
+    public:
+        // 周波数応答の絶対値を返す関数, 引数: z^(-1)
+        virtual float AbsH_z(Complex u) = 0;
+
+    protected:
+        FrequencyResponse() {}
+    };
+}
+#endif  // F746_FREQUENCY_RESPONSE_BASE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/FrquencyResponseDrawer.cpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,105 @@
+//-----------------------------------------------------------
+//  周波数が対数スケールの周波数特性を描画するクラス
+//  FrqRespDrawer class
+//
+//  2016/04/25, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#include "FrquencyResponseDrawer.hpp"
+
+namespace Mikami
+{
+    // 目盛線の描画
+    void FrqRespDrawer::DrawAxis()
+    {
+        uint16_t height = DB1_*(MAX_DB_ - MIN_DB_);
+        int logMin = (int)floorf(log10f(MIN_));
+        int loop = (int)floorf(log10f(MAX_)) - logMin;
+
+        lcd_->SetTextColor(AXIS_COLOR_);
+        uint16_t y0 = ORGY_ - height;
+        lcd_->DrawVLine(X(MIN_), y0, height);   // 最小値に対応する線
+
+        float du = powf(10.0, logMin);          // 座標値の増分
+        float u1 = (floorf(MIN_/du) + 1.0f)*du; // 最小値に対応する線の次の座標値
+
+        for (int n=0; n<=loop; n++)
+        {
+            float uMax = (10.0f*du < MAX_) ? 10.0f*du : MAX_;
+            for (float u=u1; u<uMax*0.99f; u+=du)
+                lcd_->DrawVLine(X(u), y0, height);
+
+            du = uMax;          // 値の増分を 10 倍する
+            u1 = du;            // 次の for ループ の最初の値
+        }
+
+        lcd_->DrawVLine(X(MAX_), y0, height);   // 最大値に対応する線
+        
+        uint16_t width = X(MAX_) - X(MIN_);
+        int count =Round((MAX_DB_ - MIN_DB_)/(Y_SPACE_/DB1_));
+        for (int n=0; n<= count; n++)
+            lcd_->DrawHLine(X(MIN_), ORGY_-Y_SPACE_*n, width);
+    }
+
+    // 横軸の目盛値の表示
+    void FrqRespDrawer::DrawNumericX(AxisX_Char xChar[], int nDisp, int offsetY,
+                                     string str, sFONT &fonts, uint32_t textColor)
+    {
+        for (int n=0; n<nDisp; n++)
+            Label frq(X(xChar[n].frq), ORGY_+offsetY,
+                        xChar[n].str, Label::CENTER);
+        uint16_t x0 = ORGX_ + (uint16_t)(DEC_*log10f(MAX_/MIN_))/2;
+        Label l_frq(x0, ORGY_+20, str, Label::CENTER);
+    }
+
+    // 縦軸の目盛値の表示
+    void FrqRespDrawer::DrawNumericY(int offsetX, int offsetY, uint16_t d_dB,
+                                     const char fmt[], sFONT &fonts,
+                                     uint32_t textColor, string str)
+    {
+        uint16_t x0 = ORGX_ + offsetX;
+        uint16_t y0 = ORGY_ + offsetY;
+        int count = Round((MAX_DB_ - MIN_DB_)/d_dB);
+
+        for (int n=0; n<=count; n++)
+            NumericLabel<int> num(x0, y0-n*d_dB*DB1_,
+                                  fmt, (int)(MIN_DB_+d_dB*n));
+        Label l_dB(x0, y0-count*d_dB*DB1_-12, str);
+    }
+
+    // 周波数特性のグラフの描画
+    void FrqRespDrawer::DrawGraph(FrequencyResponse *frqResp, uint32_t color)
+    {
+        lcd_->SetTextColor(color);
+        uint16_t width = X(MAX_) - X(MIN_);   
+        uint16_t x1 = 0;
+        uint16_t y1 = 0;
+        float pi2FsM = -6.283185f/FS_;  // -2*PI*Ts
+        for (int n=0; n<=width; n++)
+        {
+            float frq = PosToFrq(n+ORGX_);
+            uint16_t x2 = X(frq);
+            float absHz = frqResp->AbsH_z(exp(Complex(0, pi2FsM*frq)));
+            float dB = (absHz > 0.001f) ? 20.0f*log10f(absHz) : MIN_DB_;
+            uint16_t y2 = ORGY_ - Round((dB - MIN_DB_)*DB1_);
+            if (y2 > ORGY_) y2 = ORGY_;
+
+            if (n != 0) lcd_->DrawLine(x1, y1, x2, y2);
+
+            x1 = x2;
+            y1 = y2;
+        }
+        lcd_->SetTextColor(AXIS_COLOR_);
+        lcd_->DrawHLine(X(MIN_), ORGY_, width);
+    }
+
+    // 消去
+    void FrqRespDrawer::Erase()
+    {
+        lcd_->SetTextColor(BACK_COLOR_);
+        uint16_t height = DB1_*(MAX_DB_ - MIN_DB_);
+        lcd_->FillRect(ORGX_, ORGY_- height, X(MAX_)-X(MIN_)+1, height+1);
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/FrquencyResponseDrawer.hpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------
+//  周波数が対数スケールの周波数特性を描画するクラス
+//  FrqRespDrawer class Header
+//
+//  2016/04/25, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef F746_FRQ_RESP_DRAWER_HPP
+#define F746_FRQ_RESP_DRAWER_HPP
+
+#include "NumericLabel.hpp"
+#include "FrequancyResponseBase.hpp"
+
+namespace Mikami
+{
+    class FrqRespDrawer
+    {
+    public:
+        // 横軸の目盛値を描画する際に使う構造体
+        struct AxisX_Char { uint16_t frq; string str; };
+        
+        // Constructor
+        FrqRespDrawer(uint16_t org, float min, float max, uint16_t dec,
+                      uint16_t orgY, float minDb, float maxDb,
+                      float db1Pixel, float ySpace, float fs,
+                      uint32_t lineColor = 0xFF00B0FF,
+                      uint32_t axisColor = LCD_COLOR_LIGHTGRAY,
+                      uint32_t backColor = GuiBase::ENUM_BACK)
+            : lcd_(GuiBase::GetLcdPtr()),
+              ORGX_(org), MIN_(min), MAX_(max), DEC_(dec),
+              ORGY_(orgY), MIN_DB_(minDb), MAX_DB_(maxDb),
+              DB1_(db1Pixel), Y_SPACE_(db1Pixel*ySpace), FS_(fs),
+              LINE_COLOR_(lineColor),
+              AXIS_COLOR_(axisColor),
+              BACK_COLOR_(backColor) {}
+
+        // 周波数に対応する x 座標値の取得
+        int X(float frq)
+        {   return Round(ORGX_ + DEC_*log10f(frq/MIN_));  }
+
+        // x 座標値を周波数に変換
+        float PosToFrq(uint16_t x)
+        {   return MIN_*powf(10.0f, (x - ORGX_)/(float)DEC_); }
+
+        // 目盛線の描画
+        void DrawAxis();
+
+        // 横軸の目盛値の表示
+        void DrawNumericX(AxisX_Char xChar[], int nDisp, int offsetY,
+                          string str, sFONT &fonts = Font12,
+                          uint32_t textColor = LCD_COLOR_WHITE);
+
+        // 縦軸の目盛値の表示
+        void DrawNumericY(int offsetX, int offsetY, uint16_t d_dB,
+                          const char fmt[], sFONT &fonts = Font12,
+                          uint32_t textColor = LCD_COLOR_WHITE,
+                          string str = "[dB]");
+
+        // 周波数特性のグラフの描画
+        void DrawGraph(FrequencyResponse *frqResp, uint32_t color);
+        void DrawGraph(FrequencyResponse *frqResp)
+        {   DrawGraph(frqResp, LINE_COLOR_);}
+
+        // 消去
+        void Erase();
+
+    private:
+        LCD_DISCO_F746NG *lcd_;
+        const uint16_t ORGX_;   // 横軸の目盛の最小値に対応する位置
+        const float MIN_;       // 横軸の目盛の最小値
+        const float MAX_;       // 横軸の目盛の最大値
+        const uint16_t DEC_;    // 周波数の 10 倍に対応する長さ (pixels)
+        const uint16_t ORGY_;   // 縦軸の目盛の最小値に対応する位置
+        const float MIN_DB_;    // 縦軸の目盛の最小値 [dB]
+        const float MAX_DB_;    // 縦軸の目盛の最大値 [dB]
+        const float DB1_;       // 1 dB に対応する pixels 数
+        const float Y_SPACE_;   // 縦軸の目盛線の間隔に対応する pixels 数
+        const float FS_;        // 標本化周波数
+        const uint32_t LINE_COLOR_;
+        const uint32_t AXIS_COLOR_;
+        const uint32_t BACK_COLOR_;
+        
+        // 丸め
+        int Round(float x) { return x + 0.5f - (x < 0); }  
+
+        // 10 のべき乗かどうかの検査
+        bool PowersOf10(float  x)
+        {   return fabsf(log10f(x) - Round(log10f(x))) < 0.01f; }
+
+        // disallow copy constructor and assignment operator
+        FrqRespDrawer(const FrqRespDrawer&);
+        FrqRespDrawer& operator=(const FrqRespDrawer&);
+    };
+}
+#endif  // F746_FRQ_RESP_DRAWER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/GrEqParamsCalculator.hpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+//  Parameters calculator class of buquad unit for graphic equalizer
+//  グラフィックイコライザで使う biquad フィルタの係数を計算するクラス
+//
+//   2016/04/27, 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 GrEqParamsCalculator
+    {
+    public:
+        // Constructor
+        GrEqParamsCalculator(float fs) : FS_(fs) {}
+
+        // 係数を計算する
+        BiquadGrEq::Coefs Execute(float f0, float gDb, float qVal)
+        {
+            const float PI = 3.1415926536f;
+            BiquadGrEq::Coefs coefs;
+            
+            float g_sqrt = sqrtf(powf(10, gDb/20.0f));
+            float w0 = 2.0f*PI*f0/FS_;
+            float alpha = sinf(w0)/(2.0f*qVal);
+            float a0 = 1.0f + alpha/g_sqrt;
+            coefs.a1 = 2.0f*cosf(w0)/a0;
+            coefs.a2 = -(1.0f - alpha/g_sqrt)/a0;
+            coefs.b0 = (1.0f + alpha*g_sqrt)/a0;
+            coefs.b1 = -coefs.a1;
+            coefs.b2 = (1.0f - alpha*g_sqrt)/a0;
+            return coefs;
+        }
+
+    private:
+        const float FS_;
+    };
+}
+#endif  // GRAPHIC_EQALIZER_PARAMETER_CALCULATOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/GrEqualizerFrqResp.hpp	Wed Apr 27 13:56:39 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	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,75 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザ付き SD オーディオプレーヤーで使う大域関数
+//
+//  2016/04/27, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "MyFunctions.hpp"
+
+// 1フレーム分の信号処理 (イコライザ) の実行
+void ProcessSignal(SD_WavReader &sdReader, SaiIO_O &mySai,
+                   int16_t sn[], BiquadGrEq hn[], int stages)
+{
+    // 1フレーム分のデータを SD から読み込む
+    sdReader.ReadAndToMono(sn, mySai.GetLength());
+
+    while (!mySai.IsXferred()) {}  // データの転送が終わるまで待つ
+    //--------------------------------------------------------------
+    // 1フレーム分のイコライザ処理を行い,その結果を出力する
+    for (int n=0; n<mySai.GetLength(); n++)
+    {
+        // 縦続形の IIR フィルタ実行
+        float yn = sn[n];
+        for (int k=0; k<stages; k++) yn = hn[k].Execute(yn);
+        int16_t value = (int16_t)yn;
+        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)
+{
+    msg.Draw("Select file");
+    selector.DisplayFileList();   
+    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 &reset)
+{
+    if (reset.Touched())
+    {
+        drawerObj.DesignAndRedraw();
+        for (int n=0; n<drawerObj.GetStages(); n++)
+            hn[n] = BiquadGrEq(drawerObj.GetCoefficient(n));
+        myBars.DrawAll(0);  // ツマミの位置を 0 dB に設定する
+        reset.Draw();
+        return;
+    }
+    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	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,37 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザ付き SD オーディオプレーヤーで使う大域関数(ヘッダ)
+//
+//  2016/04/27, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#ifndef F746_MY_FUNCTIONS_HPP
+#define F746_MY_FUNCTIONS_HPP
+
+#include "SAI_Output.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 ProcessSignal(SD_WavReader &sdReader, SaiIO_O &mySai,
+                   int16_t sn[], BiquadGrEq hn[], int stages);
+
+// 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 &reset);
+
+#endif  // F746_MY_FUNCTIONS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/SAI_Output.cpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,82 @@
+//-----------------------------------------------------------
+//  SiaIO class for output
+//  2016/04/20, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#include "SAI_Output.hpp"
+
+namespace Mikami
+{
+    SaiIO_O::SaiIO_O(int size, int fs) : FS_(fs), tmpIndex_(0)
+    {
+        nData_ = size;
+        bufferSize_ = (size*2)*2;
+        outBuffer_ = new int16_t[(size*2)*2];
+        tmp_ = new int16_t[size*2];
+        xferred_ = false;
+    }
+    SaiIO_O::~SaiIO_O()
+    {
+        delete[] tmp_;
+        delete[] outBuffer_;
+    }
+
+    void SaiIO_O::InitCodecOut()
+    {
+        if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, VOLUME_OUT_, FS_) == AUDIO_ERROR)
+            ErrorTrap();
+        for (int n=0; n<bufferSize_; n++) outBuffer_[n] = 0;
+        for (int n=0; n<nData_*2; n++) tmp_[n] = 0;
+
+        NVIC_SetVector(AUDIO_OUT_SAIx_DMAx_IRQ, (uint32_t)AUDIO_OUT_SAIx_DMAx_IRQHandler);
+        BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
+
+        if (BSP_AUDIO_OUT_Play((uint16_t *)outBuffer_,
+                               bufferSize_*AUDIODATA_SIZE) == AUDIO_ERROR)
+            ErrorTrap();
+    }
+
+    bool SaiIO_O::IsXferred()
+    {
+        if (xferred_)
+        {
+            tmpIndex_ = 0;
+            return true;
+        }
+        else
+            return false;
+    }
+
+    void SaiIO_O::Output(int16_t xL, int16_t xR)
+    {
+        tmp_[tmpIndex_++] = xL; // Left
+        tmp_[tmpIndex_++] = xR; // Right
+    }
+    
+    void SaiIO_O::ErrorTrap()
+    {
+        DigitalOut led1(LED1);
+        fprintf(stderr, "\r\n### ERROR\r\n");
+        while(true)
+        {
+            led1 = !led1;
+            wait_ms(250);
+        }
+    }
+
+    void SaiIO_O::FillBuffer(uint32_t offset)
+    {
+        int k = offset;
+        for (int n=0; n<nData_*2; n++)
+             outBuffer_[k++] = tmp_[n];
+        xferred_ = true;
+    }
+
+    // Instances for static variables
+    int32_t SaiIO_O::nData_;
+    int32_t SaiIO_O::bufferSize_;
+    int16_t* SaiIO_O::outBuffer_;
+    int16_t* SaiIO_O::tmp_;       
+    __IO bool SaiIO_O::xferred_;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/SAI_Output.hpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,60 @@
+//-----------------------------------------------------------
+//  SiaIO class for output (Header)
+//  2016/04/20, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef F746_SAI_IO_HPP
+#define F746_SAI_IO_HPP
+
+#include "mbed.h"
+#include "stm32746g_discovery_audio.h"
+#include "BSP_AudioOut_Overwrite.hpp"
+
+namespace Mikami
+{
+    class SaiIO_O
+    {
+    public:
+        SaiIO_O(int size, int fs);
+        ~SaiIO_O();
+
+        void InitCodecOut();
+        
+        bool IsXferred();
+        void Output(int16_t xL, int16_t xR);
+        
+        void ResetXferred() { xferred_ = false; }
+        int32_t GetLength() { return nData_; }
+        void Stop()   { BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW); }
+        void Pause()  { BSP_AUDIO_OUT_Pause(); }
+        void Resume() { BSP_AUDIO_OUT_Resume(); }
+
+        
+        // These three member functions are called from
+        // callback functions in "BSP_AudioOut_Overwrite.cpp"
+
+        // Called form BSP_AUDIO_OUT_HalfTransfer_CallBack()
+        static void FillBuffer1st() { FillBuffer(0); }
+        // Called form BSP_AUDIO_OUT_TransferComplete_CallBack()
+        static void FillBuffer2nd() { FillBuffer(bufferSize_/2); }
+        // Also called form BSP_AUDIO_OUT_Error_CallBack()
+        static void ErrorTrap();
+
+    private:
+        const int FS_;
+        static const uint8_t VOLUME_OUT_ = 90;
+
+        static int32_t nData_;
+        static int32_t bufferSize_;
+
+        static int16_t* outBuffer_;
+        static int16_t* tmp_;       
+
+        static __IO bool xferred_;
+        
+        __IO int32_t tmpIndex_;
+
+        static void FillBuffer(uint32_t offset);
+    };
+}
+#endif  // F746_SAI_IO_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MyClasses_Functions/SD_WavReader.cpp	Wed Apr 27 13:56:39 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	Wed Apr 27 13:56:39 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem_Warning_Fixed.lib	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/MikamiUitOpen/code/SDFileSystem_Warning_Fixed/#225138ac03fd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TS_DISCO_F746NG.lib	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ST/code/TS_DISCO_F746NG/#fe0cf5e2960f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,156 @@
+//--------------------------------------------------------------
+//  グラフィックイコライザ付き SD オーディオプレーヤー
+//      SD のファイル: *.wav
+//                   PCM,16 ビットステレオ,標本化周波数 44.1 kHz
+//                   上記以外の形式は扱わない
+//      出力:モノラル
+//
+//  2016/04/27, Copyright (c) 2016 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "MyFunctions.hpp"
+#include "BlinkLabel.hpp"
+
+using namespace Mikami;
+
+int main()
+{
+    Label myLabel(80, 4, "SD Card Audio Player 16:36", Label::LEFT, Font16);
+
+    const int FS = AUDIO_FREQUENCY_44K;         // 標本化周波数: 44.1 kHz
+    SaiIO_O mySai(2048, FS);
+
+    SD_WavReader sdReader(mySai.GetLength());   // SD カード読み込み用オブジェクト
+    const int MAX_FILES = 7;
+    FileSelector selector(4, 28, MAX_FILES, 38, sdReader);
+    if (!selector.CreateTable())
+        BlinkLabel errLabel(240, 100, "SD CARD ERROR", Label::CENTER);
+
+    // ボタン用の定数
+    const uint16_t BG_LEFT = 420;
+    const uint16_t BG_WIDTH = 60;
+    const uint16_t BG_HEIGHT = 40;
+
+    // ButtonGroup: "OPEN", "PLAY", "PAUSE", "RESUME", "STOP"
+    const string MENU[5] = {"OPEN", "PLAY", "PAUSE", "RESUME", "STOP"};
+    ButtonGroup menu(BG_LEFT, 2, BG_WIDTH, BG_HEIGHT,
+                     5, MENU, 0, 2, 1);
+    // OPEN のみアクティブ
+    menu.Activate(0);
+    for (int n=1; n<5; n++) menu.Inactivate(n);
+
+    Button flatButton(BG_LEFT, 230, BG_WIDTH, BG_HEIGHT, "FLAT");
+
+    // フィルタの設計と周波数特性描画用
+    const int STAGES = 9;       // バンド数
+    DesignerDrawer drawerObj(
+                     30,        // グラフの左端の位置
+                     130,       // グラフの下端の位置
+                     STAGES,    // バンド数
+                     62.5f,     // 最低域バンドの中心周波数
+                     FS,        // 標本化周波数
+                     4);        // 1 dB 当たりのピクセル数
+
+    // 周波数特性変更用スライダ
+    SeekbarGroup myBars(drawerObj.GetX0(), 186, 66, STAGES,
+                        drawerObj.GetSpaceX(), -8, 8, 0,
+                        SeekBar::Vertical);
+
+    // フィルタの準備
+    BiquadGrEq::Coefs ck[STAGES];
+    drawerObj.GetCoefficients(ck);
+    BiquadGrEq hn[STAGES];
+    for (int k=0; k<STAGES; k++) hn[k] = BiquadGrEq(ck[k]);
+
+    int32_t frameSize = mySai.GetLength();
+    int16_t *sn = new int16_t[frameSize+1]; // フレームバッファ
+    bool playOk = false;
+    bool whileFirst = true;
+    string fileName;
+    int32_t loopCount;
+
+    while (true)
+    {
+        if (!playOk)
+        {
+            if (whileFirst)
+            {
+                whileFirst = false;
+                while (!menu.Touched(0))    // OPEN がタッチされるまで待つ
+                    ModifyFilter(drawerObj, myBars, hn, flatButton);
+                SelectFile(menu, selector, myLabel, fileName);
+            }
+            else
+            {
+                menu.Activate(1);       // PLAY 有効
+                int touch10;
+                while (!menu.GetTouchedNumber(touch10))
+                    ModifyFilter(drawerObj, myBars, hn, flatButton);
+                if (touch10 == 0)
+                    SelectFile(menu, selector, myLabel, fileName);
+            }
+
+            loopCount = SD_Open(sdReader, fileName, frameSize);
+            while (!menu.Touched(1))   // PLAY がタッチされるまで待つ
+                ModifyFilter(drawerObj, myBars, hn, flatButton);
+        }
+        else
+            loopCount = SD_Open(sdReader, fileName, frameSize);
+
+        selector.Erase(BG_LEFT-4, 288);
+        myLabel.Draw("9-band Graphic Equalizer");
+        myBars.RedrawAll();
+        drawerObj.DrawResponse();
+        menu.Inactivate(0); // OPEN 無効
+        menu.Activate(2);   // PAUSE 有効
+        menu.Activate(4);   // STOP 有効
+
+        playOk = false;
+        bool stopOk = false;
+        mySai.InitCodecOut();   // SAI の初期化
+
+        // IIR フィルタの内部の遅延器のクリア
+        for (int k=0; k<STAGES; k++) hn[k].Clear();
+
+        for (int k=0; k<loopCount; k++)
+        {
+            int touch42 = -1;
+            menu.GetTouchedNumber(touch42);
+            if (touch42 == 4) break;    // STOP
+            if (touch42 == 2)           // PAUSE
+            {
+                menu.Inactivate(2); // PAUSE 無効
+                menu.Activate(3);   // RESUME 有効
+                mySai.Pause();
+
+                // PLAY か RESUME か STOP がタッチされるまで待つ
+                int touch134 = -1;
+                while (!menu.GetTouchedNumber(touch134))
+                    ModifyFilter(drawerObj, myBars, hn, flatButton);
+                switch (touch134)
+                {
+                    case 1: playOk = true;  // 最初から PLAY
+                            break;
+                    case 3: mySai.Resume(); // PAUSE したところから PLAY 再開
+                            menu.Activate(2);
+                            menu.Inactivate(3);
+                            menu.TouchedColor(1);
+                            break;
+                    case 4: stopOk = true;  // STOP
+                            break;
+                }
+            }
+            if (playOk || stopOk) break;
+
+            ModifyFilter(drawerObj, myBars, hn, flatButton);
+            // 1フレーム分の信号処理 (イコライザ) の実行
+            ProcessSignal(sdReader, mySai, sn, hn, STAGES);
+        }
+        mySai.Stop();
+        menu.Activate(0);               // OPEN 有効
+        if (!playOk) menu.Activate(1);  // PLAY 有効
+        for (int n=2; n<5; n++)         // その他は無効
+            menu.Inactivate(n);
+        sdReader.Close();   // SD のファイルのクローズ
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Apr 27 13:56:39 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/082adc85693f
\ No newline at end of file