Output the audio signal with filtering by IIR filter in the *.wav file on the SD card using onboard CODEC. SD カードの *.wav ファイルのオーディオ信号を遮断周波数可変の IIR フィルタを通して,ボードに搭載されているCODEC で出力する.

Dependencies:   BSP_DISCO_F746NG F746_GUI LCD_DISCO_F746NG SDFileSystem_Warning_Fixed TS_DISCO_F746NG mbed FrequencyResponseDrawer F746_SAI_IO Array_Matrix

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //--------------------------------------------------------------
00002 //  フィルタ処理付き SD オーディオプレーヤー
00003 //      SD のファイル: *.wav
00004 //                   PCM,16 ビットステレオ,標本化周波数 44.1 kHz
00005 //      IIR フィルタ ---- 低域通過および高域通過フィルタ
00006 //      出力:モノラル(L+R,左チャンネルのみ,右チャンネルには出力しない)
00007 //
00008 //  2016/07/04, Copyright (c) 2016 MIKAMI, Naoki
00009 //--------------------------------------------------------------
00010 
00011 #include "MyFunctions.hpp"
00012 #include "BlinkLabel.hpp"
00013 
00014 using namespace Mikami;
00015 
00016 int main()
00017 {
00018     Label myLabel1(200, 4, "Variable LPF and HPF 15:02", Label::CENTER, Font16);
00019     Label myLabel2(200, 20, "---- Source: microSD card ----", Label::CENTER, Font12);
00020 
00021     const int FS = AUDIO_FREQUENCY_44K;         // 標本化周波数: 44.1 kHz
00022     SaiIO mySai(SaiIO::OUTPUT, 2048, FS);
00023 
00024     SD_WavReader sdReader(mySai.GetLength());   // SD カード読み込み用オブジェクト
00025     const int MAX_FILES = 7;
00026     FileSelector selector(4, 22, MAX_FILES, 34, sdReader);
00027     if (!selector.CreateTable())
00028         BlinkLabel errLabel(240, 100, "SD CARD ERROR", Label::CENTER);
00029 
00030     // ボタン用の定数
00031     const uint16_t BG_LEFT = 390;
00032     const uint16_t BG_WIDTH = 80;
00033     const uint16_t BG_HEIGHT = 36;
00034 
00035     // ButtonGroup: "OPEN", "PLAY", "PAUSE", "RESUME", "STOP"
00036     const string MENU[5] = {"OPEN", "PLAY", "PAUSE", "RESUME", "STOP"};
00037     ButtonGroup menu(BG_LEFT, 2, BG_WIDTH, BG_HEIGHT,
00038                      5, MENU, 0, 2, 1);
00039     // OPEN のみアクティブ
00040     menu.Activate(0);
00041     for (int n=1; n<5; n++) menu.Inactivate(n);
00042 
00043     // ButtonGroup: "LPF", "HPF"
00044     const string LP_HP[2] = {"LPF", "HPF"};
00045     ButtonGroup lpHp(BG_LEFT, 197, BG_WIDTH/2, BG_HEIGHT,
00046                      2, LP_HP, 0, 0, 2, 0);
00047 
00048     // ButtonGroup: "ON", "OFF"
00049     const string ON_OFF[2] = {"ON", "OFF"};
00050     ButtonGroup onOff(BG_LEFT, 235, BG_WIDTH/2, BG_HEIGHT,
00051                       2, ON_OFF, 0, 0, 2, 1);
00052 
00053     // フィルタの設計と周波数特性描画用
00054     const int ORDER = 6;        // フィルタの次数
00055     DesignerDrawer drawerObj(
00056                      40,        // グラフの左端の位置
00057                      238,       // グラフの下端の位置
00058                      3,         // 1 dB 当たりのピクセル数
00059                      FS,        // 標本化周波数
00060                      ORDER,     // フィルタの次数
00061                      400,       // 最初に与える遮断周波数
00062                      200,       // 遮断周波数の最小値
00063                      10000,     // 遮断周波数の最大値
00064                      BilinearDesign::LPF);  // 低域通過フィルタ
00065 
00066     // フィルタの準備
00067     Biquad::Coefs ck[ORDER/2];
00068     float g0;
00069     drawerObj.GetCoefficients(ck, g0);
00070     Biquad hn[ORDER/2];
00071     for (int k=0; k<ORDER/2; k++) hn[k] = Biquad(ck[k]);
00072 
00073     int32_t frameSize = mySai.GetLength();
00074     bool playOk = false;
00075     bool filterOn = false;
00076     bool whileFirst = true;
00077     string fileName;
00078     int32_t loopCount;
00079 
00080     while (true)
00081     {
00082         if (!playOk)
00083         {
00084             if (whileFirst)
00085             {
00086                 whileFirst = false;
00087                 while (!menu.Touched(0))    // OPEN がタッチされるまで待つ
00088                     ModifyFilter(drawerObj, lpHp, onOff,
00089                                  hn, ck, g0, filterOn);
00090                 SelectFile(menu, selector, myLabel1, fileName);
00091             }
00092             else
00093             {
00094                 menu.Activate(1);       // PLAY 有効
00095                 int touch10;
00096                 while (!menu.GetTouchedNumber(touch10))
00097                     ModifyFilter(drawerObj, lpHp, onOff,
00098                                  hn, ck, g0, filterOn);
00099                 if (touch10 == 0)
00100                     SelectFile(menu, selector, myLabel1, fileName);
00101             }
00102 
00103             loopCount = SD_Open(sdReader, fileName, frameSize);
00104             while (!menu.Touched(1))    // PLAY がタッチされるまで待つ
00105                 ModifyFilter(drawerObj, lpHp, onOff,
00106                              hn, ck, g0, filterOn);
00107         }
00108         else
00109             loopCount = SD_Open(sdReader, fileName, frameSize);
00110 
00111         selector.Erase(0, 0, BG_LEFT-4, 272);
00112         myLabel1.Draw();
00113         drawerObj.DrawResponse();
00114         menu.Inactivate(0); // OPEN 無効
00115         menu.Activate(2);   // PAUSE 有効
00116         menu.Activate(4);   // STOP 有効
00117 
00118         playOk = false;
00119         bool stopOk = false;
00120 
00121         // IIR フィルタの内部の遅延器のクリア
00122         for (int k=0; k<ORDER/2; k++) hn[k].Clear();
00123         mySai.PlayOut();    // Play 開始
00124 
00125         for (int k=0; k<loopCount; k++)
00126         {
00127             int touch42 = -1;
00128             menu.GetTouchedNumber(touch42);
00129             if (touch42 == 4) break;    // STOP
00130             if (touch42 == 2)           // PAUSE
00131             {
00132                 menu.Inactivate(2); // PAUSE 無効
00133                 menu.Activate(3);   // RESUME 有効
00134                 mySai.PauseOut();
00135 
00136                 // PLAY か RESUME か STOP がタッチされるまで待つ
00137                 int touch134 = -1;
00138                 while (!menu.GetTouchedNumber(touch134))
00139                     ModifyFilter(drawerObj, lpHp, onOff,
00140                                  hn, ck, g0, filterOn);
00141                 switch (touch134)
00142                 {
00143                     case 1: playOk = true;      // 最初から PLAY
00144                             break;
00145                     case 3: mySai.ResumeOut();  // PAUSE したところから PLAY 再開
00146                             menu.Activate(2);
00147                             menu.Inactivate(3);
00148                             menu.TouchedColor(1);
00149                             break;
00150                     case 4: stopOk = true;      // STOP
00151                             break;
00152                 }
00153             }
00154             if (playOk || stopOk) break;
00155 
00156             ModifyFilter(drawerObj, lpHp, onOff, hn, ck, g0, filterOn);
00157             // 1フレーム分の信号処理 (IIR フィルタ) の実行
00158             IIR_Filtering(sdReader, mySai, g0, hn, ORDER, filterOn);
00159         }
00160         mySai.StopOut();
00161         menu.Activate(0);               // OPEN 有効
00162         if (!playOk) menu.Activate(1);  // PLAY 有効
00163         for (int n=2; n<5; n++)         // その他は無効
00164             menu.Inactivate(n);
00165         sdReader.Close();   // SD のファイルのクローズ
00166     }
00167 }