![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
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
Revision 11:769d986c10fa, committed 2016-07-04
- Comitter:
- MikamiUitOpen
- Date:
- Mon Jul 04 05:59:44 2016 +0000
- Parent:
- 10:8e321be14b18
- Commit message:
- 12
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Array_Matrix.lib Mon Jul 04 05:59:44 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/MikamiUitOpen/code/Array_Matrix/#efe9b1f01090
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/FileSelectorWav.cpp Mon Jul 04 05:59:44 2016 +0000 @@ -0,0 +1,114 @@ +//-------------------------------------------------------------- +// FileSelector class +// SD カード内のファイル名の一覧を表示し,ファイルを選択する +// +// 2016/06/30, Copyright (c) 2016 MIKAMI, Naoki +//-------------------------------------------------------------- + +#include "FileSelectorWav.hpp" + +namespace Mikami +{ + bool FileSelector::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; + sdReader_.Close(); + } + + if (fileCount_ >= MAX_FILES_) break; + } + closedir(dp); + } + else + return false; + + if (fileCount_ == 0) return false; + + if (rect_ != NULL) delete rect_; + Array<string> nonString(fileCount_, ""); + 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 FileSelector::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 = fileNames_[n]; + return true; + } + else + return false; + } + + // ファイルの一覧の表示 + void FileSelector::DisplayFileList(bool sortEnable) + { + if (sortEnable) + std::sort((string *)fileNames_, + (string *)fileNames_+fileCount_); + + Erase(X_, Y_, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 272-Y_); + rect_->DrawAll(); + for (int n=0; n<fileCount_; n++) + fileNameLabels_[n]->Draw(GetFileNameNoExt(n)); + } + + // ファイルの一覧の消去 + void FileSelector::Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height, + uint32_t color) + { + lcd_->SetTextColor(color); + lcd_->FillRect(x, y, width, height); + } + + // Label を生成 + void FileSelector::CreateLabels() + { + fileNameLabels_.SetSize(fileCount_); + + for (int n=0; n<fileCount_; n++) + fileNameLabels_[n] = new Label(X_+30, Y_+5+V_L_*n, "", + Label::LEFT, Font16, + BASE_COLOR_); + } + + // 拡張子を削除した文字列を取得 + string FileSelector::GetFileNameNoExt(int n) + { + string name = fileNames_[n]; + name.erase(name.find(".")); + return name.substr(0, MAX_NAME_LENGTH_); + } + +}
--- a/MyClasses_Functions/FileSelectorWav.hpp Wed Jun 15 13:16:49 2016 +0000 +++ b/MyClasses_Functions/FileSelectorWav.hpp Mon Jul 04 05:59:44 2016 +0000 @@ -1,18 +1,16 @@ //-------------------------------------------------------------- -// FileSelector class +// FileSelector class ---- Header ---- // SD カード内のファイル名の一覧を表示し,ファイルを選択する // -// 2016/04/18, Copyright (c) 2016 MIKAMI, Naoki +// 2016/06/30, 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> @@ -26,22 +24,68 @@ : 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()), + fileNames_(maxFiles), + rect_(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_; - } + { delete rect_; } + + bool CreateTable(); + + // ファイルを選択する + bool Select(string &fileName); + + // ファイルの一覧の表示 + void DisplayFileList(bool sortEnable = true); + + // ファイルの一覧の消去 + void Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height, + uint32_t color = GuiBase::ENUM_BACK); + + 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_; + + Array<string> fileNames_; + ButtonGroup *rect_; + Array<Label *> fileNameLabels_; + LCD_DISCO_F746NG *lcd_; + SD_WavReader &sdReader_; + int fileCount_, prevFileCount_; + int prev_; + + // Label を生成 + void CreateLabels(); + + // 拡張子を削除した文字列を取得 + string GetFileNameNoExt(int n); + + // disallow copy constructor and assignment operator + FileSelector(const FileSelector&); + FileSelector& operator=(const FileSelector&); + }; +} +/* +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_(maxFiles), + rect_(NULL), lcd_(GuiBase::GetLcdPtr()), + sdReader_(reader), prevFileCount_(0), prev_(-1) {} + + ~FileSelector() + { delete rect_; } bool CreateTable() { @@ -63,30 +107,23 @@ // PCM,16 ビットステレオ,標本化周波数 44.1 kHz 以外のファイルは除外 if (sdReader_.IsWavFile()) - { - fileNames_[fileCount_] = strName; - fileCount_++; - } + fileNames_[fileCount_++] = strName; 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_; + Array<string> nonString(fileCount_, ""); rect_ = new ButtonGroup(X_, Y_, W_H_, W_H_, fileCount_, - nonString_, 0, V_L_-W_H_, 1, + 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); @@ -105,7 +142,7 @@ if ((prev_ >= 0) && (prev_ != n)) fileNameLabels_[prev_]->Draw(GetFileNameNoExt(prev_)); prev_ = n; - fileName = sortedFileNames_[n]; + fileName = fileNames_[n]; return true; } else @@ -113,34 +150,26 @@ } // ファイルの一覧の表示 - void DisplayFileList(bool sort = true) + void DisplayFileList(bool sortEnable = true) { - for (int n=0; n<fileCount_; n++) - sortedFileNames_[n] = fileNames_[n]; - if (sort) - std::sort(sortedFileNames_, sortedFileNames_+fileCount_); + if (sortEnable) + std::sort((string *)fileNames_, + (string *)fileNames_+fileCount_); -//// Erase(MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 270-Y_); - Erase(X_, 0, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 288); + Erase(X_, Y_, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 272-Y_); 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(X_, Y_, width, height); - } -*/ + // ファイルの一覧の消去 void Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color = GuiBase::ENUM_BACK) { lcd_->SetTextColor(color); lcd_->FillRect(x, y, width, height); } + private: const uint8_t X_, Y_, W_H_, V_L_; const int MAX_FILES_; @@ -148,11 +177,9 @@ const uint32_t BASE_COLOR_; const uint32_t TOUCHED_COLOR_; - string *fileNames_; - string *sortedFileNames_; - string *nonString_; + Array<string> fileNames_; ButtonGroup *rect_; - Label **fileNameLabels_; + Array<Label *> fileNameLabels_; LCD_DISCO_F746NG *lcd_; SD_WavReader &sdReader_; int fileCount_, prevFileCount_; @@ -161,13 +188,8 @@ // Label を生成 void CreateLabels() { - if (fileNameLabels_ != NULL) - { - for (int n=0; n<prevFileCount_; n++) - delete fileNameLabels_[n]; - delete[] fileNameLabels_; - } - fileNameLabels_ = new Label *[fileCount_+1]; + fileNameLabels_.SetSize(fileCount_); + for (int n=0; n<fileCount_; n++) fileNameLabels_[n] = new Label(X_+30, Y_+5+V_L_*n, "", Label::LEFT, Font16, @@ -177,7 +199,7 @@ // 拡張子を削除した文字列を取得 string GetFileNameNoExt(int n) { - string name = sortedFileNames_[n]; + string name = fileNames_[n]; name.erase(name.find(".")); return name.substr(0, MAX_NAME_LENGTH_); } @@ -187,4 +209,6 @@ FileSelector& operator=(const FileSelector&); }; } +*/ #endif // FILE_SELECTOR_HPP +
--- a/MyClasses_Functions/MyFunctions.cpp Wed Jun 15 13:16:49 2016 +0000 +++ b/MyClasses_Functions/MyFunctions.cpp Mon Jul 04 05:59:44 2016 +0000 @@ -1,35 +1,35 @@ //-------------------------------------------------------------- // フィルタ処理付き SD オーディオプレーヤーで使う大域関数(ヘッダ) // -// 2016/05/07, Copyright (c) 2016 MIKAMI, Naoki +// 2016/07/04, Copyright (c) 2016 MIKAMI, Naoki //-------------------------------------------------------------- #include "MyFunctions.hpp" // 1フレーム分の信号処理 (IIR フィルタ) の実行 void IIR_Filtering(SD_WavReader &sdReader, SaiIO &mySai, - int16_t sn[], float g0, Biquad hn[], + float g0, Biquad hn[], int order, bool filterOn) { + static int32_t frameSize = mySai.GetLength(); + static Array<int16_t> sn(frameSize); // フレームバッファ + // 1フレーム分のデータを SD から読み込む - sdReader.ReadAndToMono(sn, mySai.GetLength()); + sdReader.ReadAndToMono(sn); while (!mySai.IsXferred()) {} // データの転送が終わるまで待つ //-------------------------------------------------------------- // 1フレーム分の信号処理を行い,その結果を出力する - for (int n=0; n<mySai.GetLength(); n++) + for (int n=0; n<frameSize; n++) { - int16_t value; - if (filterOn) // フィルタ処理実行 - { - // 縦続形の IIR フィルタ - float yn = g0*sn[n]; - for (int k=0; k<order/2; k++) yn = hn[k].Execute(yn); - value = (int16_t)yn; - } - else - value = sn[n]; // フィルタ処理なし - mySai.Output(value, value); // 音響信号の出力 + // 縦続形の IIR フィルタ + float yn = g0*sn[n]; + for (int k=0; k<order/2; k++) yn = hn[k].Execute(yn); + + int16_t value = filterOn ? (int16_t)yn : sn[n]; + + // 音響信号の出力,右チャンネルには出力しない + mySai.Output(value, 0); } //-------------------------------------------------------------- mySai.ResetXferred(); // 次のデータ転送に備える @@ -82,4 +82,3 @@ } } -
--- a/MyClasses_Functions/MyFunctions.hpp Wed Jun 15 13:16:49 2016 +0000 +++ b/MyClasses_Functions/MyFunctions.hpp Mon Jul 04 05:59:44 2016 +0000 @@ -1,7 +1,7 @@ //-------------------------------------------------------------- // フィルタ処理付き SD オーディオプレーヤーで使う大域関数(ヘッダ) // -// 2016/05/07, Copyright (c) 2016 MIKAMI, Naoki +// 2016/07/04, Copyright (c) 2016 MIKAMI, Naoki //-------------------------------------------------------------- #ifndef F746_MY_FUNCTIONS_HPP @@ -17,7 +17,7 @@ // 1フレーム分の信号処理 (IIR フィルタ) の実行 void IIR_Filtering(SD_WavReader &sdReader, SaiIO &mySai, - int16_t sn[], float g0, Biquad hn[], + float g0, Biquad hn[], int order, bool filterOn); // SD カードのファイルのオープン
--- a/MyClasses_Functions/SD_WavReader.cpp Wed Jun 15 13:16:49 2016 +0000 +++ b/MyClasses_Functions/SD_WavReader.cpp Mon Jul 04 05:59:44 2016 +0000 @@ -4,7 +4,7 @@ // 以下のフォーマット以外は扱わない // PCM,16 ビットステレオ,標本化周波数 44.1 kHz // -// 2016/04/19, Copyright (c) 2016 MIKAMI, Naoki +// 2016/06/17, Copyright (c) 2016 MIKAMI, Naoki //-------------------------------------------------------------- #include "SD_WavReader.hpp" @@ -15,14 +15,12 @@ : STR_("sd"), ok_(false) { sd_ = new SDFileSystem(STR_.c_str()); - sd_->mount(); - - buffer = new int16_t[bufferSize*2]; + sd_->mount(); + buffer.SetSize(bufferSize*2); } SD_WavReader::~SD_WavReader() { - delete[] buffer; sd_->unmount(); delete sd_; } @@ -88,17 +86,25 @@ return true; } - // ファイルからデータの取得 - void SD_WavReader::Read(int16_t data[], uint32_t size) + // ファイルからステレオデータの取得 + void SD_WavReader::ReadStereo(Array<int16_t>& dataL, + Array<int16_t>& dataR) { if (!ok_) ErrorMsg("Get data FAILED"); - fread(data, sizeof(int16_t), size, fp_); - } + uint32_t size = dataL.Length(); + fread(buffer, sizeof(int16_t), size*2, fp_); + for (int n=0; n<size; n++) + { + dataL[n] = buffer[2*n]; + dataR[n] = buffer[2*n+1]; + } + } // ファイルからデータをモノラルに変換しての取得 - void SD_WavReader::ReadAndToMono(int16_t data[], uint32_t size) + void SD_WavReader::ReadAndToMono(Array<int16_t>& data) { if (!ok_) ErrorMsg("Get data FAILED"); + uint32_t size = data.Length(); 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;
--- a/MyClasses_Functions/SD_WavReader.hpp Wed Jun 15 13:16:49 2016 +0000 +++ b/MyClasses_Functions/SD_WavReader.hpp Mon Jul 04 05:59:44 2016 +0000 @@ -4,7 +4,7 @@ // 以下のフォーマット以外は扱わない // PCM,16 ビットステレオ,標本化周波数 44.1 kHz // -// 2016/04/19, Copyright (c) 2016 MIKAMI, Naoki +// 2016/06/17, Copyright (c) 2016 MIKAMI, Naoki //-------------------------------------------------------------- #ifndef SD_WAV_READER_HPP @@ -12,6 +12,8 @@ #include "SDFileSystem.h" #include "BlinkLabel.hpp" +#define DEBUG_ARRAY_CHECK +#include "Array.hpp" #include <string> namespace Mikami @@ -26,16 +28,16 @@ void Close() { fclose(fp_); } - // ファイルのヘッダ (RIFFxxxxWAVEfm ) 読み込み + // ファイルのヘッダ読み込み // 戻り値: *.wav で,16 ビットステレオ, // 標本化周波数:44.1 kHz の場合 true bool IsWavFile(); - // ファイルからデータの取得 - void Read(int16_t data[], uint32_t size); + // ファイルからステレオデータの取得 + void ReadStereo(Array<int16_t>& dataL, Array<int16_t>& dataR); // ファイルからデータをモノラルに変換しての取得 - void ReadAndToMono(int16_t data[], uint32_t size); + void ReadAndToMono(Array<int16_t>& data); // データサイズ(標本化点の数)の取得 int32_t GetSize(); @@ -51,15 +53,15 @@ uint32_t nAvgBytesPerSec; // 転送速度 (bytes/s) uint16_t nBlockAlign; // 4: 16ビットステレオの場合 uint16_t wBitsPerSample; // データのビット数,8 または 16 - uint16_t cbSize; + uint16_t cbSize; // PCM の場合使わない }; SDFileSystem *sd_; FILE *fp_; bool ok_; - int32_t size_; // モノラルデータのサイズ - int16_t *buffer; // ステレオをモノラルに変換する際の作業領域 + int32_t size_; // データサイズ(標本化点の数) + Array<int16_t> buffer; // ステレオをモノラルに変換する際の作業領域 void ErrorMsg(char msg[]) { BlinkLabel errLabel(240, 100, msg, Label::CENTER); }
--- a/main.cpp Wed Jun 15 13:16:49 2016 +0000 +++ b/main.cpp Mon Jul 04 05:59:44 2016 +0000 @@ -3,9 +3,9 @@ // SD のファイル: *.wav // PCM,16 ビットステレオ,標本化周波数 44.1 kHz // IIR フィルタ ---- 低域通過および高域通過フィルタ -// 出力:モノラル +// 出力:モノラル(L+R,左チャンネルのみ,右チャンネルには出力しない) // -// 2016/05/10, Copyright (c) 2016 MIKAMI, Naoki +// 2016/07/04, Copyright (c) 2016 MIKAMI, Naoki //-------------------------------------------------------------- #include "MyFunctions.hpp" @@ -15,15 +15,15 @@ int main() { - Label myLabel1(200, 4, "SD Card Audio Player", Label::CENTER, Font16); - Label myLabel2(200, 18, "---- variable LPF and HPF ----", Label::CENTER, Font12); + Label myLabel1(200, 4, "Variable LPF and HPF 15:02", Label::CENTER, Font16); + Label myLabel2(200, 20, "---- Source: microSD card ----", 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; - FileSelector selector(4, 26, MAX_FILES, 34, sdReader); + FileSelector selector(4, 22, MAX_FILES, 34, sdReader); if (!selector.CreateTable()) BlinkLabel errLabel(240, 100, "SD CARD ERROR", Label::CENTER); @@ -71,7 +71,6 @@ for (int k=0; k<ORDER/2; k++) hn[k] = Biquad(ck[k]); int32_t frameSize = mySai.GetLength(); - int16_t *sn = new int16_t[frameSize+1]; // フレームバッファ bool playOk = false; bool filterOn = false; bool whileFirst = true; @@ -109,8 +108,8 @@ else loopCount = SD_Open(sdReader, fileName, frameSize); - selector.Erase(0, 0, BG_LEFT-4, 288); - myLabel1.Draw("IIR Butterworth filter"); + selector.Erase(0, 0, BG_LEFT-4, 272); + myLabel1.Draw(); drawerObj.DrawResponse(); menu.Inactivate(0); // OPEN 無効 menu.Activate(2); // PAUSE 有効 @@ -156,7 +155,7 @@ ModifyFilter(drawerObj, lpHp, onOff, hn, ck, g0, filterOn); // 1フレーム分の信号処理 (IIR フィルタ) の実行 - IIR_Filtering(sdReader, mySai, sn, g0, hn, ORDER, filterOn); + IIR_Filtering(sdReader, mySai, g0, hn, ORDER, filterOn); } mySai.StopOut(); menu.Activate(0); // OPEN 有効 @@ -166,4 +165,3 @@ sdReader.Close(); // SD のファイルのクローズ } } -