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:
mustime 2012-08-02 14:28:40 +08:00
parent b4e7e1152f
commit 6beae122da
4 changed files with 287 additions and 139 deletions

View File

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

View File

@ -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;
} }

View File

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

View File

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