Merge pull request #12742 from WenhaiLin/v3-audioengine-preload

AudioEngine:support preload for audio
This commit is contained in:
子龙山人 2015-07-13 17:06:17 +08:00
commit db71e073dd
11 changed files with 290 additions and 391 deletions

View File

@ -23,6 +23,7 @@
****************************************************************************/
#include "platform/CCPlatformConfig.h"
#include <condition_variable>
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
@ -61,8 +62,110 @@ AudioEngine::ProfileHelper* AudioEngine::_defaultProfileHelper = nullptr;
std::unordered_map<int, AudioEngine::AudioInfo> AudioEngine::_audioIDInfoMap;
AudioEngineImpl* AudioEngine::_audioEngineImpl = nullptr;
AudioEngine::AudioEngineThreadPool* AudioEngine::s_threadPool = nullptr;
class AudioEngine::AudioEngineThreadPool
{
public:
AudioEngineThreadPool(bool detach)
: _numThread(6)
, _detach(detach)
{
s_threadPool = this;
_threads.reserve(_numThread);
_tasks.reserve(_numThread);
for (int index = 0; index < _numThread; ++index) {
_tasks.push_back(nullptr);
_threads.push_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this, index)));
if (_detach)
{
_threads[index].detach();
}
}
}
void addTask(const std::function<void()> &task){
_taskMutex.lock();
int targetIndex = -1;
for (int index = 0; index < _numThread; ++index) {
if (_tasks[index] == nullptr) {
targetIndex = index;
_tasks[index] = task;
break;
}
}
if (targetIndex == -1) {
_tasks.push_back(task);
_threads.push_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this, _numThread)));
if (_detach)
{
_threads[_numThread].detach();
}
_numThread++;
}
_taskMutex.unlock();
_sleepCondition.notify_all();
}
void destroy()
{
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.notify_all();
if (!_detach)
{
for (int index = 0; index < _numThread; ++index) {
_threads[index].join();
}
}
}
private:
std::vector<std::thread> _threads;
std::vector< std::function<void()> > _tasks;
void threadFunc(int index)
{
while (s_threadPool == this) {
std::function<void()> task = nullptr;
_taskMutex.lock();
task = _tasks[index];
_taskMutex.unlock();
if (nullptr == task)
{
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.wait(lk);
continue;
}
task();
_taskMutex.lock();
_tasks[index] = nullptr;
_taskMutex.unlock();
}
}
int _numThread;
std::mutex _taskMutex;
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
bool _detach;
};
void AudioEngine::end()
{
if (s_threadPool)
{
s_threadPool->destroy();
delete s_threadPool;
s_threadPool = nullptr;
}
delete _audioEngineImpl;
_audioEngineImpl = nullptr;
@ -82,6 +185,18 @@ bool AudioEngine::lazyInit()
}
}
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
if (_audioEngineImpl && s_threadPool == nullptr)
{
s_threadPool = new (std::nothrow) AudioEngineThreadPool(true);
}
#elif CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
if (_audioEngineImpl && s_threadPool == nullptr)
{
s_threadPool = new (std::nothrow) AudioEngineThreadPool(false);
}
#endif
return true;
}
@ -415,4 +530,28 @@ 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);
}
}
void AudioEngine::addTask(const std::function<void()> &task)
{
lazyInit();
if (_audioEngineImpl && s_threadPool)
{
s_threadPool->addTask(task);
}
}
#endif

View File

@ -1,5 +1,5 @@
/****************************************************************************
Copyright (c) 2014 Chukong Technologies Inc.
Copyright (c) 2014-2015 Chukong Technologies Inc.
http://www.cocos2d-x.org
@ -432,4 +432,9 @@ void AudioEngineImpl::setFinishCallback(int audioID, const std::function<void (i
_audioPlayers[audioID]._finishCallback = callback;
}
void AudioEngineImpl::preload(const std::string& filePath)
{
CCLOG("Preload not support on Anroid");
}
#endif

View File

@ -1,5 +1,5 @@
/****************************************************************************
Copyright (c) 2014 Chukong Technologies Inc.
Copyright (c) 2014-2015 Chukong Technologies Inc.
http://www.cocos2d-x.org
@ -88,6 +88,7 @@ public:
void uncache(const std::string& filePath){}
void uncacheAll(){}
void preload(const std::string& filePath);
void update(float dt);
private:

View File

@ -38,8 +38,6 @@ NS_CC_BEGIN
namespace experimental{
#define MAX_AUDIOINSTANCES 24
class AudioEngineThreadPool;
class AudioEngineImpl : public cocos2d::Ref
{
public:
@ -61,14 +59,12 @@ public:
void uncache(const std::string& filePath);
void uncacheAll();
AudioCache* preload(const std::string& filePath);
void update(float dt);
private:
void _play2d(AudioCache *cache, int audioID);
AudioEngineThreadPool* _threadPool;
ALuint _alSources[MAX_AUDIOINSTANCES];
//source,used

View File

@ -42,93 +42,6 @@ using namespace cocos2d::experimental;
static ALCdevice *s_ALDevice = nullptr;
static ALCcontext *s_ALContext = nullptr;
namespace cocos2d {
namespace experimental {
class AudioEngineThreadPool
{
public:
AudioEngineThreadPool()
: _running(true)
, _numThread(6)
{
_threads.reserve(_numThread);
_tasks.reserve(_numThread);
for (int index = 0; index < _numThread; ++index) {
_tasks.push_back(nullptr);
_threads.push_back( std::thread( std::bind(&AudioEngineThreadPool::threadFunc,this,index) ) );
}
}
void addTask(const std::function<void()> &task){
_taskMutex.lock();
int targetIndex = -1;
for (int index = 0; index < _numThread; ++index) {
if (_tasks[index] == nullptr) {
targetIndex = index;
_tasks[index] = task;
break;
}
}
if (targetIndex == -1) {
_tasks.push_back(task);
_threads.push_back( std::thread( std::bind(&AudioEngineThreadPool::threadFunc,this,_numThread) ) );
_numThread++;
}
_taskMutex.unlock();
_sleepCondition.notify_all();
}
void destroy()
{
_running = false;
_sleepCondition.notify_all();
for (int index = 0; index < _numThread; ++index) {
_threads[index].join();
}
}
private:
bool _running;
std::vector<std::thread> _threads;
std::vector< std::function<void ()> > _tasks;
void threadFunc(int index)
{
while (_running) {
std::function<void ()> task = nullptr;
_taskMutex.lock();
task = _tasks[index];
_taskMutex.unlock();
if (nullptr == task)
{
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.wait(lk);
continue;
}
task();
_taskMutex.lock();
_tasks[index] = nullptr;
_taskMutex.unlock();
}
}
int _numThread;
std::mutex _taskMutex;
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
};
}
}
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
@interface AudioEngineSessionHandler : NSObject
{
@ -220,8 +133,7 @@ static id s_AudioEngineSessionHandler = nullptr;
#endif
AudioEngineImpl::AudioEngineImpl()
: _threadPool(nullptr)
, _lazyInitLoop(true)
: _lazyInitLoop(true)
, _currentAudioID(0)
{
@ -240,10 +152,7 @@ AudioEngineImpl::~AudioEngineImpl()
if (s_ALDevice) {
alcCloseDevice(s_ALDevice);
}
if (_threadPool) {
_threadPool->destroy();
delete _threadPool;
}
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
[s_AudioEngineSessionHandler release];
#endif
@ -275,7 +184,6 @@ bool AudioEngineImpl::init()
_alSourceUsed[_alSources[i]] = false;
}
_threadPool = new (std::nothrow) AudioEngineThreadPool();
ret = true;
}
}while (false);
@ -283,6 +191,24 @@ bool AudioEngineImpl::init()
return ret;
}
AudioCache* AudioEngineImpl::preload(const std::string& filePath)
{
AudioCache* audioCache = nullptr;
auto it = _audioCaches.find(filePath);
if (it == _audioCaches.end()) {
audioCache = &_audioCaches[filePath];
audioCache->_fileFullPath = FileUtils::getInstance()->fullPathForFilename(filePath);
AudioEngine::addTask(std::bind(&AudioCache::readDataTask, audioCache));
}
else {
audioCache = &it->second;
}
return audioCache;
}
int AudioEngineImpl::play2d(const std::string &filePath ,bool loop ,float volume)
{
if (s_ALDevice == nullptr) {
@ -303,16 +229,9 @@ 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];
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];

View File

@ -281,8 +281,14 @@ 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 addTask(const std::function<void()> &task);
static void remove(int audioID);
struct ProfileHelper
@ -335,6 +341,9 @@ protected:
static ProfileHelper* _defaultProfileHelper;
static AudioEngineImpl* _audioEngineImpl;
class AudioEngineThreadPool;
static AudioEngineThreadPool* s_threadPool;
friend class AudioEngineImpl;
};

View File

@ -26,7 +26,7 @@
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
#include "AudioEngine-win32.h"
#include <condition_variable>
#ifdef OPENAL_PLAIN_INCLUDES
#include "alc.h"
#include "alext.h"
@ -47,95 +47,9 @@ static ALCdevice *s_ALDevice = nullptr;
static ALCcontext *s_ALContext = nullptr;
static bool MPG123_LAZYINIT = true;
namespace cocos2d {
namespace experimental {
class AudioEngineThreadPool
{
public:
AudioEngineThreadPool()
: _running(true)
, _numThread(6)
{
_threads.reserve(_numThread);
_tasks.reserve(_numThread);
for (int index = 0; index < _numThread; ++index) {
_tasks.push_back(nullptr);
_threads.push_back( std::thread( std::bind(&AudioEngineThreadPool::threadFunc,this,index) ) );
_threads[index].detach();
}
}
void addTask(const std::function<void()> &task){
_taskMutex.lock();
int targetIndex = -1;
for (int index = 0; index < _numThread; ++index) {
if (_tasks[index] == nullptr) {
targetIndex = index;
_tasks[index] = task;
break;
}
}
if (targetIndex == -1) {
_tasks.push_back(task);
_threads.push_back( std::thread( std::bind(&AudioEngineThreadPool::threadFunc,this,_numThread) ) );
_threads[_numThread].detach();
_numThread++;
}
_taskMutex.unlock();
_sleepCondition.notify_all();
}
void destroy()
{
_running = false;
_sleepCondition.notify_all();
for (int index = 0; index < _numThread; ++index) {
_threads[index].join();
}
}
private:
bool _running;
std::vector<std::thread> _threads;
std::vector< std::function<void ()> > _tasks;
void threadFunc(int index)
{
while (_running) {
std::function<void ()> task = nullptr;
_taskMutex.lock();
task = _tasks[index];
_taskMutex.unlock();
if (nullptr == task)
{
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.wait(lk);
continue;
}
task();
_taskMutex.lock();
_tasks[index] = nullptr;
_taskMutex.unlock();
}
}
int _numThread;
std::mutex _taskMutex;
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
};
}
}
AudioEngineImpl::AudioEngineImpl()
: _lazyInitLoop(true)
, _currentAudioID(0)
, _threadPool(nullptr)
{
}
@ -155,10 +69,6 @@ AudioEngineImpl::~AudioEngineImpl()
alcCloseDevice(s_ALDevice);
s_ALDevice = nullptr;
}
if (_threadPool) {
_threadPool->destroy();
delete _threadPool;
}
mpg123_exit();
MPG123_LAZYINIT = true;
@ -186,7 +96,6 @@ bool AudioEngineImpl::init()
_alSourceUsed[_alSources[i]] = false;
}
_threadPool = new (std::nothrow) AudioEngineThreadPool();
ret = true;
}
}while (false);
@ -194,6 +103,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);
AudioEngine::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 +166,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];

View File

@ -38,8 +38,6 @@ NS_CC_BEGIN
namespace experimental{
#define MAX_AUDIOINSTANCES 32
class AudioEngineThreadPool;
class CC_DLL AudioEngineImpl : public cocos2d::Ref
{
public:
@ -61,14 +59,13 @@ public:
void uncache(const std::string& filePath);
void uncacheAll();
AudioCache* preload(const std::string& filePath);
void update(float dt);
private:
void _play2d(AudioCache *cache, int audioID);
AudioEngineThreadPool* _threadPool;
ALuint _alSources[MAX_AUDIOINSTANCES];
//source,used

View File

@ -21,101 +21,13 @@
#if CC_TARGET_PLATFORM == CC_PLATFORM_WINRT
#include "AudioEngine-winrt.h"
#include <condition_variable>
using namespace cocos2d;
using namespace cocos2d::experimental;
namespace cocos2d {
namespace experimental {
class AudioEngineThreadPool
{
public:
AudioEngineThreadPool()
: _running(true)
, _numThread(6)
{
_threads.reserve(_numThread);
_tasks.reserve(_numThread);
for (int index = 0; index < _numThread; ++index) {
_tasks.push_back(nullptr);
_threads.push_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this, index)));
}
}
void addTask(const std::function<void()> &task){
_taskMutex.lock();
int targetIndex = -1;
for (int index = 0; index < _numThread; ++index) {
if (_tasks[index] == nullptr) {
targetIndex = index;
_tasks[index] = task;
break;
}
}
if (targetIndex == -1) {
_tasks.push_back(task);
_threads.push_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this, _numThread)));
_numThread++;
}
_taskMutex.unlock();
_sleepCondition.notify_all();
}
void destroy()
{
_running = false;
_sleepCondition.notify_all();
for (int index = 0; index < _numThread; ++index) {
_threads[index].join();
}
}
private:
bool _running;
std::vector<std::thread> _threads;
std::vector< std::function<void()> > _tasks;
void threadFunc(int index)
{
while (_running) {
std::function<void()> task = nullptr;
_taskMutex.lock();
task = _tasks[index];
_taskMutex.unlock();
if (nullptr == task)
{
std::unique_lock<std::mutex> lk(_sleepMutex);
_sleepCondition.wait(lk);
continue;
}
task();
_taskMutex.lock();
_tasks[index] = nullptr;
_taskMutex.unlock();
}
}
int _numThread;
std::mutex _taskMutex;
std::mutex _sleepMutex;
std::condition_variable _sleepCondition;
};
}
}
AudioEngineImpl::AudioEngineImpl()
: _lazyInitLoop(true)
, _currentAudioID(0)
, _threadPool(nullptr)
{
}
@ -123,64 +35,63 @@ AudioEngineImpl::AudioEngineImpl()
AudioEngineImpl::~AudioEngineImpl()
{
_audioCaches.clear();
if (_threadPool) {
_threadPool->destroy();
delete _threadPool;
}
}
bool AudioEngineImpl::init()
{
bool ret = false;
if (nullptr == _threadPool) {
_threadPool = new (std::nothrow) AudioEngineThreadPool();
}
ret = true;
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;
AudioEngine::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];

View File

@ -35,9 +35,6 @@ NS_CC_BEGIN
namespace experimental{
#define MAX_AUDIOINSTANCES 32
class AudioEngineThreadPool;
class CC_DLL AudioEngineImpl : public cocos2d::Ref
{
public:
@ -58,6 +55,7 @@ NS_CC_BEGIN
void setFinishCallback(int audioID, const std::function<void(int, const std::string &)> &callback);
void uncache(const std::string& filePath);
void uncacheAll();
AudioCache* preload(const std::string& filePath);
void update(float dt);
private:
@ -72,7 +70,6 @@ NS_CC_BEGIN
std::vector<int> _toRemoveAudioIDs;
bool _lazyInitLoop;
int _currentAudioID;
AudioEngineThreadPool* _threadPool;
};
}

View File

@ -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();