三星S 2 i 9100の音声放送の崩壊(CocosDeshion)を解決する

2638 ワード

三星S 2 i 9100機のサブサウンドドライブにバグがあり、SoundPoolの再生音が多すぎるとクラッシュする.弾丸の連続射撃の音響効果はこの機械ではほとんど必殺技だ.
        cococos 2 d-xはこの問題を解決し、OpenSLを使用した.これはOpenGLのような音声基準であり、android 2.3以上のシステムがサポートされている. i 9100以外のデバイスはSoundPoolを使用し、i 9100デバイスはOpenSLを使用して音響効果を再生する.        cococos 2 d-xの音声再生エンジンCocosDeshionにはまだ瑕疵があり、OpenSLでファイルを読み取る際にAssetsManagerを使用したが、SDカードのサウンドファイル読み取りはサポートされていない.私のゲームの実現は、すべてのリソースをpakファイルにパッケージ化し、音声を再生するときにSDカードに対応するファイルがなければSDカードに音声をコピーし、SDカードの音声ファイルを再生することです. 明らかにcococos 2 d−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 descriptor
		int (*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を取得します.