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

 原文链接: http://www.cnblogs.com/zouzf/p/3972549.html

 

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

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_WP8
13     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     else
21     {
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 

 

原文链接: http://www.cnblogs.com/zouzf/p/3972549.html

 

posted @ 2014-09-15 11:56  仙外仙  阅读(1571)  评论(0编辑  收藏  举报