mirror of https://github.com/axmolengine/axmol.git
issue #1284: fixed the problem that if the same effect is played for two
times, it will stop and restart
This commit is contained in:
parent
b4e7e1152f
commit
6beae122da
|
@ -131,7 +131,7 @@ void SimpleAudioEngine::setEffectsVolume(float volume)
|
||||||
#ifdef ENABLE_OPENSL
|
#ifdef ENABLE_OPENSL
|
||||||
// @TO-DO
|
// @TO-DO
|
||||||
// Here may crash, fixing.
|
// Here may crash, fixing.
|
||||||
// SimpleAudioEngineOpenSL::sharedEngine()->setEffectsVolume(volume);
|
SimpleAudioEngineOpenSL::sharedEngine()->setEffectsVolume(volume);
|
||||||
#else
|
#else
|
||||||
setEffectsVolumeJNI(volume);
|
setEffectsVolumeJNI(volume);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -120,15 +120,17 @@ extern "C" {
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* helper
|
* helper
|
||||||
********************************************************************************/
|
********************************************************************************/
|
||||||
#define PLAYSTATE_STOPPED 1
|
#define PLAYSTATE_UNKNOWN 0
|
||||||
#define PLAYSTATE_PAUSED 2
|
|
||||||
#define PLAYSTATE_PLAYING 3
|
|
||||||
#define FILE_NOT_FOUND -1
|
#define FILE_NOT_FOUND -1
|
||||||
|
|
||||||
#define ASSET_MANAGER_GETTER "getAssetManager"
|
#define ASSET_MANAGER_GETTER "getAssetManager"
|
||||||
|
|
||||||
|
#define MIN_VOLUME_MILLIBEL -4000
|
||||||
|
#define MAX_VOLUME_MILLIBEL 0
|
||||||
|
#define RANGE_VOLUME_MILLIBEL 4000
|
||||||
|
|
||||||
struct AudioPlayer
|
struct AudioPlayer
|
||||||
{
|
{
|
||||||
AAsset* Asset;
|
|
||||||
SLDataSource audioSrc;
|
SLDataSource audioSrc;
|
||||||
SLObjectItf fdPlayerObject;
|
SLObjectItf fdPlayerObject;
|
||||||
SLPlayItf fdPlayerPlay;
|
SLPlayItf fdPlayerPlay;
|
||||||
|
@ -136,8 +138,8 @@ struct AudioPlayer
|
||||||
SLVolumeItf fdPlayerVolume;
|
SLVolumeItf fdPlayerVolume;
|
||||||
} musicPlayer; /* for background music */
|
} musicPlayer; /* for background music */
|
||||||
|
|
||||||
typedef map<unsigned int, AudioPlayer *> EffectList;
|
typedef map<unsigned int, vector<AudioPlayer*>* > EffectList;
|
||||||
typedef pair<unsigned int, AudioPlayer *> Effect;
|
typedef pair<unsigned int, vector<AudioPlayer*>* > Effect;
|
||||||
|
|
||||||
static EffectList& sharedList()
|
static EffectList& sharedList()
|
||||||
{
|
{
|
||||||
|
@ -159,7 +161,7 @@ unsigned int _Hash(const char *key)
|
||||||
return (hash);
|
return (hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getFileDescriptor(AudioPlayer * player, const char * filename, off_t & start, off_t & length)
|
int getFileDescriptor(const char * filename, off_t & start, off_t & length)
|
||||||
{
|
{
|
||||||
JniMethodInfo methodInfo;
|
JniMethodInfo methodInfo;
|
||||||
if (! getStaticMethodInfo(methodInfo, ASSET_MANAGER_GETTER, "()Landroid/content/res/AssetManager;"))
|
if (! getStaticMethodInfo(methodInfo, ASSET_MANAGER_GETTER, "()Landroid/content/res/AssetManager;"))
|
||||||
|
@ -171,18 +173,18 @@ int getFileDescriptor(AudioPlayer * player, const char * filename, off_t & start
|
||||||
|
|
||||||
AAssetManager* mgr = AAssetManager_fromJava(methodInfo.env, assetManager);
|
AAssetManager* mgr = AAssetManager_fromJava(methodInfo.env, assetManager);
|
||||||
assert(NULL != mgr);
|
assert(NULL != mgr);
|
||||||
player->Asset = AAssetManager_open(mgr, filename, AASSET_MODE_UNKNOWN);
|
|
||||||
|
|
||||||
if (player->Asset == NULL)
|
AAsset* Asset = AAssetManager_open(mgr, filename, AASSET_MODE_UNKNOWN);
|
||||||
|
if (NULL == Asset)
|
||||||
{
|
{
|
||||||
LOGD("file not found! Stop preload file: %s", filename);
|
LOGD("file not found! Stop preload file: %s", filename);
|
||||||
return FILE_NOT_FOUND;
|
return FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// open asset as file descriptor
|
// open asset as file descriptor
|
||||||
int fd = AAsset_openFileDescriptor(player->Asset, &start, &length);
|
int fd = AAsset_openFileDescriptor(Asset, &start, &length);
|
||||||
assert(0 <= fd);
|
assert(0 <= fd);
|
||||||
AAsset_close(player->Asset);
|
AAsset_close(Asset);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
@ -195,28 +197,20 @@ static SLObjectItf s_pEngineObject = NULL;
|
||||||
static SLEngineItf s_pEngineEngine = NULL;
|
static SLEngineItf s_pEngineEngine = NULL;
|
||||||
static SLObjectItf s_pOutputMixObject = NULL;
|
static SLObjectItf s_pOutputMixObject = NULL;
|
||||||
|
|
||||||
bool initAudioPlayer(AudioPlayer* player, const char* filename)
|
bool createAudioPlayerBySource(AudioPlayer* player)
|
||||||
{
|
{
|
||||||
// configure audio sink
|
// configure audio sink
|
||||||
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, s_pOutputMixObject};
|
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, s_pOutputMixObject};
|
||||||
SLDataSink audioSnk = {&loc_outmix, NULL};
|
SLDataSink audioSnk = {&loc_outmix, NULL};
|
||||||
|
|
||||||
// configure audio source
|
|
||||||
off_t start, length;
|
|
||||||
int fd = getFileDescriptor(player, filename, start, length);
|
|
||||||
if (FILE_NOT_FOUND == fd)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
|
|
||||||
SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
|
|
||||||
(player->audioSrc) = {&loc_fd, &format_mime};
|
|
||||||
|
|
||||||
// create audio player
|
// create audio player
|
||||||
const SLInterfaceID ids[3] = {SL_IID_SEEK, SL_IID_MUTESOLO, SL_IID_VOLUME};
|
const SLInterfaceID ids[3] = {SL_IID_SEEK, SL_IID_MUTESOLO, SL_IID_VOLUME};
|
||||||
const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
const SLboolean req[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
|
||||||
SLresult result = (*s_pEngineEngine)->CreateAudioPlayer(s_pEngineEngine, &(player->fdPlayerObject), &(player->audioSrc), &audioSnk, 3, ids, req);
|
SLresult result = (*s_pEngineEngine)->CreateAudioPlayer(s_pEngineEngine, &(player->fdPlayerObject), &(player->audioSrc), &audioSnk, 3, ids, req);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
if (SL_RESULT_MEMORY_FAILURE == result)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// realize the player
|
// realize the player
|
||||||
result = (*(player->fdPlayerObject))->Realize(player->fdPlayerObject, SL_BOOLEAN_FALSE);
|
result = (*(player->fdPlayerObject))->Realize(player->fdPlayerObject, SL_BOOLEAN_FALSE);
|
||||||
|
@ -230,16 +224,37 @@ bool initAudioPlayer(AudioPlayer* player, const char* filename)
|
||||||
result = (*(player->fdPlayerObject))->GetInterface(player->fdPlayerObject, SL_IID_VOLUME, &(player->fdPlayerVolume));
|
result = (*(player->fdPlayerObject))->GetInterface(player->fdPlayerObject, SL_IID_VOLUME, &(player->fdPlayerVolume));
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
// get the volume interface
|
// get the seek interface
|
||||||
result = (*(player->fdPlayerObject))->GetInterface(player->fdPlayerObject, SL_IID_SEEK, &(player->fdPlayerSeek));
|
result = (*(player->fdPlayerObject))->GetInterface(player->fdPlayerObject, SL_IID_SEEK, &(player->fdPlayerSeek));
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool initAudioPlayer(AudioPlayer* player, const char* filename)
|
||||||
|
{
|
||||||
|
// configure audio source
|
||||||
|
off_t start, length;
|
||||||
|
int fd = getFileDescriptor(filename, start, length);
|
||||||
|
if (FILE_NOT_FOUND == fd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SLDataLocator_AndroidFD loc_fd = {SL_DATALOCATOR_ANDROIDFD, fd, start, length};
|
||||||
|
SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
|
||||||
|
(player->audioSrc) = {&loc_fd, &format_mime};
|
||||||
|
|
||||||
|
return createAudioPlayerBySource(player);
|
||||||
|
}
|
||||||
|
|
||||||
void destroyAudioPlayer(AudioPlayer * player)
|
void destroyAudioPlayer(AudioPlayer * player)
|
||||||
{
|
{
|
||||||
if (player->fdPlayerObject != NULL){
|
if (player && player->fdPlayerObject != NULL)
|
||||||
|
{
|
||||||
|
SLresult result;
|
||||||
|
result = (*(player->fdPlayerPlay))->SetPlayState(player->fdPlayerPlay, SL_PLAYSTATE_STOPPED);
|
||||||
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
(*(player->fdPlayerObject))->Destroy(player->fdPlayerObject);
|
(*(player->fdPlayerObject))->Destroy(player->fdPlayerObject);
|
||||||
player->fdPlayerObject = NULL;
|
player->fdPlayerObject = NULL;
|
||||||
player->fdPlayerPlay = NULL;
|
player->fdPlayerPlay = NULL;
|
||||||
|
@ -251,11 +266,9 @@ void destroyAudioPlayer(AudioPlayer * player)
|
||||||
void OpenSLEngine::createEngine()
|
void OpenSLEngine::createEngine()
|
||||||
{
|
{
|
||||||
SLresult result;
|
SLresult result;
|
||||||
LOGD("createEngine");
|
|
||||||
|
|
||||||
// create engine
|
|
||||||
if (s_pEngineObject == NULL)
|
if (s_pEngineObject == NULL)
|
||||||
{
|
{
|
||||||
|
// create engine
|
||||||
result = slCreateEngine(&s_pEngineObject, 0, NULL, 0, NULL, NULL);
|
result = slCreateEngine(&s_pEngineObject, 0, NULL, 0, NULL, NULL);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
|
@ -272,11 +285,11 @@ void OpenSLEngine::createEngine()
|
||||||
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
|
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
|
||||||
result = (*s_pEngineEngine)->CreateOutputMix(s_pEngineEngine, &s_pOutputMixObject, 1, ids, req);
|
result = (*s_pEngineEngine)->CreateOutputMix(s_pEngineEngine, &s_pOutputMixObject, 1, ids, req);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
}
|
|
||||||
|
|
||||||
// realize the output mix
|
// realize the output mix object in sync. mode
|
||||||
result = (*s_pOutputMixObject)->Realize(s_pOutputMixObject, SL_BOOLEAN_FALSE);
|
result = (*s_pOutputMixObject)->Realize(s_pOutputMixObject, SL_BOOLEAN_FALSE);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::closeEngine()
|
void OpenSLEngine::closeEngine()
|
||||||
|
@ -285,26 +298,36 @@ void OpenSLEngine::closeEngine()
|
||||||
destroyAudioPlayer(&musicPlayer);
|
destroyAudioPlayer(&musicPlayer);
|
||||||
|
|
||||||
// destroy effect players
|
// destroy effect players
|
||||||
|
vector<AudioPlayer*>* vec;
|
||||||
EffectList::iterator p = sharedList().begin();
|
EffectList::iterator p = sharedList().begin();
|
||||||
while (p != sharedList().end())
|
while (p != sharedList().end())
|
||||||
{
|
{
|
||||||
destroyAudioPlayer(p->second);
|
vec = p->second;
|
||||||
|
for (vector<AudioPlayer*>::iterator iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
destroyAudioPlayer(*iter);
|
||||||
|
}
|
||||||
|
vec->clear();
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
sharedList().clear();
|
sharedList().clear();
|
||||||
|
|
||||||
// destroy output mix interface
|
// destroy output mix interface
|
||||||
if (s_pOutputMixObject != NULL) {
|
if (s_pOutputMixObject)
|
||||||
|
{
|
||||||
(*s_pOutputMixObject)->Destroy(s_pOutputMixObject);
|
(*s_pOutputMixObject)->Destroy(s_pOutputMixObject);
|
||||||
s_pOutputMixObject = NULL;
|
s_pOutputMixObject = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy opensl engine
|
// destroy opensl engine
|
||||||
if (s_pEngineObject != NULL) {
|
if (s_pEngineObject)
|
||||||
|
{
|
||||||
(*s_pEngineObject)->Destroy(s_pEngineObject);
|
(*s_pEngineObject)->Destroy(s_pEngineObject);
|
||||||
s_pEngineObject = NULL;
|
s_pEngineObject = NULL;
|
||||||
s_pEngineEngine = NULL;
|
s_pEngineEngine = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOGD("engine destory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,15 +336,10 @@ void OpenSLEngine::closeEngine()
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
bool OpenSLEngine::preloadBackgroundMusic(const char * filename)
|
bool OpenSLEngine::preloadBackgroundMusic(const char * filename)
|
||||||
{
|
{
|
||||||
if (musicPlayer.Asset != NULL)
|
if (musicPlayer.fdPlayerPlay != NULL)
|
||||||
{
|
{
|
||||||
if (musicPlayer.fdPlayerPlay != NULL)
|
SLresult result = (*(musicPlayer.fdPlayerPlay))->SetPlayState(musicPlayer.fdPlayerPlay, SL_PLAYSTATE_STOPPED);
|
||||||
{
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
SLresult result = (*(musicPlayer.fdPlayerPlay))->SetPlayState(musicPlayer.fdPlayerPlay, SL_PLAYSTATE_STOPPED);
|
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
|
||||||
}
|
|
||||||
free(musicPlayer.Asset);
|
|
||||||
musicPlayer.Asset = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return initAudioPlayer(&musicPlayer, filename);
|
return initAudioPlayer(&musicPlayer, filename);
|
||||||
|
@ -330,7 +348,8 @@ bool OpenSLEngine::preloadBackgroundMusic(const char * filename)
|
||||||
void OpenSLEngine::setBackgroundMusicState(int state)
|
void OpenSLEngine::setBackgroundMusicState(int state)
|
||||||
{
|
{
|
||||||
SLresult result;
|
SLresult result;
|
||||||
if (NULL != musicPlayer.fdPlayerPlay) {
|
if (NULL != musicPlayer.fdPlayerPlay)
|
||||||
|
{
|
||||||
result = (*(musicPlayer.fdPlayerPlay))->SetPlayState(musicPlayer.fdPlayerPlay, state);
|
result = (*(musicPlayer.fdPlayerPlay))->SetPlayState(musicPlayer.fdPlayerPlay, state);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
}
|
}
|
||||||
|
@ -375,7 +394,8 @@ void OpenSLEngine::setBackgroundVolume(int volume)
|
||||||
m_musicVolume = volume;
|
m_musicVolume = volume;
|
||||||
|
|
||||||
SLresult result;
|
SLresult result;
|
||||||
if (NULL != musicPlayer.fdPlayerVolume) {
|
if (NULL != musicPlayer.fdPlayerVolume)
|
||||||
|
{
|
||||||
result = (*(musicPlayer.fdPlayerVolume))->SetVolumeLevel(musicPlayer.fdPlayerVolume, m_musicVolume);
|
result = (*(musicPlayer.fdPlayerVolume))->SetVolumeLevel(musicPlayer.fdPlayerVolume, m_musicVolume);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
}
|
}
|
||||||
|
@ -390,41 +410,39 @@ int OpenSLEngine::getBackgroundVolume()
|
||||||
/**********************************************************************************
|
/**********************************************************************************
|
||||||
* sound effect
|
* sound effect
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
#define NORMAL_EFFECT_CALLBACK 1
|
typedef struct _CallbackContext
|
||||||
#define REPLAY_EFFECT_CALLBACK 2
|
|
||||||
|
|
||||||
//typedef struct _CallbackContext
|
|
||||||
//{
|
|
||||||
// int type;
|
|
||||||
// AudioPlayer* player;
|
|
||||||
//} CallbackContext;
|
|
||||||
//
|
|
||||||
//void effectPlayCallback(SLPlayItf caller, void * context, SLuint32 event)
|
|
||||||
//{
|
|
||||||
// CallbackContext* callback = (CallbackContext*)context;
|
|
||||||
// switch(callback->type)
|
|
||||||
// {
|
|
||||||
// case NORMAL_EFFECT_CALLBACK :
|
|
||||||
// // TO-DO
|
|
||||||
// break;
|
|
||||||
// case REPLAY_EFFECT_CALLBACK :
|
|
||||||
// destroyAudioPlayer(callback->player);
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
void setSingleEffectState(AudioPlayer * player, int state)
|
|
||||||
{
|
{
|
||||||
SLresult result;
|
vector<AudioPlayer*>* vec;
|
||||||
if (player->fdPlayerPlay != NULL){
|
AudioPlayer* player;
|
||||||
result = (*(player->fdPlayerPlay))->SetPlayState(player->fdPlayerPlay, state);
|
} CallbackContext;
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
|
||||||
|
void PlayOverEvent(SLPlayItf caller, void* pContext, SLuint32 playEvent)
|
||||||
|
{
|
||||||
|
CallbackContext* context = (CallbackContext*)pContext;
|
||||||
|
if (playEvent == SL_PLAYEVENT_HEADATEND)
|
||||||
|
{
|
||||||
|
vector<AudioPlayer*>::iterator iter;
|
||||||
|
for (iter = (context->vec)->begin() ; iter != (context->vec)->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
if (*iter == context->player)
|
||||||
|
{
|
||||||
|
(context->vec)->erase(iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destroyAudioPlayer(context->player);
|
||||||
|
free(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getEffectState(AudioPlayer * player)
|
void setSingleEffectVolume(AudioPlayer* player, SLmillibel volume)
|
||||||
|
{
|
||||||
|
SLresult result;
|
||||||
|
result = (*(player->fdPlayerVolume))->SetVolumeLevel(player->fdPlayerVolume, volume);
|
||||||
|
assert(result == SL_RESULT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSingleEffectState(AudioPlayer * player)
|
||||||
{
|
{
|
||||||
SLuint32 state = 0;
|
SLuint32 state = 0;
|
||||||
SLresult result;
|
SLresult result;
|
||||||
|
@ -434,43 +452,88 @@ int getEffectState(AudioPlayer * player)
|
||||||
return (int)state;
|
return (int)state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSingleEffectState(AudioPlayer * player, int state)
|
||||||
|
{
|
||||||
|
SLresult result;
|
||||||
|
if (player->fdPlayerPlay != NULL)
|
||||||
|
{
|
||||||
|
// don't set to PAUSED state if it's already set to STOPPED state
|
||||||
|
int oldState = getSingleEffectState(player);
|
||||||
|
if (oldState == SL_PLAYSTATE_STOPPED && state == SL_PLAYSTATE_PAUSED)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result = (*(player->fdPlayerPlay))->SetPlayState(player->fdPlayerPlay, state);
|
||||||
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void resumeSingleEffect(AudioPlayer * player)
|
void resumeSingleEffect(AudioPlayer * player)
|
||||||
{
|
{
|
||||||
int state = getEffectState(player);
|
int state = getSingleEffectState(player);
|
||||||
// only resume the effect that has been paused
|
// only resume the effect that has been paused
|
||||||
if (state == PLAYSTATE_PAUSED)
|
if (state == SL_PLAYSTATE_PAUSED)
|
||||||
{
|
{
|
||||||
setSingleEffectState(player, PLAYSTATE_PLAYING);
|
setSingleEffectState(player, SL_PLAYSTATE_PLAYING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenSLEngine::recreatePlayer(const char* filename)
|
||||||
|
{
|
||||||
|
unsigned int effectID = _Hash(filename);
|
||||||
|
EffectList::iterator p = sharedList().find(effectID);
|
||||||
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
AudioPlayer* newPlayer = new AudioPlayer();
|
||||||
|
if (!initAudioPlayer(newPlayer, filename))
|
||||||
|
{
|
||||||
|
LOGD("failed to recreate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vec->push_back(newPlayer);
|
||||||
|
|
||||||
|
// set callback
|
||||||
|
SLresult result;
|
||||||
|
CallbackContext* context = new CallbackContext();
|
||||||
|
context->vec = vec;
|
||||||
|
context->player = newPlayer;
|
||||||
|
result = (*(newPlayer->fdPlayerPlay))->RegisterCallback(newPlayer->fdPlayerPlay, PlayOverEvent, (void*)context);
|
||||||
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
|
result = (*(newPlayer->fdPlayerPlay))->SetCallbackEventsMask(newPlayer->fdPlayerPlay, SL_PLAYEVENT_HEADATEND);
|
||||||
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
|
// set volume
|
||||||
|
setSingleEffectVolume(newPlayer, m_effectVolume);
|
||||||
|
setSingleEffectState(newPlayer, SL_PLAYSTATE_STOPPED);
|
||||||
|
setSingleEffectState(newPlayer, SL_PLAYSTATE_PLAYING);
|
||||||
|
|
||||||
|
// LOGD("vec count is %d of effectID %d", vec->size(), effectID);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int OpenSLEngine::preloadEffect(const char * filename)
|
unsigned int OpenSLEngine::preloadEffect(const char * filename)
|
||||||
{
|
{
|
||||||
unsigned int nID = _Hash(filename);
|
unsigned int nID = _Hash(filename);
|
||||||
// if already exists
|
// if already exists
|
||||||
if (sharedList().find(nID) != sharedList().end())
|
EffectList::iterator p = sharedList().find(nID);
|
||||||
|
if (p != sharedList().end())
|
||||||
{
|
{
|
||||||
/*AudioPlayer* newPlayer = new AudioPlayer(sharedList()[nID]);
|
|
||||||
CallbackContext* context = new CallbackContext();
|
|
||||||
context->player = newPlayer;
|
|
||||||
context->
|
|
||||||
(newPlayer->fdPlayerPlay)->RegisterCallback(newPlayer->fdPlayerPlay, effectPlayCallback, );*/
|
|
||||||
return nID;
|
return nID;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPlayer* player = new AudioPlayer();
|
AudioPlayer* player = new AudioPlayer();
|
||||||
if (!initAudioPlayer(player, filename))
|
if (!initAudioPlayer(player, filename))
|
||||||
{
|
{
|
||||||
free(player);
|
free(player);
|
||||||
return FILE_NOT_FOUND;
|
return FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the new player's volume as others'
|
// set the new player's volume as others'
|
||||||
SLresult result;
|
setSingleEffectVolume(player, m_effectVolume);
|
||||||
result = (*(player->fdPlayerVolume))->SetVolumeLevel(player->fdPlayerVolume, m_effectVolume);
|
|
||||||
assert(result == SL_RESULT_SUCCESS);
|
|
||||||
|
|
||||||
sharedList().insert(Effect(nID, player));
|
vector<AudioPlayer*>* vec = new vector<AudioPlayer*>;
|
||||||
|
vec->push_back(player);
|
||||||
|
sharedList().insert(Effect(nID, vec));
|
||||||
return nID;
|
return nID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,78 +544,146 @@ void OpenSLEngine::unloadEffect(const char * filename)
|
||||||
EffectList::iterator p = sharedList().find(nID);
|
EffectList::iterator p = sharedList().find(nID);
|
||||||
if (p != sharedList().end())
|
if (p != sharedList().end())
|
||||||
{
|
{
|
||||||
destroyAudioPlayer(p->second);
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
for (vector<AudioPlayer*>::iterator iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
destroyAudioPlayer(*iter);
|
||||||
|
}
|
||||||
|
vec->clear();
|
||||||
sharedList().erase(nID);
|
sharedList().erase(nID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::setEffectState(unsigned int effectID, int state)
|
int OpenSLEngine::getEffectState(unsigned int effectID)
|
||||||
|
{
|
||||||
|
int state = PLAYSTATE_UNKNOWN;
|
||||||
|
EffectList::iterator p = sharedList().find(effectID);
|
||||||
|
if (p != sharedList().end())
|
||||||
|
{
|
||||||
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
// get the last player's state
|
||||||
|
vector<AudioPlayer*>::reverse_iterator r_iter = vec->rbegin();
|
||||||
|
state = getSingleEffectState(*r_iter);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenSLEngine::setEffectState(unsigned int effectID, int state, bool isClear)
|
||||||
{
|
{
|
||||||
EffectList::iterator p = sharedList().find(effectID);
|
EffectList::iterator p = sharedList().find(effectID);
|
||||||
if (p != sharedList().end())
|
if (p != sharedList().end())
|
||||||
{
|
{
|
||||||
setSingleEffectState(p->second, state);
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
if (state == SL_PLAYSTATE_STOPPED || state == SL_PLAYSTATE_PAUSED)
|
||||||
|
{
|
||||||
|
// if stopped, clear the recreated players which are unused
|
||||||
|
if (isClear)
|
||||||
|
{
|
||||||
|
setSingleEffectState(*(vec->begin()), state);
|
||||||
|
vector<AudioPlayer*>::reverse_iterator r_iter = vec->rbegin();
|
||||||
|
for (int i = 1, size = vec->size() ; i < size ; ++ i)
|
||||||
|
{
|
||||||
|
destroyAudioPlayer(*r_iter);
|
||||||
|
r_iter ++;
|
||||||
|
vec->pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vector<AudioPlayer*>::iterator iter;
|
||||||
|
for (iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
setSingleEffectState(*iter, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setSingleEffectState(*(vec->rbegin()), state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::setAllEffectState(int state)
|
void OpenSLEngine::setAllEffectState(int state)
|
||||||
{
|
{
|
||||||
EffectList::iterator iter;
|
EffectList::iterator p;
|
||||||
for (iter = sharedList().begin(); iter != sharedList().end(); iter++)
|
for (p = sharedList().begin(); p != sharedList().end(); p ++)
|
||||||
{
|
{
|
||||||
setSingleEffectState(iter->second, state);
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
for (vector<AudioPlayer*>::iterator iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
setSingleEffectState(*iter, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::resumeEffect(unsigned int effectID)
|
void OpenSLEngine::resumeEffect(unsigned int effectID)
|
||||||
{
|
{
|
||||||
EffectList::iterator p = sharedList().find(effectID);
|
EffectList::iterator p = sharedList().find(effectID);
|
||||||
if (p == sharedList().end())
|
if (p != sharedList().end())
|
||||||
{
|
{
|
||||||
return;
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
for (vector<AudioPlayer*>::iterator iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
resumeSingleEffect(*iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resumeSingleEffect(p->second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::resumeAllEffects()
|
void OpenSLEngine::resumeAllEffects()
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
EffectList::iterator iter;
|
EffectList::iterator p;
|
||||||
for (iter = sharedList().begin(); iter != sharedList().end() ; ++ iter)
|
for (p = sharedList().begin(); p != sharedList().end() ; ++ p)
|
||||||
{
|
{
|
||||||
resumeSingleEffect(iter->second);
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
|
for (vector<AudioPlayer*>::iterator iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
|
{
|
||||||
|
resumeSingleEffect(*iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::setEffectLooping(unsigned int effectID, bool isLooping)
|
void OpenSLEngine::setEffectLooping(unsigned int effectID, bool isLooping)
|
||||||
{
|
{
|
||||||
SLresult result;
|
SLresult result;
|
||||||
AudioPlayer * player = sharedList()[effectID];
|
vector<AudioPlayer*>* vec = sharedList()[effectID];
|
||||||
assert(player != NULL);
|
assert(NULL != vec);
|
||||||
|
|
||||||
if (NULL != player->fdPlayerSeek)
|
// get the first effect player that to be set loop config
|
||||||
|
vector<AudioPlayer*>::iterator iter = vec->begin();
|
||||||
|
AudioPlayer * player = *iter;
|
||||||
|
|
||||||
|
if (player && player->fdPlayerSeek)
|
||||||
{
|
{
|
||||||
result = (*(player->fdPlayerSeek))->SetLoop(player->fdPlayerSeek, (SLboolean) isLooping, 0, SL_TIME_UNKNOWN);
|
result = (*(player->fdPlayerSeek))->SetLoop(player->fdPlayerSeek, (SLboolean) isLooping, 0, SL_TIME_UNKNOWN);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenSLEngine::setEffectsVolume(int volume)
|
void OpenSLEngine::setEffectsVolume(float volume)
|
||||||
{
|
{
|
||||||
m_effectVolume = volume;
|
assert(volume <= 1.0f && volume >= 0.0f);
|
||||||
|
m_effectVolume = int (RANGE_VOLUME_MILLIBEL * volume) + MIN_VOLUME_MILLIBEL;
|
||||||
|
|
||||||
SLresult result;
|
SLresult result;
|
||||||
EffectList::iterator iter;
|
EffectList::iterator p;
|
||||||
AudioPlayer * player;
|
AudioPlayer * player;
|
||||||
for (iter = sharedList().begin() ; iter != sharedList().end() ; ++ iter)
|
for (p = sharedList().begin() ; p != sharedList().end() ; ++ p)
|
||||||
{
|
{
|
||||||
player = iter->second;
|
vector<AudioPlayer*>* vec = p->second;
|
||||||
result = (*(player->fdPlayerVolume))->SetVolumeLevel(player->fdPlayerVolume, m_effectVolume);
|
for (vector<AudioPlayer*>::iterator iter = vec->begin() ; iter != vec->end() ; ++ iter)
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
{
|
||||||
|
player = *iter;
|
||||||
|
result = (*(player->fdPlayerVolume))->SetVolumeLevel(player->fdPlayerVolume, m_effectVolume);
|
||||||
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenSLEngine::getEffectsVolume()
|
float OpenSLEngine::getEffectsVolume()
|
||||||
{
|
{
|
||||||
return m_effectVolume;
|
float volume = (m_effectVolume - MIN_VOLUME_MILLIBEL) / (1.0f * RANGE_VOLUME_MILLIBEL);
|
||||||
|
LOGD("effect volume: %f", volume);
|
||||||
|
return volume;
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
#include <SLES/OpenSLES.h>
|
#include <SLES/OpenSLES.h>
|
||||||
#include <SLES/OpenSLES_Android.h>
|
#include <SLES/OpenSLES_Android.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -42,11 +43,16 @@ public:
|
||||||
int getBackgroundVolume();
|
int getBackgroundVolume();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool recreatePlayer(const char* filename);
|
||||||
|
|
||||||
unsigned int preloadEffect(const char * filename);
|
unsigned int preloadEffect(const char * filename);
|
||||||
|
|
||||||
void unloadEffect(const char * filename);
|
void unloadEffect(const char * filename);
|
||||||
|
|
||||||
void setEffectState(unsigned int effectID, int state);
|
int getEffectState(unsigned int effectID);
|
||||||
|
|
||||||
|
void setEffectState(unsigned int effectID, int state, bool isClear = false);
|
||||||
|
|
||||||
void setAllEffectState(int state);
|
void setAllEffectState(int state);
|
||||||
|
|
||||||
|
@ -56,9 +62,9 @@ public:
|
||||||
|
|
||||||
void setEffectLooping(unsigned int effectID, bool isLooping);
|
void setEffectLooping(unsigned int effectID, bool isLooping);
|
||||||
|
|
||||||
void setEffectsVolume(int volume);
|
void setEffectsVolume(float volume);
|
||||||
|
|
||||||
int getEffectsVolume();
|
float getEffectsVolume();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SLmillibel m_musicVolume;
|
SLmillibel m_musicVolume;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "SimpleAudioEngineOpenSL.h"
|
#include "SimpleAudioEngineOpenSL.h"
|
||||||
|
|
||||||
|
#define PLAYSTATE_UNKNOWN 0
|
||||||
#define PLAYSTATE_STOPPED 1
|
#define PLAYSTATE_STOPPED 1
|
||||||
#define PLAYSTATE_PAUSED 2
|
#define PLAYSTATE_PAUSED 2
|
||||||
#define PLAYSTATE_PLAYING 3
|
#define PLAYSTATE_PLAYING 3
|
||||||
|
@ -26,23 +27,23 @@ SimpleAudioEngineOpenSL::~SimpleAudioEngineOpenSL()
|
||||||
bool SimpleAudioEngineOpenSL::initEngine()
|
bool SimpleAudioEngineOpenSL::initEngine()
|
||||||
{
|
{
|
||||||
bool bRet = false;
|
bool bRet = false;
|
||||||
do
|
if (s_pOpenSL == NULL)
|
||||||
{
|
{
|
||||||
s_pOpenSL = new OpenSLEngine();
|
s_pOpenSL = new OpenSLEngine();
|
||||||
s_pOpenSL->createEngine();
|
s_pOpenSL->createEngine();
|
||||||
|
|
||||||
bRet = true;
|
bRet = true;
|
||||||
} while (0);
|
}
|
||||||
return bRet;
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleAudioEngineOpenSL* SimpleAudioEngineOpenSL::sharedEngine()
|
SimpleAudioEngineOpenSL* SimpleAudioEngineOpenSL::sharedEngine()
|
||||||
{
|
{
|
||||||
if (! s_pEngine)
|
if (s_pEngine == NULL)
|
||||||
{
|
{
|
||||||
s_pEngine = new SimpleAudioEngineOpenSL();
|
s_pEngine = new SimpleAudioEngineOpenSL();
|
||||||
s_pEngine->initEngine();
|
|
||||||
}
|
}
|
||||||
|
s_pEngine->initEngine();
|
||||||
return s_pEngine;
|
return s_pEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,32 +52,42 @@ void SimpleAudioEngineOpenSL::end()
|
||||||
if (s_pOpenSL)
|
if (s_pOpenSL)
|
||||||
{
|
{
|
||||||
s_pOpenSL->closeEngine();
|
s_pOpenSL->closeEngine();
|
||||||
|
delete s_pOpenSL;
|
||||||
|
s_pOpenSL = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float SimpleAudioEngineOpenSL::getEffectsVolume()
|
float SimpleAudioEngineOpenSL::getEffectsVolume()
|
||||||
{
|
{
|
||||||
// TODO
|
return s_pOpenSL->getEffectsVolume();
|
||||||
return 1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleAudioEngineOpenSL::setEffectsVolume(float volume)
|
void SimpleAudioEngineOpenSL::setEffectsVolume(float volume)
|
||||||
{
|
{
|
||||||
int attenuation = (1 - volume) * 100;
|
if (volume < 0.0f) volume = 0.0f;
|
||||||
int millibel = attenuation * -15;
|
if (volume > 1.0f) volume = 1.0f;
|
||||||
s_pOpenSL->setEffectsVolume(millibel);
|
s_pOpenSL->setEffectsVolume(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int SimpleAudioEngineOpenSL::playEffect(const char* pszFilePath, bool bLoop)
|
unsigned int SimpleAudioEngineOpenSL::playEffect(const char* pszFilePath, bool bLoop)
|
||||||
{
|
{
|
||||||
unsigned int soundID = s_pOpenSL->preloadEffect(pszFilePath);
|
unsigned int soundID;
|
||||||
if (soundID != FILE_NOT_FOUND)
|
do
|
||||||
{
|
{
|
||||||
s_pOpenSL->setEffectState(soundID, PLAYSTATE_STOPPED);
|
soundID = s_pOpenSL->preloadEffect(pszFilePath);
|
||||||
s_pOpenSL->setEffectLooping(soundID, bLoop);
|
if (soundID != FILE_NOT_FOUND)
|
||||||
s_pOpenSL->setEffectState(soundID, PLAYSTATE_PLAYING);
|
{
|
||||||
}
|
if (s_pOpenSL->getEffectState(soundID) == PLAYSTATE_PLAYING)
|
||||||
|
{
|
||||||
|
// recreate an effect player
|
||||||
|
s_pOpenSL->recreatePlayer(pszFilePath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s_pOpenSL->setEffectState(soundID, PLAYSTATE_STOPPED);
|
||||||
|
s_pOpenSL->setEffectState(soundID, PLAYSTATE_PLAYING);
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
s_pOpenSL->setEffectLooping(soundID, bLoop);
|
||||||
return soundID;
|
return soundID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +113,7 @@ void SimpleAudioEngineOpenSL::resumeAllEffects()
|
||||||
|
|
||||||
void SimpleAudioEngineOpenSL::stopEffect(unsigned int nSoundId)
|
void SimpleAudioEngineOpenSL::stopEffect(unsigned int nSoundId)
|
||||||
{
|
{
|
||||||
s_pOpenSL->setEffectState(nSoundId, PLAYSTATE_STOPPED);
|
s_pOpenSL->setEffectState(nSoundId, PLAYSTATE_STOPPED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleAudioEngineOpenSL::stopAllEffects()
|
void SimpleAudioEngineOpenSL::stopAllEffects()
|
||||||
|
|
Loading…
Reference in New Issue