a
Dependencies: SRC_STM32F7 F746-GUI SD_PlayerSkeleton F746-SAI-IO
Revision 0:a26ecfb99239, committed 2019-06-10
- Comitter:
- fundokukiri
- Date:
- Mon Jun 10 08:05:28 2019 +0000
- Commit message:
- a\
Changed in this revision
diff -r 000000000000 -r a26ecfb99239 F746-GUI.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/F746-GUI.lib Mon Jun 10 08:05:28 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/phungductung/code/F746-GUI/#4e245f4bc8ac
diff -r 000000000000 -r a26ecfb99239 F746-SAI-IO.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/F746-SAI-IO.lib Mon Jun 10 08:05:28 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/phungductung/code/F746-SAI-IO/#f255629eada1
diff -r 000000000000 -r a26ecfb99239 SD_PlayerSkeleton.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SD_PlayerSkeleton.lib Mon Jun 10 08:05:28 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/phungductung/code/SD_PlayerSkeleton/#84ca69a520f9
diff -r 000000000000 -r a26ecfb99239 SRC_STM32F7.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SRC_STM32F7.lib Mon Jun 10 08:05:28 2019 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/phungductung/code/SRC_STM32F7/#e87aa4c49e95
diff -r 000000000000 -r a26ecfb99239 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Jun 10 08:05:28 2019 +0000 @@ -0,0 +1,459 @@ + +//-------------------------------------------------------------------- +#include "VolumeCtrl.hpp" +#include "FileSelectorWav.hpp" +#include "SD_PlayerSkeleton.hpp" +#include "SD_WavReader.hpp" + +using namespace Mikami; + +int main() +{ + VolumeCtrl myPlayer("Music Player"); + myPlayer.Execute(); + +} +//------------------------------------------------- +//Chương trình con điều chỉnh biên độ âm thanh + +namespace Mikami +{ + // Thực thi xử lý tín hiệu cho một khối + void VolumeCtrl::SignalProcessing() + { + // Đọc giá trị dữ liệu âm thanh nổi của một khối từ SD và biến nó thành đơn âm + sdReader_.ReadAndToMono(sn_); + + while (!mySai_.IsXferred()) {} // Chờ cho đến khi truyền dữ liệu hoàn tất + + for (int n=0; n<BUFF_SIZE_; n++) + { + int16_t data = volume_*sn_[n]; //Thay đổi âm lượng đầu ra + mySai_.Output(data, data); + } + //-------------------------------------------------------------- + } + + // Điều chỉnh âm lượng + void VolumeCtrl::Modefy() + { + if (myBar_.Slide()) + volume_ = myBar_.GetValue(); + } +// Hiển thị khi phát một bài hát + void VolumeCtrl::Display() + { + Label musicTitle(207, 80, GetFileNameNoExt(), Label::CENTER, Font16); + ctrl_.Draw(); + myBar_.Redraw(); + } +} +//-------------------------------------------------------------- +namespace Mikami +{ + FileSelector::FileSelector(uint8_t x0, uint8_t y0, int maxFiles, + int maxNameLength, SD_WavReader &reader) + : X_(x0), Y_(y0), + MAX_FILES_(maxFiles), MAX_NAME_LENGTH_(maxNameLength), + fileNames_(maxFiles), fileNameLabels_(MAX_LIST_PAGE_), + next_(50, 238, 64, 36, 2, (string[]){"<", ">"}, 10, 0, 2, -1, Font24), + pageLabel_(210, 250, Label::LEFT, Font16), + lcd_(GuiBase::GetLcd()), sdReader_(reader), page_(1), + nOld_(-1), kOld_(-1) + { + Array<string> nonString(MAX_LIST_PAGE_, ""); + rect_ = new ButtonGroup(X_, Y_, W_H_, W_H_, MAX_LIST_PAGE_, + nonString, 0, V_L_-W_H_, 1, + -1, Font12, 0, GuiBase::ENUM_BACK, + BASE_COLOR_, TOUCHED_COLOR_); + rect_->EraseAll(); + next_.EraseAll(); + + // Tạo Label + for (int n=0; n<MAX_LIST_PAGE_; n++) + fileNameLabels_[n] = new Label(X_+30, Y_+5+V_L_*n, "", + Label::LEFT, Font16, BASE_COLOR_); + } + + FileSelector::~FileSelector() + { + delete rect_; + for (int n=0; n<MAX_LIST_PAGE_; n++) delete fileNameLabels_[n]; + } + + // Lập danh sách các tập tin. Trả về false nếu tệp WAV không tồn tại + 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); // mở tập tin + + // Loại trừ các tệp không phải PCM, âm thanh nổi 16 bit, tần số lấy mẫu 44,1 kHz + if (sdReader_.IsWavFile()) + fileNames_[fileCount_++] = strName; + sdReader_.Close(); + } + if (fileCount_ >= MAX_FILES_) break; + } + closedir(dp); + } + else + return false; // nếu thẻ SD không được cài đặt + if (fileCount_ == 0) return false; //Nếu tệp WAV tương ứng không tồn tại + + div_t m = div(fileCount_, MAX_LIST_PAGE_); + maxPage_ = (m.rem == 0) ? m.quot : m.quot+1; + return true; //Khi tệp WAV tương ứng tồn tại + } + + // chọn tập tin + bool FileSelector::Select(string &fileName) + { + int m; + if (next_.GetTouchedNumber(m)) + { + if (m==0) page_--; + else page_++; + DisplayFileList(false); + nOld_ = -1; + wait_ms(300); + } + + int n; + if (rect_->GetTouchedNumber(n)) + { + int k = (page_ - 1)*MAX_LIST_PAGE_ + n; + fileNameLabels_[n]->Draw(GetFileNameNoExt(k), + TOUCHED_COLOR_); + fileName = fileNames_[k]; + // Trả về màu của tên tệp đã chọn trước đó trên cùng một trang + if (nOld_ != -1) + fileNameLabels_[nOld_]->Draw(GetFileNameNoExt(kOld_), + BASE_COLOR_); + if (page_ == maxPage_) // xóa hình chữ nhật phụ trên trang cuối + for (int j=fileCount_ % MAX_LIST_PAGE_ + 1; + j < MAX_LIST_PAGE_; j++) rect_->Erase(j); + nOld_ = n; + kOld_ = k; + wait_ms(300); + return true; + } + else + return false; + } + + // Hiển thị danh sách các tập tin + 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_); + + div_t m = div(fileCount_, MAX_LIST_PAGE_); + int count = (m.quot >= page_) ? MAX_LIST_PAGE_ : m.rem; + for (int n=0; n<count; n++) rect_->Draw(n); + for (int n=0; n<count; n++) + fileNameLabels_[n]->Draw(GetFileNameNoExt(n+(page_-1)*MAX_LIST_PAGE_)); +// Hiển thị trang trước, nút chọn trang tiếp theo, v.v. + next_.InactivateAll(); + if (page_ > 1) next_.Activate(0); // "<" hợp lệ + if (page_ < maxPage_) next_.Activate(1); // ">" hợp lệ + char page[6]; + sprintf(page, "%d/%d", page_, maxPage_); + pageLabel_.Draw(page); + } + + // xóa danh sách các tập tin + 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); + } + + // Lấy tên tệp với phần mở rộng bị xóa + string FileSelector::GetFileNameNoExt(int n) + { + string name = fileNames_[n]; + int k = name.rfind("."); + if (k != string::npos) + return name.erase(k); + else + return name; + } +} +//-------------------------------------------------------------- +//chương trình hiển thị giao diện & điều khiển + +namespace Mikami +{ + SD_PlayerSkeleton::SD_PlayerSkeleton(string str, bool resetButton) + : BUFF_SIZE_(2048), sn_(BUFF_SIZE_), + mySai_(SaiIO::OUTPUT, BUFF_SIZE_, AUDIO_FREQUENCY_44K), + sdReader_(BUFF_SIZE_), + fileName_(""), + title_(214, 4, str, Label::CENTER, Font16), + selector_(0, 22, 256, 37, sdReader_), + menu_(BG_LEFT_, 2, BG_WIDTH_, BG_HEIGHT_, 5, + (string[]){"SELECT", "PLAY", "PAUSE", "RESUME", "STOP"}, + 0, 2, 1) + { + menu_.InactivateAll(); + menu_.Activate(0); + + if (!selector_.CreateTable()) + BlinkLabel errLabel(240, 100, "SD CARD ERROR", Label::CENTER); + + if (resetButton) reset_ = new ResetButton(); + else reset_ = NULL; + } + + // thực thi xử lý trình phát SD + void SD_PlayerSkeleton::Execute() + { + bool playOk = false; + int32_t loopCount; + + while (true) + { + if (playOk) // Trong trường hợp PLAY sau PAUSE + loopCount = SD_Open(); + else // Nếu không PLAY sau PAUSE + { + if (0 == WaitTouched()) SelectFile(); + loopCount = SD_Open(); + while (1 != WaitTouched()) {} // Đợi cho đến khi PLAY được chạm + } + + Display(); // Xử lý hiển thị dành riêng cho ứng dụng (chức năng ảo) + if (reset_ != NULL) reset_->Draw(); + + menu_.Inactivate(0); // SELECT bị vô hiệu hóa + menu_.Activate(2); // PAUSE bị vô hiệu hóa + menu_.Activate(4); // STOP bị vô hiệu hóa + + playOk = false; + bool stopOk = false; + + Clear(); // Quá trình xóa ứng dụng cụ thể (chức năng ảo) + + mySai_.PlayOut(); // Play + + // Lặp lại cho đến khi hết dữ liệu tệp + for (int k=0; k<loopCount; k++) + { + int touch42 = -1; + menu_.GetTouchedNumber(touch42); + if (touch42 == 4) break; // STOP + if (touch42 == 2) // PAUSE Xử lý khi chạm vào nút + { + menu_.Inactivate(2); // PAUSE Nút không hợp lệ + menu_.Activate(3); // RESUME Đã bật nút + mySai_.PauseOut(); + + // PLAY Đợi cho đến khi 'RESUME' hoặc 'STOP' được chạm vào + switch (WaitTouched()) + { + case 1: playOk = true; // PLAY từ đầu + break; + case 3: mySai_.ResumeOut(); // Tiếp tục PLAY từ điểm PAUSE + menu_.Activate(2); + menu_.Inactivate(3); + menu_.TouchedColor(1); + break; + case 4: stopOk = true; // STOP + break; + } + } + if (playOk || stopOk) break; + + DoIfHandled(); + // Xử lý tín hiệu cho một khối dành riêng cho ứng dụng (hàm ảo thuần túy) + SignalProcessing(); + } + mySai_.StopOut(); + if (!playOk) menu_.Activate(0); // SELECT hợp lệ + menu_.Draw(1); // Khởi tạo màu của nút PLAY + for (int n=2; n<5; n++) // Các nút khác bị vô hiệu hóa + menu_.Inactivate(n); + + sdReader_.Close(); // Đóng tệp SD + } + } + + // Lấy tên tệp đã chọn mà không cần phần mở rộng + string SD_PlayerSkeleton::GetFileNameNoExt() + { + string fName = fileName_; + int k = fName.rfind("."); + if (k != string::npos) + return fName.erase(k); + else + return fName; + } + + // Mở tệp thẻ SD + int32_t SD_PlayerSkeleton::SD_Open() + { + if (fileName_.empty()) SelectFile(); + sdReader_.Open(fileName_); + sdReader_.IsWavFile(); + return sdReader_.GetSize()/BUFF_SIZE_; + } + + // Lựa chọn tập tin + void SD_PlayerSkeleton::SelectFile() + { + selector_.DisplayFileList(); + title_.Draw("Select file"); + menu_.Inactivate(0); // SELECT vô hiệu hóa + menu_.Inactivate(1); // PLAY vô hiệu hóa + do + if (selector_.Select(fileName_)) + menu_.Activate(1); // PLAY đã bật + while (!menu_.Touched(1)); // PLAY Lặp lại cho đến khi nút được chạm + + selector_.Erase(0, 0, BG_LEFT_-4, 272); + title_.Draw(); + } + + // Xử lý khi bảng điều khiển được vận hành + void SD_PlayerSkeleton::DoIfHandled() + { + if (reset_ != NULL) reset_->DoIfTouched(); + Modefy(); // Ứng dụng thay đổi tham số cụ thể (chức năng ảo) + } + + //Đợi trong khi thực hiện Do IfHandled () cho đến khi bất kỳ nút nào trên menu được chạm vào + int SD_PlayerSkeleton::WaitTouched() + { + int touchNum; + while (!menu_.GetTouchedNumber(touchNum)) DoIfHandled(); + return touchNum; + } +} +//------------------------------------------------- +//chương trình con đọc file WAV-PCM-16bit-44.1KHz + +namespace Mikami +{ + SD_WavReader::SD_WavReader(int32_t bufferSize) + : STR_("sd"), ok_(false) + { + sd_ = new SDFileSystem(STR_.c_str()); + sd_->mount(); + buffer.SetSize(bufferSize*2); + } + + SD_WavReader::~SD_WavReader() + { + sd_->unmount(); + delete sd_; + } + + void SD_WavReader::Open(const string fileName) + { + string name = (string)"/" + STR_ + "/" + fileName; + fp_ = fopen(name.c_str(), "rb"); + if (fp_ == NULL) ErrorMsg("Loi The SD!!!"); + } + + + // Đọc một phần của tiêu đề tệp "RIFFxxxxWAVEfmt" + // Giá trị trả về: true nếu âm thanh nổi 16 bit, tần số lấy mẫu là 44,1 kHz + bool SD_WavReader::IsWavFile() + { + char data[17]; + fread(data, 1, 16, fp_); // Đọc 16 byte + string strRead = ""; + for (int n=0; n<4; n++) strRead += data[n]; + // Không kiểm tra 4 ký tự giữa + for (int n=8; n<16; n++) strRead += data[n]; + + // Kiểm tra xem "RIFF", "WAVE", "fmt" có tồn tại không + if (strRead != "RIFFWAVEfmt ") return false; + + // có được kích thước của fmt chunck + uint32_t fmtChunkSize; + fread(&fmtChunkSize, sizeof(uint32_t), 1, fp_); + + // Xác nhận rằng đó là PCM, Stereo, 44.1 kHz, 16 bit + WaveFormatEx fmtData; + fread(&fmtData, fmtChunkSize, 1, fp_); + if ((fmtData.wFormatTag != 1) || + (fmtData.nChannels != 2) || + (fmtData.nSamplesPerSec != AUDIO_FREQUENCY_44K) || + (fmtData.wBitsPerSample != 16) + ) return false; + + // Tìm dữ liệu + char dataId[5]; + dataId[4] = 0; + fread(dataId, 1, 4, fp_); + if ("data" != (string)dataId) + for (int n=0; n<100; n++) + { + char oneByte; + fread(&oneByte, 1, 1, fp_); + for (int k=0; k<3; k++) + dataId[k] = dataId[k+1]; + dataId[3] = oneByte; + if ("data" == (string)dataId) break; + + if (n == 99) return false; + } + + // Nhận kích thước dữ liệu (byte) + int32_t sizeByte; + fread(&sizeByte, sizeof(int32_t), 1, fp_); + size_ = sizeByte/4; + + ok_ = true; + return true; + } + + // Nhận dữ liệu âm thanh nổi từ tập tin + void SD_WavReader::ReadStereo(Array<int16_t>& dataL, + Array<int16_t>& dataR) + { + if (!ok_) ErrorMsg("Get data FAILED"); + 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]; + } + } + + // Chuyển đổi dữ liệu từ tập tin sang đơn âm + 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; + } + + // Thu thập kích thước dữ liệu (số điểm lấy mẫu) + int32_t SD_WavReader::GetSize() + { + if (!ok_) ErrorMsg("Get data size FAILED"); + return size_; + } +}