读书人

解决三星S2 i9100声音播发崩溃(CocosD

发布时间: 2013-03-06 16:20:31 作者: rapoo

解决三星S2 i9100声音播放崩溃(CocosDenshion)

三星S2 i9100机子声音驱动有bug,导致SoundPool播放音效过多的时候崩溃。子弹连续射击的音效在这台机子上几乎是必杀技。

cocos2d-x有解决这个问题,使用了OpenSL,这个是类似OpenGL的一种声音标准,android2.3以上的系统有支持。 非i9100的设备使用SoundPool,i9100设备使用OpenSL播放音效。
cocos2d-x的声音播放引擎CocosDenshion尚有瑕疵,OpenSL读取文件的时候使用了AssetsManager,但是不支持SD卡的音效文件读取。而我的游戏的实现是这样的,所有资源打包到pak文件中,播放声音的时候如果SD卡没有对应文件则把声音拷贝到SD卡,然后播放SD卡的声音文件。 显然cocos2d-x不兼容这种方式。

修改方式很简单,OpenSLEngine.cpp文件中修改getFileDescriptor函数:

int getFileDescriptor(const char * filename, off_t & start, off_t & length, bool inapk){if (!inapk) {FILE* fp = fopen(filename, "rb");fseek(fp, 0, SEEK_END);length = ftell(fp);fseek(fp, 0, SEEK_SET);start = 0;return fileno(fp);} else {JniMethodInfo methodInfo;if (! getStaticMethodInfo(methodInfo, ASSET_MANAGER_GETTER, "()Landroid/content/res/AssetManager;")){methodInfo.env->DeleteLocalRef(methodInfo.classID);return FILE_NOT_FOUND;}jobject assetManager = methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID);methodInfo.env->DeleteLocalRef(methodInfo.classID);AAssetManager* (*AAssetManager_fromJava)(JNIEnv* env, jobject assetManager);AAssetManager_fromJava = (AAssetManager* (*)(JNIEnv* env, jobject assetManager))dlsym(s_pAndroidHandle, "AAssetManager_fromJava");AAssetManager* mgr = AAssetManager_fromJava(methodInfo.env, assetManager);assert(NULL != mgr);AAsset* (*AAssetManager_open)(AAssetManager* mgr, const char* filename, int mode);AAssetManager_open = (AAsset* (*)(AAssetManager* mgr, const char* filename, int mode))dlsym(s_pAndroidHandle, "AAssetManager_open");AAsset* Asset = AAssetManager_open(mgr, filename, AASSET_MODE_UNKNOWN);if (NULL == Asset){LOGD("file not found! Stop preload file: %s", filename);return FILE_NOT_FOUND;}// open asset as file descriptorint (*AAsset_openFileDescriptor)(AAsset* asset, off_t* outStart, off_t* outLength);AAsset_openFileDescriptor = (int (*)(AAsset* asset, off_t* outStart, off_t* outLength))dlsym(s_pAndroidHandle, "AAsset_openFileDescriptor");int fd = AAsset_openFileDescriptor(Asset, &start, &length);assert(0 <= fd);void (*AAsset_close)(AAsset* asset);AAsset_close = (void (*)(AAsset* asset))dlsym(s_pAndroidHandle, "AAsset_close");AAsset_close(Asset);return fd;}}

如代码所示,如果资源不是apk包内的资源,则使用fopen的方式获取文件句柄fd。

读书人网 >操作系统

热点推荐