AudioEngine:support preload for audio[WIN32/WINRT 8.1/WP8.1]

This commit is contained in:
WenhaiLin 2015-07-08 10:48:20 +08:00
parent 1b9b741068
commit b395ef06d8
7 changed files with 137 additions and 92 deletions

View File

@ -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 #endif

View File

@ -281,6 +281,12 @@ public:
*/ */
static AudioProfile* getProfile(const std::string &profileName); 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: protected:
static void remove(int audioID); static void remove(int audioID);

View File

@ -47,15 +47,18 @@ static ALCdevice *s_ALDevice = nullptr;
static ALCcontext *s_ALContext = nullptr; static ALCcontext *s_ALContext = nullptr;
static bool MPG123_LAZYINIT = true; static bool MPG123_LAZYINIT = true;
static AudioEngineThreadPool* s_threadPool = nullptr;
namespace cocos2d { namespace cocos2d {
namespace experimental { namespace experimental {
class AudioEngineThreadPool class AudioEngineThreadPool
{ {
public: public:
AudioEngineThreadPool() AudioEngineThreadPool()
: _running(true) : _numThread(6)
, _numThread(6)
{ {
s_threadPool = this;
_threads.reserve(_numThread); _threads.reserve(_numThread);
_tasks.reserve(_numThread); _tasks.reserve(_numThread);
@ -88,21 +91,17 @@ namespace cocos2d {
void destroy() void destroy()
{ {
_running = false; std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.notify_all(); _sleepCondition.notify_all();
for (int index = 0; index < _numThread; ++index) {
_threads[index].join();
}
} }
private: private:
bool _running;
std::vector<std::thread> _threads; std::vector<std::thread> _threads;
std::vector< std::function<void ()> > _tasks; std::vector< std::function<void ()> > _tasks;
void threadFunc(int index) void threadFunc(int index)
{ {
while (_running) { while (s_threadPool == this) {
std::function<void ()> task = nullptr; std::function<void ()> task = nullptr;
_taskMutex.lock(); _taskMutex.lock();
task = _tasks[index]; task = _tasks[index];
@ -194,6 +193,54 @@ bool AudioEngineImpl::init()
return ret; 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) int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume)
{ {
bool availableSourceExist = false; bool availableSourceExist = false;
@ -209,48 +256,10 @@ int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume
return AudioEngine::INVALID_AUDIO_ID; return AudioEngine::INVALID_AUDIO_ID;
} }
AudioCache* audioCache = nullptr; AudioCache* audioCache = preload(filePath);
auto it = _audioCaches.find(filePath); if (audioCache == nullptr)
if (it == _audioCaches.end()) { {
audioCache = &_audioCaches[filePath]; return AudioEngine::INVALID_AUDIO_ID;
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;
} }
auto player = &_audioPlayers[_currentAudioID]; auto player = &_audioPlayers[_currentAudioID];

View File

@ -61,6 +61,7 @@ public:
void uncache(const std::string& filePath); void uncache(const std::string& filePath);
void uncacheAll(); void uncacheAll();
AudioCache* preload(const std::string& filePath);
void update(float dt); void update(float dt);

View File

@ -142,45 +142,53 @@ bool AudioEngineImpl::init()
return ret; return ret;
} }
int AudioEngineImpl::play2d(const std::string &filePath, bool loop, float volume) AudioCache* AudioEngineImpl::preload(const std::string& filePath)
{ {
AudioCache* audioCache = nullptr; AudioCache* audioCache = nullptr;
auto it = _audioCaches.find(filePath); do
if (it == _audioCaches.end()) { {
audioCache = &_audioCaches[filePath]; auto it = _audioCaches.find(filePath);
if (it == _audioCaches.end()) {
FileFormat fileFormat = FileFormat::UNKNOWN;
auto ext = filePath.substr(filePath.rfind('.')); auto ext = filePath.substr(filePath.rfind('.'));
transform(ext.begin(), ext.end(), ext.begin(), tolower); 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 = &_audioCaches[filePath];
audioCache->_fileFormat = FileFormat::WAV; audioCache->_fileFormat = fileFormat;
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());
}
if (eraseCache){ std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filePath);
_audioCaches.erase(filePath); audioCache->_fileFullPath = fullPath;
return AudioEngine::INVALID_AUDIO_ID; _threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache));
} }
else {
audioCache = &it->second;
}
} while (false);
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filePath); return audioCache;
audioCache->_fileFullPath = fullPath; }
_threadPool->addTask(std::bind(&AudioCache::readDataTask, audioCache));
} int AudioEngineImpl::play2d(const std::string &filePath, bool loop, float volume)
else { {
audioCache = &it->second; auto audioCache = preload(filePath);
if (audioCache == nullptr)
{
return AudioEngine::INVALID_AUDIO_ID;
} }
auto player = &_audioPlayers[_currentAudioID]; auto player = &_audioPlayers[_currentAudioID];

View File

@ -58,6 +58,7 @@ NS_CC_BEGIN
void setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback); void setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback);
void uncache(const std::string& filePath); void uncache(const std::string& filePath);
void uncacheAll(); void uncacheAll();
AudioCache* preload(const std::string& filePath);
void update(float dt); void update(float dt);
private: private:

View File

@ -303,7 +303,7 @@ bool AudioControlTest::init()
} }
}); });
_playItem = playItem; _playItem = playItem;
playItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.7f); playItem->setPosition(layerSize.width * 0.3f,layerSize.height * 0.8f);
addChild(playItem); addChild(playItem);
auto stopItem = TextButton::create("stop", [&](TextButton* button){ auto stopItem = TextButton::create("stop", [&](TextButton* button){
@ -314,7 +314,7 @@ bool AudioControlTest::init()
((TextButton*)_playItem)->setEnabled(true); ((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); addChild(stopItem);
auto pauseItem = TextButton::create("pause", [&](TextButton* button){ auto pauseItem = TextButton::create("pause", [&](TextButton* button){
@ -322,7 +322,7 @@ bool AudioControlTest::init()
AudioEngine::pause(_audioID); 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); addChild(pauseItem);
auto resumeItem = TextButton::create("resume", [&](TextButton* button){ auto resumeItem = TextButton::create("resume", [&](TextButton* button){
@ -330,32 +330,38 @@ bool AudioControlTest::init()
AudioEngine::resume(_audioID); 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); addChild(resumeItem);
auto loopItem = TextButton::create("enable-loop", [&](TextButton* button){ auto loopItem = TextButton::create("enable-loop", [&](TextButton* button){
_loopEnabled = !_loopEnabled; _loopEnabled = !_loopEnabled;
if (_audioID != AudioEngine::INVALID_AUDIO_ID ) { if (_audioID != AudioEngine::INVALID_AUDIO_ID) {
AudioEngine::setLoop(_audioID, _loopEnabled); AudioEngine::setLoop(_audioID, _loopEnabled);
} }
if(_loopEnabled){ if (_loopEnabled){
button->setString("disable-loop"); button->setString("disable-loop");
} }
else { else {
button->setString("enable-loop"); 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); 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){ auto uncacheItem = TextButton::create("uncache", [&](TextButton* button){
AudioEngine::uncache("background.mp3"); AudioEngine::uncache("background.mp3");
_audioID = AudioEngine::INVALID_AUDIO_ID; _audioID = AudioEngine::INVALID_AUDIO_ID;
((TextButton*)_playItem)->setEnabled(true); ((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); addChild(uncacheItem);
auto volumeSlider = SliderEx::create(); auto volumeSlider = SliderEx::create();