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
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 }
Generated on Wed Jul 27 2022 22:49:02 by 1.7.2