From b395ef06d83e510f42ad27a34009855fff111262 Mon Sep 17 00:00:00 2001 From: WenhaiLin Date: Wed, 8 Jul 2015 10:48:20 +0800 Subject: [PATCH] AudioEngine:support preload for audio[WIN32/WINRT 8.1/WP8.1] --- cocos/audio/AudioEngine.cpp | 14 +++ cocos/audio/include/AudioEngine.h | 6 + cocos/audio/win32/AudioEngine-win32.cpp | 113 ++++++++++-------- cocos/audio/win32/AudioEngine-win32.h | 1 + cocos/audio/winrt/AudioEngine-winrt.cpp | 70 ++++++----- cocos/audio/winrt/AudioEngine-winrt.h | 1 + .../NewAudioEngineTest/NewAudioEngineTest.cpp | 24 ++-- 7 files changed, 137 insertions(+), 92 deletions(-) diff --git a/cocos/audio/AudioEngine.cpp b/cocos/audio/AudioEngine.cpp index 252c8de835..6c43b6bfa9 100644 --- a/cocos/audio/AudioEngine.cpp +++ b/cocos/audio/AudioEngine.cpp @@ -415,4 +415,18 @@ AudioProfile* AudioEngine::getProfile(const std::string &name) } } +void AudioEngine::preload(const std::string& filePath) +{ + lazyInit(); + + if (_audioEngineImpl) + { + if (!FileUtils::getInstance()->isFileExist(filePath)){ + return; + } + + _audioEngineImpl->preload(filePath); + } +} + #endif diff --git a/cocos/audio/include/AudioEngine.h b/cocos/audio/include/AudioEngine.h index 6b3945fb61..8ed011dcfb 100644 --- a/cocos/audio/include/AudioEngine.h +++ b/cocos/audio/include/AudioEngine.h @@ -281,6 +281,12 @@ public: */ static AudioProfile* getProfile(const std::string &profileName); + /** + * Preload audio file. + * @param filePath The file path of an audio. + */ + static void preload(const std::string& filePath); + protected: static void remove(int audioID); diff --git a/cocos/audio/win32/AudioEngine-win32.cpp b/cocos/audio/win32/AudioEngine-win32.cpp index 573daa2867..923c6671c2 100644 --- a/cocos/audio/win32/AudioEngine-win32.cpp +++ b/cocos/audio/win32/AudioEngine-win32.cpp @@ -47,15 +47,18 @@ static ALCdevice *s_ALDevice = nullptr; static ALCcontext *s_ALContext = nullptr; static bool MPG123_LAZYINIT = true; +static AudioEngineThreadPool* s_threadPool = nullptr; + namespace cocos2d { namespace experimental { class AudioEngineThreadPool { public: AudioEngineThreadPool() - : _running(true) - , _numThread(6) + : _numThread(6) { + s_threadPool = this; + _threads.reserve(_numThread); _tasks.reserve(_numThread); @@ -88,21 +91,17 @@ namespace cocos2d { void destroy() { - _running = false; + std::unique_lock lk(_sleepMutex); _sleepCondition.notify_all(); - - for (int index = 0; index < _numThread; ++index) { - _threads[index].join(); - } - } + } + private: - bool _running; std::vector _threads; std::vector< std::function > _tasks; void threadFunc(int index) { - while (_running) { + while (s_threadPool == this) { std::function task = nullptr; _taskMutex.lock(); task = _tasks[index]; @@ -194,6 +193,54 @@ bool AudioEngineImpl::init() return ret; } +AudioCache* AudioEngineImpl::preload(const std::string& filePath) +{ + AudioCache* audioCache = nullptr; + + do + { + auto it = _audioCaches.find(filePath); + if (it != _audioCaches.end()) + { + audioCache = &it->second; + break; + } + + auto ext = strchr(filePath.c_str(), '.'); + AudioCache::FileFormat fileFormat = AudioCache::FileFormat::UNKNOWN; + + if (_stricmp(ext, ".ogg") == 0){ + fileFormat = AudioCache::FileFormat::OGG; + } + else if (_stricmp(ext, ".mp3") == 0){ + fileFormat = AudioCache::FileFormat::MP3; + + if (MPG123_LAZYINIT){ + auto error = mpg123_init(); + if (error == MPG123_OK){ + MPG123_LAZYINIT = false; + } + else{ + log("Basic setup goes wrong: %s", mpg123_plain_strerror(error)); + break; + } + } + } + else{ + log("unsupported media type:%s\n", ext); + break; + } + + audioCache = &_audioCaches[filePath]; + audioCache->_fileFormat = fileFormat; + + audioCache->_fileFullPath = FileUtils::getInstance()->fullPathForFilename(filePath); + _threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache)); + } while (false); + + return audioCache; +} + int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume) { bool availableSourceExist = false; @@ -209,48 +256,10 @@ int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume return AudioEngine::INVALID_AUDIO_ID; } - AudioCache* audioCache = nullptr; - auto it = _audioCaches.find(filePath); - if (it == _audioCaches.end()) { - audioCache = &_audioCaches[filePath]; - auto ext = strchr(filePath.c_str(), '.'); - bool eraseCache = true; - - if (_stricmp(ext, ".ogg") == 0){ - audioCache->_fileFormat = AudioCache::FileFormat::OGG; - eraseCache = false; - } - else if (_stricmp(ext, ".mp3") == 0){ - audioCache->_fileFormat = AudioCache::FileFormat::MP3; - - if (MPG123_LAZYINIT){ - auto error = mpg123_init(); - if(error == MPG123_OK){ - MPG123_LAZYINIT = false; - eraseCache = false; - } - else{ - log("Basic setup goes wrong: %s", mpg123_plain_strerror(error)); - } - } - else{ - eraseCache = false; - } - } - else{ - log("unsupported media type:%s\n", ext); - } - - if (eraseCache){ - _audioCaches.erase(filePath); - return AudioEngine::INVALID_AUDIO_ID; - } - - audioCache->_fileFullPath = FileUtils::getInstance()->fullPathForFilename(filePath); - _threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache)); - } - else { - audioCache = &it->second; + AudioCache* audioCache = preload(filePath); + if (audioCache == nullptr) + { + return AudioEngine::INVALID_AUDIO_ID; } auto player = &_audioPlayers[_currentAudioID]; diff --git a/cocos/audio/win32/AudioEngine-win32.h b/cocos/audio/win32/AudioEngine-win32.h index 8103f3d027..d290bb367b 100644 --- a/cocos/audio/win32/AudioEngine-win32.h +++ b/cocos/audio/win32/AudioEngine-win32.h @@ -61,6 +61,7 @@ public: void uncache(const std::string& filePath); void uncacheAll(); + AudioCache* preload(const std::string& filePath); void update(float dt); diff --git a/cocos/audio/winrt/AudioEngine-winrt.cpp b/cocos/audio/winrt/AudioEngine-winrt.cpp index 22a322171e..4306bd8b46 100644 --- a/cocos/audio/winrt/AudioEngine-winrt.cpp +++ b/cocos/audio/winrt/AudioEngine-winrt.cpp @@ -142,45 +142,53 @@ bool AudioEngineImpl::init() return ret; } -int AudioEngineImpl::play2d(const std::string &filePath, bool loop, float volume) +AudioCache* AudioEngineImpl::preload(const std::string& filePath) { AudioCache* audioCache = nullptr; - auto it = _audioCaches.find(filePath); - if (it == _audioCaches.end()) { - audioCache = &_audioCaches[filePath]; + do + { + auto it = _audioCaches.find(filePath); + if (it == _audioCaches.end()) { + FileFormat fileFormat = FileFormat::UNKNOWN; - auto ext = filePath.substr(filePath.rfind('.')); - transform(ext.begin(), ext.end(), ext.begin(), tolower); + auto ext = filePath.substr(filePath.rfind('.')); + transform(ext.begin(), ext.end(), ext.begin(), tolower); - bool eraseCache = true; + if (ext.compare(".wav") == 0){ + fileFormat = FileFormat::WAV; + } + else if (ext.compare(".ogg") == 0){ + fileFormat = FileFormat::OGG; + } + else if (ext.compare(".mp3") == 0){ + fileFormat = FileFormat::MP3; + } + else{ + log("unsupported media type:%s\n", ext.c_str()); + break; + } - if (ext.compare(".wav") == 0){ - audioCache->_fileFormat = FileFormat::WAV; - eraseCache = false; - } - else if (ext.compare(".ogg") == 0){ - audioCache->_fileFormat = FileFormat::OGG; - eraseCache = false; - } - else if (ext.compare(".mp3") == 0){ - audioCache->_fileFormat = FileFormat::MP3; - eraseCache = false; - } - else{ - log("unsupported media type:%s\n", ext.c_str()); - } + audioCache = &_audioCaches[filePath]; + audioCache->_fileFormat = fileFormat; - if (eraseCache){ - _audioCaches.erase(filePath); - return AudioEngine::INVALID_AUDIO_ID; + std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filePath); + audioCache->_fileFullPath = fullPath; + _threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache)); } + else { + audioCache = &it->second; + } + } while (false); - std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filePath); - audioCache->_fileFullPath = fullPath; - _threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache)); - } - else { - audioCache = &it->second; + return audioCache; +} + +int AudioEngineImpl::play2d(const std::string &filePath, bool loop, float volume) +{ + auto audioCache = preload(filePath); + if (audioCache == nullptr) + { + return AudioEngine::INVALID_AUDIO_ID; } auto player = &_audioPlayers[_currentAudioID]; diff --git a/cocos/audio/winrt/AudioEngine-winrt.h b/cocos/audio/winrt/AudioEngine-winrt.h index 906ab7ff31..3ab18f2a43 100644 --- a/cocos/audio/winrt/AudioEngine-winrt.h +++ b/cocos/audio/winrt/AudioEngine-winrt.h @@ -58,6 +58,7 @@ NS_CC_BEGIN void setFinishCallback(int audioID, const std::function &callback); void uncache(const std::string& filePath); void uncacheAll(); + AudioCache* preload(const std::string& filePath); void update(float dt); private: diff --git a/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp index a506c286a5..deddfa470b 100644 --- a/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp +++ b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.cpp @@ -303,7 +303,7 @@ bool AudioControlTest::init() } }); _playItem = playItem; - playItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.7f); + playItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.8f); addChild(playItem); auto stopItem = TextButton::create("stop", [&](TextButton* button){ @@ -314,7 +314,7 @@ bool AudioControlTest::init() ((TextButton*)_playItem)->setEnabled(true); } }); - stopItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.7f); + stopItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.8f); addChild(stopItem); auto pauseItem = TextButton::create("pause", [&](TextButton* button){ @@ -322,7 +322,7 @@ bool AudioControlTest::init() AudioEngine::pause(_audioID); } }); - pauseItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.6f); + pauseItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.7f); addChild(pauseItem); auto resumeItem = TextButton::create("resume", [&](TextButton* button){ @@ -330,32 +330,38 @@ bool AudioControlTest::init() AudioEngine::resume(_audioID); } }); - resumeItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.6f); + resumeItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.7f); addChild(resumeItem); auto loopItem = TextButton::create("enable-loop", [&](TextButton* button){ _loopEnabled = !_loopEnabled; - - if (_audioID != AudioEngine::INVALID_AUDIO_ID ) { + + if (_audioID != AudioEngine::INVALID_AUDIO_ID) { AudioEngine::setLoop(_audioID, _loopEnabled); } - if(_loopEnabled){ + if (_loopEnabled){ button->setString("disable-loop"); } else { button->setString("enable-loop"); } }); - loopItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.5f); + loopItem->setPosition(layerSize.width * 0.5f, layerSize.height * 0.5f); addChild(loopItem); + auto preloadItem = TextButton::create("preload", [&](TextButton* button){ + AudioEngine::preload("background.mp3"); + }); + preloadItem->setPosition(layerSize.width * 0.3f, layerSize.height * 0.6f); + addChild(preloadItem); + auto uncacheItem = TextButton::create("uncache", [&](TextButton* button){ AudioEngine::uncache("background.mp3"); _audioID = AudioEngine::INVALID_AUDIO_ID; ((TextButton*)_playItem)->setEnabled(true); }); - uncacheItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.5f); + uncacheItem->setPosition(layerSize.width * 0.7f,layerSize.height * 0.6f); addChild(uncacheItem); auto volumeSlider = SliderEx::create();