多平台声音播放方案

多平台声音播放方案
多平台声音播放本质是引擎提供统一播放接口,根据平台不同调用各平台的api。
/********************************************************************
 Copyright(C), 2012-2013,
 FileName:AudioEngine.h
 Description:
 Author:cloud
 Created:2014/10/24
 history:
24:10:2014 13:45 by
*********************************************************************/
#pragma once
#include "Singleton.h"
#include <map>
#include <list>
#include <string>

namespace cloud
{	
	//wraper of cocosDension
	class AudioEngine : public Singleton<AudioEngine>
	{
	public:
		DECLARE_SINGLETON_CREATE_DESTROY

		void setVolume(float volume);
        void setBGMVolume(float volume);
        void setSFXVolume(float volume);

		void playMusic(const std::string& fileName,bool bLoop = false);
		void stopMusic();
		void pauseBackgroundMusic();
		void resumeBackgroundMusic();
		void stopAllMusic();
		void stopAllSFX();
		
		void playSound(unsigned int soundId,bool bLoop = false);
		void playSoundOnce(const std::string& fileName);
		void stopSound(unsigned int soundId);

		void loadSound(const std::string& fileName,unsigned int soundId);
		void unLoadSound(unsigned int soundId);
		void clearSounds();		

		bool isBGMEnabled() const;
		void setBGMEnabled(bool bBGMEnabled);

		bool isSFXEnabled() const;
		void setSFXEnabled(bool bSFXEnabled);

	protected:	
		AudioEngine();
		~AudioEngine();

		typedef std::map<unsigned int,std::string> SoundIDMap;
		typedef std::multimap<unsigned int,unsigned int> SoundRTMap;
		SoundIDMap m_soundIdResMap;
		SoundRTMap m_soundRtMap;
		
		bool m_bgmEnabled;
		bool m_sfxEnabled;
	};
}

/********************************************************************
 Copyright(C), 2012-2013,
 FileName:AudioEngine.cpp
 Description:
 Author:cloud
 Created:2014/10/24
 history:
24:10:2014 13:46 by
*********************************************************************/
#include "AudioEngine.h"
#include "AudioEngineCore.h"




namespace cloud
{
	IMPLEMENT_SINGLETON_ALL(AudioEngine)	

	AudioEngine::AudioEngine()
		:Singleton<AudioEngine>(),m_bgmEnabled(true),m_sfxEnabled(true)
	{
	}

	AudioEngine::~AudioEngine()
	{
		stopAllMusic();
		clearSounds();
		AudioEngineCore::end();

	}

	void AudioEngine::setVolume(float volume)
	{
		AudioEngineCore::setEffectsVolume(volume);
		AudioEngineCore::setBackgroundMusicVolume(volume);
	}
    
    void AudioEngine::setBGMVolume(float volume)
    {
        AudioEngineCore::setBackgroundMusicVolume(volume);
    }
    
    void AudioEngine::setSFXVolume(float volume)
    {
        AudioEngineCore::setEffectsVolume(volume);
    }



	void AudioEngine::playMusic(const std::string& fileName,bool bLoop /* = false */)
	{
		stopMusic();
		if (m_bgmEnabled)
		{
			AudioEngineCore::playBackgroundMusic(fileName.c_str(),bLoop);			
		}		
	}

	void AudioEngine::stopMusic()
	{
		AudioEngineCore::stopBackgroundMusic(true);
	}

	void AudioEngine::pauseBackgroundMusic()
	{
		AudioEngineCore::pauseBackgroundMusic();
	}

	void AudioEngine::resumeBackgroundMusic()
	{
		AudioEngineCore::resumeBackgroundMusic();
	}

	void AudioEngine::stopAllSFX()
	{
		AudioEngineCore::stopAllEffects();
		m_soundRtMap.clear();
	}

	void AudioEngine::stopAllMusic()
	{
		stopMusic();
	}

	void AudioEngine::playSoundOnce(const std::string& fileName)
	{
		if (m_sfxEnabled)
		{
			AudioEngineCore::playEffect(fileName.c_str());			
		}		
	}

	void AudioEngine::playSound(unsigned int soundId,bool bLoop /* = false */)
	{
		if (m_sfxEnabled)
		{
			unsigned int rtId = AudioEngineCore::playEffect(m_soundIdResMap[soundId].c_str(),bLoop);	
			m_soundRtMap.insert(std::make_pair(soundId,rtId));
		}		
	}

	void AudioEngine::stopSound(unsigned int soundId)
	{
		SoundRTMap::iterator iter = m_soundRtMap.find(soundId);
		size_t count = m_soundRtMap.count(soundId);
		for (size_t i = 0;i < count;++i)
		{
			SoundRTMap::iterator tempIter=iter;
			AudioEngineCore::stopEffect(iter->second);
			++iter;
			m_soundRtMap.erase(tempIter);
		}	
	}

	void AudioEngine::loadSound(const std::string& fileName,unsigned int soundId)
	{
		const char* fullName = fileName.c_str();
		AudioEngineCore::preloadEffect(fullName);
		m_soundIdResMap.insert(std::make_pair(soundId,std::string(fullName)));
	}

	void AudioEngine::unLoadSound(unsigned int soundId)
	{
		stopSound(soundId);
		AudioEngineCore::unloadEffect(m_soundIdResMap[soundId].c_str());		
	}

	void AudioEngine::clearSounds()
	{
		stopAllSFX();
		for (SoundIDMap::iterator itB = m_soundIdResMap.begin(),itE=m_soundIdResMap.end();itB!=itE;++itB)
		{
			AudioEngineCore::unloadEffect(itB->second.c_str());
		}
		m_soundIdResMap.clear();		
	}	
	
	bool AudioEngine::isBGMEnabled() const
	{
		return m_bgmEnabled;
	}

	bool AudioEngine::isSFXEnabled() const
	{
		return m_sfxEnabled;
	}

	void AudioEngine::setBGMEnabled(bool bBGMEnabled)
	{
		m_bgmEnabled = bBGMEnabled;
		if (!m_bgmEnabled)
		{
			stopAllMusic();
		}		
	}

	void AudioEngine::setSFXEnabled(bool bSFXEnabled)
	{
		m_sfxEnabled = bSFXEnabled;
		if (!bSFXEnabled)
		{
			stopAllSFX();
		}		
	}
}

这部分代码用的cocos2dx的代码,cocos2dx似乎用的某个开源库,看了下,没什么好优化的。但要注意的是,android c++调用java的用法。
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
	cloud::JniHelper::setJavaVM(vm); //获取JavaVM接口
	return JNI_VERSION_1_4; //告知java使用什么版本的VM
}

namespace cloud {


JavaVM* JniHelper::_psJavaVM = nullptr;

void JniHelper::setJavaVM(JavaVM *javaVM) {
	_psJavaVM = javaVM;
}

bool JniHelper::getEnv(JNIEnv **env) {
	bool bRet = false;
	do {
		if (_psJavaVM->GetEnv((void**) env, JNI_VERSION_1_4) != JNI_OK) {
			LOG("Failed to get the environment using GetEnv()");
			break;
		}
		if (_psJavaVM->AttachCurrentThread(env, 0) < 0) {
			LOG("Failed to get the environment using AttachCurrentThread()");
			break;
		}
		bRet = true;
	} while (0);
	return bRet;
}

bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo,
		const char *methodName, const char *paramCode) {

	JNIEnv* env = nullptr;
	getEnv(&env);
	if(env != nullptr)
	{
		jclass classID = env->FindClass("com/cloudgame/org/GameJniHelper");
		jmethodID java_method = env->GetStaticMethodID(
					classID, methodName, paramCode);
			methodinfo.env = env;
			methodinfo.classID = classID;
			methodinfo.methodID = java_method;

			if (java_method == 0) {
				return false;
			}
			return true;
	}
	else
	{
		return false;
	}

}

}

这里的逻辑是一个进程会有一个jvm,但不同线程有不同的JNIEnv。
JNI_Load 是java调用System.loadLibrary("cloudGameEngine_share");时首次加载的地方。
findclass,getstaticMethodInfo,得到java中的函数。

至此,2d游戏引擎的底层架构已经完全实现,除了点击,(稍后做放到eglView中去)。接下来就是开发者会密切调用到的一些功能块的设计了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值