Nam

Dependencies:   SRC_STM32F7 F746-GUI SD_PlayerSkeleton F746-SAI-IO

Revision:
0:415638154129
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jun 10 11:19:36 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();
+    
+}
+//-------------------------------------------------
+//Chuong trình con di?u ch?nh biên d? â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 don âm
+        sdReader_.ReadAndToMono(sn_);
+
+        while (!mySai_.IsXferred()) {}  // Ch? cho d?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 d?i âm lu?ng d?u ra
+            mySai_.Output(data, data);
+        }
+        //--------------------------------------------------------------
+    }
+
+    // Ði?u ch?nh âm lu?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 du?c cài d?t
+        if (fileCount_ == 0) return false;  //N?u t?p WAV tuong ?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 tuong ?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 dã ch?n tru?c dó 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 tru?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;
+    }
+}
+//--------------------------------------------------------------
+//chuong trình hi?n th? giao di?n & di?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 tru?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 d?n khi PLAY du?c ch?m
+            }
+
+            Display();  // X? lý hi?n th? dành riêng cho ?ng d?ng (ch?c nang ?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 nang ?o)
+
+            mySai_.PlayOut();       // Play
+
+            // L?p l?i cho d?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 d?n khi 'RESUME' ho?c 'STOP' du?c ch?m vào
+                    switch (WaitTouched())
+                    {
+                        case 1: playOk = true;      // PLAY t? d?u
+                                break;
+                        case 3: mySai_.ResumeOut(); // Ti?p t?c PLAY t? di?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 dã 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 dã b?t
+        while (!menu_.Touched(1));  // PLAY L?p l?i cho d?n khi nút du?c ch?m
+
+        selector_.Erase(0, 0, BG_LEFT_-4, 272);
+        title_.Draw();
+    }
+
+    // X? lý khi b?ng di?u khi?n du?c v?n hành
+    void SD_PlayerSkeleton::DoIfHandled()
+    {
+        if (reset_ != NULL) reset_->DoIfTouched();
+        Modefy();   // ?ng d?ng thay d?i tham s? c? th? (ch?c nang ?o)
+    }
+
+    //Ð?i trong khi th?c hi?n Do IfHandled () cho d?n khi b?t k? nút nào trên menu du?c ch?m vào
+    int SD_PlayerSkeleton::WaitTouched()
+    {
+        int touchNum;
+        while (!menu_.GetTouchedNumber(touchNum)) DoIfHandled();
+        return touchNum;
+    }
+}
+//-------------------------------------------------
+//chuong trình con d?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 d? 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ó du?c kích thu?c c?a fmt chunck
+        uint32_t fmtChunkSize;
+        fread(&fmtChunkSize, sizeof(uint32_t), 1, fp_);
+
+        // Xác nh?n r?ng dó 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 thu?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 d?i d? li?u t? t?p tin sang don â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 thu?c d? li?u (s? di?m l?y m?u)
+    int32_t SD_WavReader::GetSize()
+    {
+        if (!ok_) ErrorMsg("Get data size FAILED");
+        return size_;
+    }
+}