首页 > 代码库 > Cocos2d-x项目移植到WP8系列之五:播放MP3

Cocos2d-x项目移植到WP8系列之五:播放MP3

 

这一块的细节还是不太了解,只是东凑西拼能跑起来而已

1、网上下载lamb库 生成需要的lib库,详情见 【Advanced Windows Phone Programming】在windows phone 8中录制MP3和AAC及Amr音频  第三点的前半部分,也就是生成lib那一部分,然后在CocosDenshion工程里引用那两个lib。

2、把CocosDenshion工程里的Audio.cpp里的void Audio::PreloadSoundEffect(const char* pszFilePath, bool isMusic) 方法里的m_soundEffects[sound].m_soundID = sound; 这句代码之前的代码改成如下:

 1     if (m_engineExperiencedCriticalError) { 2         return; 3     } 4  5     std::string path(pszFilePath); 6  7     int sound = Hash(pszFilePath); 8  9     MediaStreamer mediaStreamer;10 11 12     // no MP3 support for CC_PLATFORM_WP813     std::string::size_type pos = path.find(".mp3");14     if (pos  != path.npos)15     {16         //path.replace(pos, path.length(), ".wav");17 18         mediaStreamer.Initialize_MP3(CCUtf8ToUnicode(pszFilePath).c_str());19     }20     else21     {22         mediaStreamer.Initialize(CCUtf8ToUnicode(pszFilePath).c_str());23     }24 25     26 //    mediaStreamer.Initialize(CCUtf8ToUnicode(pszFilePath).c_str());27     m_soundEffects[sound].m_soundID = sound;    


3、CocosDenshion工程里的MediaStreamer类加多一个方法:void MediaStreamer::Initialize_MP3(__in const WCHAR* url),实现如下:

  1 void MediaStreamer::Initialize_MP3(__in const WCHAR* url)  2 {  3   4     WCHAR filePath[MAX_PATH] = {0};  5     if ((wcslen(url) > 1 && url[1] == :))  6     {  7         // path start with "x:", is absolute path  8         wcscat_s(filePath, url);  9     } 10     else if (wcslen(url) > 0  11         && (L/ == url[0] || L\\ == url[0])) 12     { 13         // path start with ‘/‘ or ‘\‘, is absolute path without driver name 14         wcscat_s(filePath, m_locationPath->Data()); 15         // remove ‘/‘ or ‘\\‘ 16         wcscat_s(filePath, (const WCHAR*)url[1]); 17     }else 18     { 19         wcscat_s(filePath, m_locationPath->Data()); 20         wcscat_s(filePath, url); 21     } 22  23  24     hip_t hip = hip_decode_init(); 25     if (!hip)   26     { 27         printf("创建mp3解码失败");  28         return ; 29     }  30  31     mp3data_struct mp3str;//mp3文件编码信息 32     std::vector<short*> mp3Buffer;// mp3数据流 33     std::vector<int> mp3BufferSize; 34  35     int samples; 36     int mp3_bytes; 37     int write_bytes = 0; 38  39     const int BUF_SIZE = 512; 40     const int INBUF_SIZE = 4096; 41     const int MP3BUF_SIZE = (int)(1.25 * BUF_SIZE) + 7200; 42  43     short pcm_l[INBUF_SIZE]; 44     short pcm_r[INBUF_SIZE]; 45     unsigned char mp3_buf[MP3BUF_SIZE]; 46  47     FILE * MP3File; 48      49  50     std::wstring wstr = std::wstring(filePath); 51 //    return std::string(wstr.begin(),wstr.end()); 52  53     std::string str_filePath = std::string(wstr.begin(),wstr.end());//"C:\\Data\\Programs\\{4AE99D96-62EE-4A1C-A345-F1B0A81D07BC}\\Install\\Assets\\Resources\\islandbg.mp3"; 54      55      56     auto error = fopen_s(&MP3File, str_filePath.c_str(), "rb"); 57     mp3data_struct mp3Header; 58  59     while ((mp3_bytes = fread(mp3_buf, 1, 210, MP3File)) > 0) 60     { 61         samples = hip_decode_headers(hip, mp3_buf, 210, pcm_l, pcm_r, &mp3Header); 62         if (samples > 0) 63         { 64             short *tt = new short[samples*sizeof(short)]; 65             memcpy((void*)tt, (const void*)pcm_l, samples*sizeof(short)); 66             mp3Buffer.push_back(tt); 67             write_bytes += samples*sizeof(short); 68             mp3BufferSize.push_back(samples*sizeof(short)); 69             //write_bytes = fwrite(pcm_l, sizeof(short), samples, wavfp); 70         } 71     } 72  73  74     byte* _mp3Buffer = new byte[write_bytes]; 75     byte* temp = _mp3Buffer; 76     int size = mp3BufferSize.size(); 77     for(int i=0;i<size;i++) 78     { 79         memcpy(temp, mp3Buffer[i],mp3BufferSize[i]); 80         delete mp3Buffer[i]; 81         temp += mp3BufferSize[i]; 82     } 83     mp3Buffer.clear(); 84     hip_decode_exit(hip); 85     //m_soundEffects[sound].m_soundEffectBufferData 86  87     m_data.resize(write_bytes); 88     for(int i=0;i<write_bytes;i++) 89     { 90         m_data[i]=_mp3Buffer[i]; 91     } 92  93     fclose(MP3File); 94  95  96  97     m_waveFormat.wFormatTag = WAVE_FORMAT_PCM; //固定 98     m_waveFormat.nChannels = 1; //固定 99     m_waveFormat.nSamplesPerSec = (DWORD) mp3Header.samplerate;// 固定 100 101     m_waveFormat.wBitsPerSample = 16;// mp3Header.bitrate * m_waveFormat.nChannels / 8; 102     //m_waveFormat.wBitsPerSample = mp3Header.bitrate * m_waveFormat.nChannels / 8.0; 103     m_waveFormat.nBlockAlign = m_waveFormat.nChannels * m_waveFormat.wBitsPerSample / 8.0; 104     m_waveFormat.nAvgBytesPerSec = m_waveFormat.nSamplesPerSec * m_waveFormat.nBlockAlign; //越大越快105     m_waveFormat.cbSize = 0;106 107 }


完成。

大概流程就是,通过lamb的两个lib库的方法,读取MP3文件的流构建成wav文件格式的流,重点在于通过MP3的文件头信息mp3data_struct 构建出 wav文件的文件头信息WAVEFORMATEX。

另外,因为只读取了一个声道的流,所以m_waveFormat.nChannels = 1;如果对声道有要求的,可以在while循环里把右声道的流也处理一下。

附上一些参考文章: lame mp3解码      Suche MP3 to WAV decoder 

 

Cocos2d-x项目移植到WP8系列之五:播放MP3