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_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

时间: 2024-10-12 13:41:28

Cocos2d-x项目移植到WP8系列之五:播放MP3的相关文章

Cocos2d-x项目移植到WP8系列之二:开篇

开发环境一笔带过吧,主板和CPU要支持虚拟化技术,要开启才行,装个64位win8.1系统,win8不好用,我用的是vs2012,然后装个wp8的SDK,再装个vs2012的补丁4,最后能把模拟器跑起来能上网就可以了.模拟器上网这也是个蛋疼问题,如果电脑是通过路由器DHCP自动分配IP模拟器能正常上网,但在公司里电脑是根据Mac地址绑定IP的,模拟器上不了网,这里面碰到问题的话自行谷歌吧. 公司的框架是在Cocos2d-x的框架之上稍微封装了一下,方便加上一些自己的功能,总的来说就是业务层用Lua

Cocos2d-x项目移植到WP8系列之一:前传

许久没动笔了,随想一直都有动笔的想法,但拖来拖去,归根到底还是一个懒字吧 .发现人的惰性真是太强大了,特别是在像我这种意志不够坚定的人,稍微拖一拖,一个星期,一个月,大半年,就这样都过去了,加上平时的效率也挺低的,时间都浪费得让人心痛,再和一些刚毕业一年的后辈相比,发现根本跟不上他们的步伐,无论是已掌握的技术或者学习新的东西,才猛然惊醒,甚为愧疚.针对性下药,现在强迫自己把一些要做的工作上的事情都写在一个几乎从不关闭的Excel里,每次回到桌面都能看到,还有哪些事情没有完成的,完成后就标记一下,

Cocos2d-x项目移植到WP8系列之三:C++和C#的交互

上一篇提到工程使用 XAML 和 Direct3D 项目模板 是因为要涉及到C++和C#的交互,微软给我们提供了一个叫运行时组件的东西(也就是 windows phone 运行时组件 模板,一下简称winRT组件)来实现两者的交互.winRT组件 工程里用的C++/CX语言(关于winRT自行谷歌),但完全兼容C++.在winRT组件 工程里,里面定义的类和方法只要符合一定的规范,就能被C#的工程直接访问到,那C++如何访问C#呢?毕竟,在Cocos2dx-wp8框架里,除了一开始启动是从xam

Cocos2d-x项目移植到WP8系列之八:CCLabelTTF显示中文不换行

在wp8平台上,CCLabeTTF显示中文不会自动换行,看了下源码,原来底层的实现是根据text的空格进行判断的,每遇到一个空格就判断是否超过label的宽度,超过就换行,但text如果是中文的话,哪来的空格给换行~~ 以下实现全部参考 http://blog.csdn.net/hopingwhite/article/details/38414917 ,整理后的代码如下: 在CCFreeTypeFont.h里的CCFreeTypeFont类添加两个方法: FT_Error addLine(con

Cocos2d-x项目移植到WP8系列之六:C#工程使用C++的DLL

此时,一些大问题都被解决后,整个工程基本能跑起来了,最后一个大问题是:业务层是用Lua开发的,底层的源码对他们是不可见的,也就是需要把我们工程生成的各种DLL.lib.winmd文件拿出来然后再搭建一个开发环境给项目组使用,要求就是,每次底层改了什么只需要把对应的生成的lib.dll.winmd文件给他们替换就行了,而他们的开发环境里工程并不需要因此而变.嗯,但我们的工程大部分都是C++的,有DLL工程,也有lib工程,还有运行时工程,如何让C#用上这些工程的生成品? 原本我们的工程结构是这样的

Cocos2d-x项目移植到WP8系列之四:文件操作

读写文件Cocos已经用fopen fwrite来做好了,这里说的主要是文件和文件夹的创建.删除.判断是否存在等. 本来打算把把这部分代码放到C#工程来做,然后通过上一篇说到的C++和C#交互的那个通道来调用的,但是wp8里很多东西都被做成异步的形式了,文件的读写操作也被设计成了异步的形式,但是在C++这边发起调用的方法是需要同步调用的,这里如何转换是一个难题,由于对task PPL 那一套不熟悉,最后没办法只能放到C++工程来做. 另外,在task里那个捕获异常也是很痛苦的一件事情——一直没研

Cocos2d-x项目移植到WP8系列之九:使用自定义shader

有时候想得到一些例如灰度图等特殊的渲染效果,就得用到自定义shader,关于shader的一些背景知识,自行谷歌,列出两篇cocos2dx里介绍shader的相关文章 http://blog.csdn.net/while0/article/details/9666829     http://blog.sina.com.cn/s/blog_aa01f7030101mdom.html cocos2dx在wp8平台不知道是不是在渲染时OpenGL要转成D3D的原因还是其他原因,不能在运行时编译链接s

Cocos2d-x项目移植到WP8系列之七:中文显示乱码

C++和C#互调时经常会带一些参数过去例如最常见的字符串,如果字符串里有中文的话,会发现传递过去后变成了乱码,这是因为两边的编码方式不一样,C#默认使用UnicodeEncoding(中文环境下是GBK?)编码,C++(Lua和cocos2d-x引擎默认编码为UTF-8)里用的是utf8编码.大概流程就是 C++的里的std::string字符串转成 C++/CX 里的 Platform::string,再传到C#里System.String ,从C#到C++的话就是反过来. Cocos其实已经

大屏设计系列之五——大屏设计语言分析

如果您想订阅本博客内容,每天自动发到您的邮箱中,请点这里 作者:蓝蓝 蓝蓝设计经常会接到大屏设计的项目,比如中国移动互联网监控大屏可视化设计及开发.太极集团承接的中央台应急指挥中心大屏可视化设计.交大思源承接的北京地铁轨道批挥中心大屏可视化设计.数码视讯展厅大屏可视化设计,在积累了一定经验的同时,也在不断的学习和丰富关于大屏设计的特点及数据可视化的表达方式. 数据可视化过滤了非常多的冗余信息,浓缩了最重要的信息,它的魅力就在于将枯燥的数据组织在一起,把最需要的那些编辑成一个故事.目前大数据那么流