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

Committer:
MikamiUitOpen
Date:
Tue Apr 19 09:46:11 2016 +0000
Revision:
0:04b43b777fae
Child:
1:cc2669b9d1e2
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:04b43b777fae 1 //--------------------------------------------------------------
MikamiUitOpen 0:04b43b777fae 2 // フィルタ処理付き SD オーディオプレーヤー
MikamiUitOpen 0:04b43b777fae 3 // SD のファイル: *.wav
MikamiUitOpen 0:04b43b777fae 4 // PCM,16 ビットステレオ,標本化周波数 44.1 kHz
MikamiUitOpen 0:04b43b777fae 5 // IIR フィルタ ---- 低域通過および高域通過フィルタ
MikamiUitOpen 0:04b43b777fae 6 //
MikamiUitOpen 0:04b43b777fae 7 // 2016/04/19, Copyright (c) 2016 MIKAMI, Naoki
MikamiUitOpen 0:04b43b777fae 8 //--------------------------------------------------------------
MikamiUitOpen 0:04b43b777fae 9
MikamiUitOpen 0:04b43b777fae 10 #include "MyFunctions.hpp"
MikamiUitOpen 0:04b43b777fae 11 #include "BlinkLabel.hpp"
MikamiUitOpen 0:04b43b777fae 12
MikamiUitOpen 0:04b43b777fae 13 using namespace Mikami;
MikamiUitOpen 0:04b43b777fae 14
MikamiUitOpen 0:04b43b777fae 15 int main()
MikamiUitOpen 0:04b43b777fae 16 {
MikamiUitOpen 0:04b43b777fae 17 Label myLabel(80, 4, "SD Card Audio Player", Label::LEFT, Font16);
MikamiUitOpen 0:04b43b777fae 18
MikamiUitOpen 0:04b43b777fae 19 const int FS = AUDIO_FREQUENCY_44K; // 標本化周波数: 44.1 kHz
MikamiUitOpen 0:04b43b777fae 20 SaiIO_O mySai(2048, FS);
MikamiUitOpen 0:04b43b777fae 21
MikamiUitOpen 0:04b43b777fae 22 SD_WavReader sdReader(mySai.GetLength()); // SD カード読み込み用オブジェクト
MikamiUitOpen 0:04b43b777fae 23 const int MAX_FILES = 7;
MikamiUitOpen 0:04b43b777fae 24 FileSelector selector(4, 28, MAX_FILES, 34, sdReader);
MikamiUitOpen 0:04b43b777fae 25 if (!selector.CreateTable())
MikamiUitOpen 0:04b43b777fae 26 BlinkLabel errLabel(240, 100, "SD CARD ERROR", Label::CENTER);
MikamiUitOpen 0:04b43b777fae 27
MikamiUitOpen 0:04b43b777fae 28 // ボタン用の定数
MikamiUitOpen 0:04b43b777fae 29 const uint16_t BG_LEFT = 390;
MikamiUitOpen 0:04b43b777fae 30 const uint16_t BG_WIDTH = 80;
MikamiUitOpen 0:04b43b777fae 31 const uint16_t BG_HEIGHT = 36;
MikamiUitOpen 0:04b43b777fae 32
MikamiUitOpen 0:04b43b777fae 33 // ButtonGroup: "OPEN", "PLAY", "PAUSE", "RESUME", "STOP"
MikamiUitOpen 0:04b43b777fae 34 const string MENU[5] = {"OPEN", "PLAY", "PAUSE", "RESUME", "STOP"};
MikamiUitOpen 0:04b43b777fae 35 ButtonGroup menu(BG_LEFT, 2, BG_WIDTH, BG_HEIGHT,
MikamiUitOpen 0:04b43b777fae 36 5, MENU, 0, 2, 1);
MikamiUitOpen 0:04b43b777fae 37 // OPEN のみアクティブ
MikamiUitOpen 0:04b43b777fae 38 menu.Activate(0);
MikamiUitOpen 0:04b43b777fae 39 for (int n=1; n<5; n++) menu.Inactivate(n);
MikamiUitOpen 0:04b43b777fae 40
MikamiUitOpen 0:04b43b777fae 41 // ButtonGroup: "LPF", "HPF"
MikamiUitOpen 0:04b43b777fae 42 const string LP_HP[2] = {"LPF", "HPF"};
MikamiUitOpen 0:04b43b777fae 43 ButtonGroup lpHp(BG_LEFT, 197, BG_WIDTH/2, BG_HEIGHT,
MikamiUitOpen 0:04b43b777fae 44 2, LP_HP, 0, 0, 2, 0);
MikamiUitOpen 0:04b43b777fae 45
MikamiUitOpen 0:04b43b777fae 46 // ButtonGroup: "ON", "OFF"
MikamiUitOpen 0:04b43b777fae 47 const string ON_OFF[2] = {"ON", "OFF"};
MikamiUitOpen 0:04b43b777fae 48 ButtonGroup onOff(BG_LEFT, 235, BG_WIDTH/2, BG_HEIGHT,
MikamiUitOpen 0:04b43b777fae 49 2, ON_OFF, 0, 0, 2, 1);
MikamiUitOpen 0:04b43b777fae 50
MikamiUitOpen 0:04b43b777fae 51 // フィルタの設計と周波数特性描画用
MikamiUitOpen 0:04b43b777fae 52 const int ORDER = 6; // フィルタの次数
MikamiUitOpen 0:04b43b777fae 53 DesignerDrawer drawerObj(
MikamiUitOpen 0:04b43b777fae 54 45, // グラフの左端の位置
MikamiUitOpen 0:04b43b777fae 55 230, // グラフの下端の位置
MikamiUitOpen 0:04b43b777fae 56 30, // 10 dB 当たりのピクセル数
MikamiUitOpen 0:04b43b777fae 57 FS, // 標本化周波数
MikamiUitOpen 0:04b43b777fae 58 ORDER, // フィルタの次数
MikamiUitOpen 0:04b43b777fae 59 400, // 最初に与える遮断周波数
MikamiUitOpen 0:04b43b777fae 60 200, // 遮断周波数の最小値
MikamiUitOpen 0:04b43b777fae 61 10000, // 遮断周波数の最大値
MikamiUitOpen 0:04b43b777fae 62 BilinearDesign::LPF); // 低域通過フィルタ
MikamiUitOpen 0:04b43b777fae 63
MikamiUitOpen 0:04b43b777fae 64 // フィルタの準備
MikamiUitOpen 0:04b43b777fae 65 Biquad::Coefs ck[ORDER/2];
MikamiUitOpen 0:04b43b777fae 66 float g0;
MikamiUitOpen 0:04b43b777fae 67 drawerObj.GetCoefficients(ck, g0);
MikamiUitOpen 0:04b43b777fae 68 Biquad hn[ORDER/2];
MikamiUitOpen 0:04b43b777fae 69 for (int k=0; k<ORDER/2; k++) hn[k] = Biquad(ck[k]);
MikamiUitOpen 0:04b43b777fae 70
MikamiUitOpen 0:04b43b777fae 71 int32_t frameSize = mySai.GetLength();
MikamiUitOpen 0:04b43b777fae 72 int16_t *sn = new int16_t[frameSize+1]; // フレームバッファ
MikamiUitOpen 0:04b43b777fae 73 bool playOk = false;
MikamiUitOpen 0:04b43b777fae 74 bool filterOn = false;
MikamiUitOpen 0:04b43b777fae 75 bool whileFirst = true;
MikamiUitOpen 0:04b43b777fae 76 string fileName;
MikamiUitOpen 0:04b43b777fae 77 int32_t loopCount;
MikamiUitOpen 0:04b43b777fae 78
MikamiUitOpen 0:04b43b777fae 79 while (true)
MikamiUitOpen 0:04b43b777fae 80 {
MikamiUitOpen 0:04b43b777fae 81 if (!playOk)
MikamiUitOpen 0:04b43b777fae 82 {
MikamiUitOpen 0:04b43b777fae 83 if (whileFirst)
MikamiUitOpen 0:04b43b777fae 84 {
MikamiUitOpen 0:04b43b777fae 85 whileFirst = false;
MikamiUitOpen 0:04b43b777fae 86 while (!menu.Touched(0)) // OPEN がタッチされるまで待つ
MikamiUitOpen 0:04b43b777fae 87 ModifyFilter(drawerObj, lpHp, onOff,
MikamiUitOpen 0:04b43b777fae 88 hn, ck, g0, filterOn);
MikamiUitOpen 0:04b43b777fae 89 SelectFile(menu, selector, myLabel, fileName);
MikamiUitOpen 0:04b43b777fae 90 }
MikamiUitOpen 0:04b43b777fae 91 else
MikamiUitOpen 0:04b43b777fae 92 {
MikamiUitOpen 0:04b43b777fae 93 menu.Activate(1); // PLAY 有効
MikamiUitOpen 0:04b43b777fae 94 int touch10;
MikamiUitOpen 0:04b43b777fae 95 while (!menu.GetTouchedNumber(touch10))
MikamiUitOpen 0:04b43b777fae 96 ModifyFilter(drawerObj, lpHp, onOff,
MikamiUitOpen 0:04b43b777fae 97 hn, ck, g0, filterOn);
MikamiUitOpen 0:04b43b777fae 98 if (touch10 == 0)
MikamiUitOpen 0:04b43b777fae 99 SelectFile(menu, selector, myLabel, fileName);
MikamiUitOpen 0:04b43b777fae 100 }
MikamiUitOpen 0:04b43b777fae 101
MikamiUitOpen 0:04b43b777fae 102 loopCount = SD_Open(sdReader, fileName, frameSize);
MikamiUitOpen 0:04b43b777fae 103 while (!menu.Touched(1)) // PLAY がタッチされるまで待つ
MikamiUitOpen 0:04b43b777fae 104 ModifyFilter(drawerObj, lpHp, onOff,
MikamiUitOpen 0:04b43b777fae 105 hn, ck, g0, filterOn);
MikamiUitOpen 0:04b43b777fae 106 }
MikamiUitOpen 0:04b43b777fae 107 else
MikamiUitOpen 0:04b43b777fae 108 loopCount = SD_Open(sdReader, fileName, frameSize);
MikamiUitOpen 0:04b43b777fae 109
MikamiUitOpen 0:04b43b777fae 110 selector.Erase(BG_LEFT-4, 244);
MikamiUitOpen 0:04b43b777fae 111 myLabel.Draw("IIR Butterworth filter");
MikamiUitOpen 0:04b43b777fae 112 drawerObj.DrawResponse();
MikamiUitOpen 0:04b43b777fae 113 menu.Inactivate(0); // OPEN 無効
MikamiUitOpen 0:04b43b777fae 114 menu.Activate(2); // PAUSE 有効
MikamiUitOpen 0:04b43b777fae 115 menu.Activate(4); // STOP 有効
MikamiUitOpen 0:04b43b777fae 116
MikamiUitOpen 0:04b43b777fae 117 playOk = false;
MikamiUitOpen 0:04b43b777fae 118 bool stopOk = false;
MikamiUitOpen 0:04b43b777fae 119 mySai.InitCodecOut(); // SAI の初期化
MikamiUitOpen 0:04b43b777fae 120
MikamiUitOpen 0:04b43b777fae 121 // IIR フィルタの内部の遅延器のクリア
MikamiUitOpen 0:04b43b777fae 122 for (int k=0; k<ORDER/2; k++) hn[k].Clear();
MikamiUitOpen 0:04b43b777fae 123
MikamiUitOpen 0:04b43b777fae 124 for (int k=0; k<loopCount; k++)
MikamiUitOpen 0:04b43b777fae 125 {
MikamiUitOpen 0:04b43b777fae 126 int touch42 = -1;
MikamiUitOpen 0:04b43b777fae 127 menu.GetTouchedNumber(touch42);
MikamiUitOpen 0:04b43b777fae 128 if (touch42 == 4) break; // STOP
MikamiUitOpen 0:04b43b777fae 129 if (touch42 == 2) // PAUSE
MikamiUitOpen 0:04b43b777fae 130 {
MikamiUitOpen 0:04b43b777fae 131 menu.Inactivate(2); // PAUSE 無効
MikamiUitOpen 0:04b43b777fae 132 menu.Activate(3); // RESUME 有効
MikamiUitOpen 0:04b43b777fae 133 mySai.Pause();
MikamiUitOpen 0:04b43b777fae 134
MikamiUitOpen 0:04b43b777fae 135 // PLAY か RESUME か STOP がタッチされるまで待つ
MikamiUitOpen 0:04b43b777fae 136 int touch134 = -1;
MikamiUitOpen 0:04b43b777fae 137 while (!menu.GetTouchedNumber(touch134))
MikamiUitOpen 0:04b43b777fae 138 ModifyFilter(drawerObj, lpHp, onOff,
MikamiUitOpen 0:04b43b777fae 139 hn, ck, g0, filterOn);
MikamiUitOpen 0:04b43b777fae 140 switch (touch134)
MikamiUitOpen 0:04b43b777fae 141 {
MikamiUitOpen 0:04b43b777fae 142 case 1: playOk = true; // 最初から PLAY
MikamiUitOpen 0:04b43b777fae 143 break;
MikamiUitOpen 0:04b43b777fae 144 case 3: mySai.Resume(); // PAUSE したところから PLAY 再開
MikamiUitOpen 0:04b43b777fae 145 menu.Activate(2);
MikamiUitOpen 0:04b43b777fae 146 menu.Inactivate(3);
MikamiUitOpen 0:04b43b777fae 147 menu.TouchedColor(1);
MikamiUitOpen 0:04b43b777fae 148 break;
MikamiUitOpen 0:04b43b777fae 149 case 4: stopOk = true; // STOP
MikamiUitOpen 0:04b43b777fae 150 break;
MikamiUitOpen 0:04b43b777fae 151 }
MikamiUitOpen 0:04b43b777fae 152 }
MikamiUitOpen 0:04b43b777fae 153 if (playOk || stopOk) break;
MikamiUitOpen 0:04b43b777fae 154
MikamiUitOpen 0:04b43b777fae 155 ModifyFilter(drawerObj, lpHp, onOff, hn, ck, g0, filterOn);
MikamiUitOpen 0:04b43b777fae 156 // 1フレーム分の信号処理 (IIR フィルタ) の実行
MikamiUitOpen 0:04b43b777fae 157 ProcessSignal(sdReader, mySai, sn, g0, hn, ORDER, filterOn);
MikamiUitOpen 0:04b43b777fae 158 }
MikamiUitOpen 0:04b43b777fae 159 mySai.Stop();
MikamiUitOpen 0:04b43b777fae 160 menu.Activate(0); // OPEN 有効
MikamiUitOpen 0:04b43b777fae 161 if (!playOk) menu.Activate(1); // PLAY 有効
MikamiUitOpen 0:04b43b777fae 162 for (int n=2; n<5; n++) // その他は無効
MikamiUitOpen 0:04b43b777fae 163 menu.Inactivate(n);
MikamiUitOpen 0:04b43b777fae 164 sdReader.Close(); // SD のファイルのクローズ
MikamiUitOpen 0:04b43b777fae 165 }
MikamiUitOpen 0:04b43b777fae 166 }