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 不韋 呂

main.cpp

Committer:
edamame22
Date:
2016-06-22
Revision:
10:fc6367c2ffcf
Parent:
9:0d5bd1539291
Child:
12:87f6955b5a80

File content as of revision 10:fc6367c2ffcf:

//--------------------------------------------------------------
//  グラフィックイコライザ付き SD オーディオプレーヤー
//      SD のファイル: *.wav
//                   PCM,16 ビットステレオ,標本化周波数 44.1 kHz
//                   上記以外の形式は扱わない
//      出力:モノラル
//
//  2016/05/09, Copyright (c) 2016 MIKAMI, Naoki
//--------------------------------------------------------------

#include "MyFunctions.hpp"
#include "BlinkLabel.hpp"

using namespace Mikami;
enum ts_State {
    IDLE_NOPALY, SELECTED_PREPARE_PALY, PALYING, PAUSED, STOPPED, RESUMED
};

int main()
{
    Label myLabel1(212, 2, "SD Card Audio Player", Label::CENTER, Font16);
    Label myLabel2(212, 16, "---- Graphic equalizer ----", Label::CENTER, Font12);

    const int FS = AUDIO_FREQUENCY_44K;         // 標本化周波数: 44.1 kHz
    SaiIO mySai(SaiIO::OUTPUT, 2048, FS);

    SD_WavReader sdReader(mySai.GetLength());   // SD カード読み込み用オブジェクト
    const int MAX_FILES = 7;
    string PlayList[MAX_FILES];
    int list_id = 0;
    FileSelector selector(4, 26, MAX_FILES, 37, sdReader);
    if (!selector.CreateTable())
        BlinkLabel errLabel(240, 100, "SD CARD ERROR", Label::CENTER);

    // ボタン用の定数
    const uint16_t BG_LEFT = 414;
    const uint16_t BG_WIDTH = 66;
    const uint16_t BG_HEIGHT = 36;

    // 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);
//    printf("Button flat with 0 expanded detection Area\n");
    Button flat(BG_LEFT, 197, BG_WIDTH, BG_HEIGHT, 0, "FLAT");

    const string ON_OFF[2] = {"ON", "OFF"};
    ButtonGroup onOff(BG_LEFT, 235, BG_WIDTH/2, BG_HEIGHT,
                      2, ON_OFF, 0, 0, 2, 0);

    // フィルタの設計と周波数特性描画用
    const int STAGES = 9;       // バンド数
    DesignerDrawer drawerObj(
        28,        // グラフの左端の位置
        130,       // グラフの下端の位置
        STAGES,    // バンド数
        62.5f,     // 最低域バンドの中心周波数
        FS,        // 標本化周波数
        2.5f);     // 1 dB 当たりのピクセル数

    // 周波数特性変更用スライダ
    SeekbarGroup myBars(drawerObj.GetX0(), 178, 82, STAGES,
                        drawerObj.GetSpaceX(), -8.0f, 8.0f, 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 on = true;
    string fileName;
    int32_t loopCount;
    ts_State ui_mode = IDLE_NOPALY;
    int k;
    while (true) {
        switch(ui_mode) {
            case IDLE_NOPALY:
                while (!menu.Touched(0))    // OPEN がタッチされるまで待つ
                    ModifyFilter(drawerObj, myBars, hn, flat, onOff, on);
                for(int m=0; m<MAX_FILES; m++)  PlayList[m]="";      // clear playlist
                SelectFile(menu, selector, myLabel1, PlayList, &list_id);   // returned playlist and selected ID
                ui_mode = SELECTED_PREPARE_PALY ;
            case SELECTED_PREPARE_PALY:
            printf(" current track is %s  ******\n", PlayList[list_id].c_str());
                loopCount = SD_Open(sdReader, PlayList[list_id], frameSize);
                // while (!menu.Touched(1))   // PLAY がタッチされるまで待つ
                //     ModifyFilter(drawerObj, myBars, hn, flat, onOff, on);
                selector.Erase(0, 0, BG_LEFT-4, 288);
                myLabel1.Draw("9-band Graphic Equalizer");
                myBars.RedrawAll();
                drawerObj.DrawResponse();
                menu.Inactivate(0); // OPEN 無効
                menu.Activate(2);   // PAUSE 有効
                menu.Activate(4);   // STOP 有効
                // IIR フィルタの内部の遅延器のクリア
                for (int j=0; j<STAGES; j++) hn[j].Clear();
                mySai.PlayOut();    // Play 開始
                ui_mode = PALYING ;
                k=0;
            case PALYING:
                for (; k<loopCount && ui_mode==PALYING; k++) {
                    int touch42 = -1;
                    menu.GetTouchedNumber(touch42);
                    if (touch42 == 4)     ui_mode = STOPPED;      // STOP
                    else if (touch42 == 2)   ui_mode = PAUSED;    // PAUSE
                    ModifyFilter(drawerObj, myBars, hn, flat, onOff, on);
                    // 1フレーム分の信号処理 (イコライザ) の実行
                    SignalProcessing(sdReader, mySai, sn, hn, STAGES, on);
                }
                if(ui_mode == PAUSED)   break;   // Paused 
                mySai.StopOut();    // current track play ended
                sdReader.Close();   // SD のファイルのクローズ
                if(ui_mode == STOPPED)   break;   // Stopped 
                
                if (list_id < MAX_FILES-1) {  // goto next track
                    if (PlayList[list_id+1].empty())   list_id=0;
                    else  list_id++;
                } else list_id=0;
                ui_mode = SELECTED_PREPARE_PALY;
                break;
            case PAUSED: {
                menu.Inactivate(2); // PAUSE 無効
                menu.Activate(3);   // RESUME 有効
                mySai.PauseOut();
                // PLAY か RESUME か STOP がタッチされるまで待つ
                int touch134 = -1;
                while (!menu.GetTouchedNumber(touch134))
                    ModifyFilter(drawerObj, myBars, hn, flat, onOff, on);
                if(touch134 == 3) {
                    ui_mode = RESUMED;
                    break;  // PAUSE したところから PLAY 再開
                }
                mySai.ResumeOut();  // PAUSE したところから PLAY 再開 またはSTOPの後処理
                mySai.StopOut();
                sdReader.Close();   // SD のファイルのクローズ

                if(touch134 == 4) {
                    ui_mode = STOPPED;      break;    // STOP
                }
                if(touch134 == 1) {
                    ui_mode = SELECTED_PREPARE_PALY;      // 最初から PLAY
                    menu.Inactivate(3);      // RESUME disable to start play
                    break;
                }
                printf("a very bad wrong point\n");
                break;
            }
            case STOPPED:
                menu.Activate(0);               // OPEN 有効
                menu.Activate(1);               // PLAY 有効
                for (int n=2; n<5; n++)         // その他は無効
                    menu.Inactivate(n);
                int touch10;
                while (!menu.GetTouchedNumber(touch10))
                    ModifyFilter(drawerObj, myBars, hn, flat, onOff, on);
                if (touch10 == 0)
                    SelectFile(menu, selector, myLabel1, PlayList, &list_id);
                ui_mode = SELECTED_PREPARE_PALY;
                break;
            case RESUMED:
                mySai.ResumeOut();  // PAUSE したところから PLAY 再開
                menu.Activate(2);
                menu.Inactivate(3);
                menu.TouchedColor(1);
                ui_mode = PALYING;
                break;
        }
    }
}