最近在做项目的过程中遇到一个需求,需要改变项目中原有背景音乐的音量
但是cocos2dx在win32平台下setBackgroundMusicVolume(float volume)函数是没有实现的
这就尴尬了
我设置了半天这玩意儿不起作用
但是项目中又需要实现这样的功能
那么问题就来了?
挖掘机技术哪家强!!!!
其实cocos2dx对安卓以及ios系统这个函数是实现了的,在安卓版本中是可以实现对背景音量的控制的
但是在TestCpp项目中,这个改变背景音乐的功能是不起作用的
在对项目功能实现之后我也把源码拿出来分享了
这免得走弯路啊
虽然改的东西不是很多
但是涉及到的东西还是比较多的
下面是引擎源码有改动的地方
1. CocosDenshion\include文件夹下的SimpleAudioEngine.h文件
/**************************************************************************** Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2010 Steve Oldmeadow http://www.cocos2d-x.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef _SIMPLE_AUDIO_ENGINE_H_ #define _SIMPLE_AUDIO_ENGINE_H_ #include <stddef.h> #include "Export.h" #include <typeinfo> #include <ctype.h> #include <string.h> namespace CocosDenshion { class TypeInfo { public: virtual long getClassTypeInfo() = 0; }; static inline unsigned int getHashCodeByString(const char *key) { unsigned int len = strlen(key); const char *end=key+len; unsigned int hash; for (hash = 0; key < end; key++) { hash *= 16777619; hash ^= (unsigned int) (unsigned char) toupper(*key); } return (hash); } /** @class SimpleAudioEngine @brief offer a VERY simple interface to play background music & sound effect */ class EXPORT_DLL SimpleAudioEngine : public TypeInfo { public: SimpleAudioEngine(); ~SimpleAudioEngine(); virtual long getClassTypeInfo() { return getHashCodeByString(typeid(CocosDenshion::SimpleAudioEngine).name()); } /** @brief Get the shared Engine object,it will new one when first time be called */ static SimpleAudioEngine* sharedEngine(); /** @brief Release the shared Engine object @warning It must be called before the application exit, or a memroy leak will be casued. */ static void end(); /** @brief Preload background music @param pszFilePath The path of the background music file,or the FileName of T_SoundResInfo */ void preloadBackgroundMusic(const char* pszFilePath); /** @brief Play background music @param pszFilePath The path of the background music file,or the FileName of T_SoundResInfo @param bLoop Whether the background music loop or not */ void playBackgroundMusic(const char* pszFilePath, bool bLoop); void playBackgroundMusic(const char* pszFilePath) { this->playBackgroundMusic(pszFilePath, false); } /** @brief Stop playing background music @param bReleaseData If release the background music data or not.As default value is false */ void stopBackgroundMusic(bool bReleaseData); void stopBackgroundMusic() { this->stopBackgroundMusic(false); } /** @brief Pause playing background music */ void pauseBackgroundMusic(); /** @brief Resume playing background music */ void resumeBackgroundMusic(); /** @brief Rewind playing background music */ void rewindBackgroundMusic(); bool willPlayBackgroundMusic(); /** @brief Whether the background music is playing @return If is playing return true,or return false */ bool isBackgroundMusicPlaying(); // properties /** @brief The volume of the background music max value is 1.0,the min value is 0.0 */ float getBackgroundMusicVolume(); /** @brief set the volume of background music @param volume must be in 0.0~1.0 */ void setBackgroundMusicVolume(float volume); /** @brief The volume of the effects max value is 1.0,the min value is 0.0 */ float getEffectsVolume(); /** @brief set the volume of sound effecs @param volume must be in 0.0~1.0 */ void setEffectsVolume(float volume); // for sound effects /** @brief Play sound effect @param pszFilePath The path of the effect file,or the FileName of T_SoundResInfo @bLoop Whether to loop the effect playing, default value is false */ unsigned int playEffect(const char* pszFilePath, bool bLoop); unsigned int playEffect(const char* pszFilePath) { return this->playEffect(pszFilePath, false); } /** @brief Pause playing sound effect @param nSoundId The return value of function playEffect */ void pauseEffect(unsigned int nSoundId); /** @brief Pause all playing sound effect @param nSoundId The return value of function playEffect */ void pauseAllEffects(); /** @brief Resume playing sound effect @param nSoundId The return value of function playEffect */ void resumeEffect(unsigned int nSoundId); /** @brief Resume all playing sound effect @param nSoundId The return value of function playEffect */ void resumeAllEffects(); /** @brief Stop playing sound effect @param nSoundId The return value of function playEffect */ void stopEffect(unsigned int nSoundId); /** @brief Stop all playing sound effects */ void stopAllEffects(); /** @brief preload a compressed audio file @details the compressed audio will be decode to wave, then write into an internal buffer in SimpleaudioEngine */ void preloadEffect(const char* pszFilePath); /** @brief unload the preloaded effect from internal buffer @param[in] pszFilePath The path of the effect file,or the FileName of T_SoundResInfo */ void unloadEffect(const char* pszFilePath); private: float m_effectsVolume; }; } // end of namespace CocosDenshion #endif // _SIMPLE_AUDIO_ENGINE_H_
#include "SimpleAudioEngine.h" #include <map> #include <cstdlib> #include "MciPlayer.h" #include "cocos2d.h" USING_NS_CC; using namespace std; namespace CocosDenshion { typedef map<unsigned int, MciPlayer *> EffectList; typedef pair<unsigned int, MciPlayer *> Effect; static char s_szRootPath[MAX_PATH]; static DWORD s_dwRootLen; static char s_szFullPath[MAX_PATH]; static std::string _FullPath(const char * szPath); static unsigned int _Hash(const char *key); #define BREAK_IF(cond) if (cond) break; static EffectList& sharedList() { static EffectList s_List; return s_List; } static MciPlayer& sharedMusic() { static MciPlayer s_Music; return s_Music; } SimpleAudioEngine::SimpleAudioEngine() : m_effectsVolume(1.0f) { } SimpleAudioEngine::~SimpleAudioEngine() { } SimpleAudioEngine* SimpleAudioEngine::sharedEngine() { static SimpleAudioEngine s_SharedEngine; return &s_SharedEngine; } void SimpleAudioEngine::end() { sharedMusic().Close(); EffectList::iterator p = sharedList().begin(); while (p != sharedList().end()) { delete p->second; p->second = NULL; p++; } sharedList().clear(); return; } ////////////////////////////////////////////////////////////////////////// // BackgroundMusic ////////////////////////////////////////////////////////////////////////// void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop) { if (! pszFilePath) { return; } sharedMusic().Open(_FullPath(pszFilePath).c_str(), _Hash(pszFilePath)); sharedMusic().Play((bLoop) ? -1 : 1); } void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData) { if (bReleaseData) { sharedMusic().Close(); } else { sharedMusic().Stop(); } } void SimpleAudioEngine::pauseBackgroundMusic() { sharedMusic().Pause(); } void SimpleAudioEngine::resumeBackgroundMusic() { sharedMusic().Resume(); } void SimpleAudioEngine::rewindBackgroundMusic() { sharedMusic().Rewind(); } bool SimpleAudioEngine::willPlayBackgroundMusic() { return false; } bool SimpleAudioEngine::isBackgroundMusicPlaying() { return sharedMusic().IsPlaying(); } ////////////////////////////////////////////////////////////////////////// // effect function ////////////////////////////////////////////////////////////////////////// unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop) { unsigned int nRet = _Hash(pszFilePath); preloadEffect(pszFilePath); EffectList::iterator p = sharedList().find(nRet); if (p != sharedList().end()) { p->second->Play((bLoop) ? -1 : 1); p->second->SetVolume((UINT) (m_effectsVolume * 1000.0)); } return nRet; } void SimpleAudioEngine::stopEffect(unsigned int nSoundId) { EffectList::iterator p = sharedList().find(nSoundId); if (p != sharedList().end()) { p->second->Stop(); } } void SimpleAudioEngine::preloadEffect(const char* pszFilePath) { int nRet = 0; do { BREAK_IF(! pszFilePath); nRet = _Hash(pszFilePath); BREAK_IF(sharedList().end() != sharedList().find(nRet)); sharedList().insert(Effect(nRet, new MciPlayer())); MciPlayer * pPlayer = sharedList()[nRet]; pPlayer->Open(_FullPath(pszFilePath).c_str(), nRet); BREAK_IF(nRet == pPlayer->GetSoundID()); sharedList().erase(nRet); nRet = 0; } while (0); } void SimpleAudioEngine::pauseEffect(unsigned int nSoundId) { EffectList::iterator p = sharedList().find(nSoundId); if (p != sharedList().end()) { p->second->Pause(); } } void SimpleAudioEngine::pauseAllEffects() { EffectList::iterator iter; for (iter = sharedList().begin(); iter != sharedList().end(); iter++) { iter->second->Pause(); } } void SimpleAudioEngine::resumeEffect(unsigned int nSoundId) { EffectList::iterator p = sharedList().find(nSoundId); if (p != sharedList().end()) { p->second->Resume(); } } void SimpleAudioEngine::resumeAllEffects() { EffectList::iterator iter; for (iter = sharedList().begin(); iter != sharedList().end(); iter++) { iter->second->Resume(); } } void SimpleAudioEngine::stopAllEffects() { EffectList::iterator iter; for (iter = sharedList().begin(); iter != sharedList().end(); iter++) { iter->second->Stop(); } } void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath) { } void SimpleAudioEngine::unloadEffect(const char* pszFilePath) { unsigned int nID = _Hash(pszFilePath); EffectList::iterator p = sharedList().find(nID); if (p != sharedList().end()) { delete p->second; p->second = NULL; sharedList().erase(nID); } } ////////////////////////////////////////////////////////////////////////// // volume interface ////////////////////////////////////////////////////////////////////////// float SimpleAudioEngine::getBackgroundMusicVolume() { return sharedMusic().GetVolume() / 1000.0f; } void SimpleAudioEngine::setBackgroundMusicVolume(float volume) { sharedMusic().SetVolume((UINT) (volume * 1000.0)); } float SimpleAudioEngine::getEffectsVolume() { return m_effectsVolume; } void SimpleAudioEngine::setEffectsVolume(float volume) { m_effectsVolume = volume; EffectList::iterator iter; for (iter = sharedList().begin(); iter != sharedList().end(); iter++) { iter->second->SetVolume((UINT) (volume * 1000.0)); } } ////////////////////////////////////////////////////////////////////////// // static function ////////////////////////////////////////////////////////////////////////// static std::string _FullPath(const char * szPath) { return CCFileUtils::sharedFileUtils()->fullPathForFilename(szPath); } unsigned int _Hash(const char *key) { unsigned int len = strlen(key); const char *end=key+len; unsigned int hash; for (hash = 0; key < end; key++) { hash *= 16777619; hash ^= (unsigned int) (unsigned char) toupper(*key); } return (hash); } } // end of namespace CocosDenshion
#ifndef _MCI_PLAYER_WIN32_H_ #define _MCI_PLAYER_WIN32_H_ #include "CCStdC.h" #include <mmsystem.h> namespace CocosDenshion { class MciPlayer { public: MciPlayer(); ~MciPlayer(); void Close(); /** @brief 播放声音文件 @param pFileName 播放的声音文件名称,需要包含文件的路径 @param nTimes 播放声音文件的循环次数,默认值为 1,即播放一次 */ void Open(const char* pFileName, UINT uId); void Play(UINT uTimes = 1); /** @brief 暂停播放声音 */ void Pause(); /** @brief 继续播放声音 */ void Resume(); /** @brief 停止播放声音 */ void Stop(); /** @brief 重新播放 */ void Rewind(); /** @brief 获取播放器当前是否正在播放中 */ bool IsPlaying(); /** @brief 获取当前播放的音效 ID @return 当前播放的音效ID */ UINT GetSoundID(); // @volume value ranges from 0 .. 1000 void SetVolume(UINT volume); // @return value ranges from 0 .. 1000 UINT GetVolume() const; private: friend LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); void _SendGenericCommand(int nCommand); HWND m_hWnd; MCIDEVICEID m_hDev; UINT m_nSoundID; UINT m_uTimes; bool m_bPlaying; }; } // end of namespace CocosDenshion #endif
#include "MciPlayer.h" #include <Digitalv.h> #define WIN_CLASS_NAME "CocosDenshionCallbackWnd" #define BREAK_IF(cond) if (cond) break; namespace CocosDenshion { static HINSTANCE s_hInstance; static MCIERROR s_mciError; static LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); MciPlayer::MciPlayer() : m_hWnd(NULL) , m_hDev(NULL) , m_nSoundID(0) , m_uTimes(0) , m_bPlaying(false) { if (! s_hInstance) { s_hInstance = GetModuleHandle( NULL ); // Grab An Instance For Our Window WNDCLASS wc; // Windows Class Structure // Redraw On Size, And Own DC For Window. wc.style = 0; wc.lpfnWndProc = _SoundPlayProc; // WndProc Handles Messages wc.cbClsExtra = 0; // No Extra Window Data wc.cbWndExtra = 0; // No Extra Window Data wc.hInstance = s_hInstance; // Set The Instance wc.hIcon = 0; // Load The Default Icon wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load The Arrow Pointer wc.hbrBackground = NULL; // No Background Required For GL wc.lpszMenuName = NULL; // We Don't Want A Menu wc.lpszClassName = WIN_CLASS_NAME; // Set The Class Name if (! RegisterClass(&wc) && 1410 != GetLastError()) { return; } } m_hWnd = CreateWindowEx( WS_EX_APPWINDOW, // Extended Style For The Window WIN_CLASS_NAME, // Class Name NULL, // Window Title WS_POPUPWINDOW,/*WS_OVERLAPPEDWINDOW*/ // Defined Window Style 0, 0, // Window Position 0, // Window Width 0, // Window Height NULL, // No Parent Window NULL, // No Menu s_hInstance, // Instance NULL ); if (m_hWnd) { SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); } } MciPlayer::~MciPlayer() { Close(); DestroyWindow(m_hWnd); } void MciPlayer::Open(const char* pFileName, UINT uId) { // WCHAR * pBuf = NULL; do { BREAK_IF(! pFileName || ! m_hWnd); int nLen = (int)strlen(pFileName); BREAK_IF(! nLen); // pBuf = new WCHAR[nLen + 1]; // BREAK_IF(! pBuf); // MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, pBuf, nLen + 1); Close(); MCI_OPEN_PARMS mciOpen = {0}; MCIERROR mciError; mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID; mciOpen.lpstrElementName = pFileName; mciError = mciSendCommand(0,MCI_OPEN, MCI_OPEN_ELEMENT, (DWORD)&mciOpen); BREAK_IF(mciError); m_hDev = mciOpen.wDeviceID; m_nSoundID = uId; m_bPlaying = false; } while (0); } void MciPlayer::SetVolume(UINT volume) { if (!m_hDev) return; MCI_DGV_SETAUDIO_PARMS mciParams = {0}; mciParams.dwItem = MCI_DGV_SETAUDIO_VOLUME; mciParams.dwValue = volume; mciSendCommand(m_hDev, MCI_SETAUDIO, MCI_DGV_SETAUDIO_ITEM | MCI_DGV_SETAUDIO_VALUE, (DWORD)&mciParams); } UINT MciPlayer::GetVolume() const { if (!m_hDev) return 0; MCI_STATUS_PARMS mciParams = {0}; mciParams.dwItem = MCI_DGV_STATUS_VOLUME; mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)&mciParams); return mciParams.dwReturn; } void MciPlayer::Play(UINT uTimes /* = 1 */) { if (! m_hDev) { return; } MCI_PLAY_PARMS mciPlay = {0}; mciPlay.dwCallback = (DWORD_PTR)m_hWnd; s_mciError = mciSendCommand(m_hDev,MCI_PLAY, MCI_FROM|MCI_NOTIFY,(DWORD)&mciPlay); if (! s_mciError) { m_bPlaying = true; m_uTimes = uTimes; } } void MciPlayer::Close() { if (m_bPlaying) { Stop(); } if (m_hDev) { _SendGenericCommand(MCI_CLOSE); } m_hDev = 0; m_bPlaying = false; } void MciPlayer::Pause() { _SendGenericCommand(MCI_PAUSE); } void MciPlayer::Resume() { _SendGenericCommand(MCI_RESUME); } void MciPlayer::Stop() { _SendGenericCommand(MCI_STOP); m_bPlaying = false; } void MciPlayer::Rewind() { if (! m_hDev) { return; } mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0); MCI_PLAY_PARMS mciPlay = {0}; mciPlay.dwCallback = (DWORD)m_hWnd; m_bPlaying = mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY,(DWORD)&mciPlay) ? false : true; } bool MciPlayer::IsPlaying() { return m_bPlaying; } UINT MciPlayer::GetSoundID() { return m_nSoundID; } ////////////////////////////////////////////////////////////////////////// // private member ////////////////////////////////////////////////////////////////////////// void MciPlayer::_SendGenericCommand(int nCommand) { if (! m_hDev) { return; } mciSendCommand(m_hDev, nCommand, 0, 0); } ////////////////////////////////////////////////////////////////////////// // static function ////////////////////////////////////////////////////////////////////////// LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { MciPlayer * pPlayer = NULL; if (MM_MCINOTIFY == Msg && MCI_NOTIFY_SUCCESSFUL == wParam &&(pPlayer = (MciPlayer *)GetWindowLong(hWnd, GWL_USERDATA))) { if (pPlayer->m_uTimes) { --pPlayer->m_uTimes; } if (pPlayer->m_uTimes) { mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0); MCI_PLAY_PARMS mciPlay = {0}; mciPlay.dwCallback = (DWORD)hWnd; mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY,(DWORD)&mciPlay); } else { pPlayer->m_bPlaying = false; } return 0; } return DefWindowProc(hWnd, Msg, wParam, lParam); } } // end of namespace CocosDenshion
http://download.csdn.net/detail/u013476751/8162815
不要问我名字,请叫我雷锋。