mirror of https://github.com/axmolengine/axmol.git
fixed #17800: [iOS] Streaming audio (normally a background music) maybe cut and may not be looped. (#17947)
* fixed #17800: [iOS] Streaming audio (normally a background music) may be cut and may not be looped. * Updates including.
This commit is contained in:
parent
a23924c95b
commit
567fa5b0a7
|
@ -66,6 +66,7 @@ public:
|
|||
|
||||
private:
|
||||
void _play2d(AudioCache *cache, int audioID);
|
||||
static ALvoid myAlSourceNotificationCallback(ALuint sid, ALuint notificationID, ALvoid* userData);
|
||||
|
||||
ALuint _alSources[MAX_AUDIOINSTANCES];
|
||||
|
||||
|
|
|
@ -41,8 +41,27 @@
|
|||
using namespace cocos2d;
|
||||
using namespace cocos2d::experimental;
|
||||
|
||||
static ALCdevice *s_ALDevice = nullptr;
|
||||
static ALCcontext *s_ALContext = nullptr;
|
||||
static ALCdevice* s_ALDevice = nullptr;
|
||||
static ALCcontext* s_ALContext = nullptr;
|
||||
static AudioEngineImpl* s_instance = nullptr;
|
||||
|
||||
typedef ALvoid (*alSourceNotificationProc)(ALuint sid, ALuint notificationID, ALvoid* userData);
|
||||
typedef ALenum (*alSourceAddNotificationProcPtr)(ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData);
|
||||
static ALenum alSourceAddNotificationExt(ALuint sid, ALuint notificationID, alSourceNotificationProc notifyProc, ALvoid* userData)
|
||||
{
|
||||
static alSourceAddNotificationProcPtr proc = nullptr;
|
||||
|
||||
if (proc == nullptr)
|
||||
{
|
||||
proc = (alSourceAddNotificationProcPtr)alcGetProcAddress(nullptr, "alSourceAddNotification");
|
||||
}
|
||||
|
||||
if (proc)
|
||||
{
|
||||
return proc(sid, notificationID, notifyProc, userData);
|
||||
}
|
||||
return AL_INVALID_VALUE;
|
||||
}
|
||||
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
@interface AudioEngineSessionHandler : NSObject
|
||||
|
@ -189,12 +208,29 @@ void AudioEngineInterruptionListenerCallback(void* user_data, UInt32 interruptio
|
|||
static id s_AudioEngineSessionHandler = nullptr;
|
||||
#endif
|
||||
|
||||
ALvoid AudioEngineImpl::myAlSourceNotificationCallback(ALuint sid, ALuint notificationID, ALvoid* userData)
|
||||
{
|
||||
// Currently, we only care about AL_BUFFERS_PROCESSED event
|
||||
if (notificationID != AL_BUFFERS_PROCESSED)
|
||||
return;
|
||||
|
||||
AudioPlayer* player = nullptr;
|
||||
for (const auto& e : s_instance->_audioPlayers)
|
||||
{
|
||||
player = e.second;
|
||||
if (player->_alSource == sid && player->_streamingSource)
|
||||
{
|
||||
player->wakeupRotateThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioEngineImpl::AudioEngineImpl()
|
||||
: _lazyInitLoop(true)
|
||||
, _currentAudioID(0)
|
||||
, _scheduler(nullptr)
|
||||
{
|
||||
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
AudioEngineImpl::~AudioEngineImpl()
|
||||
|
@ -219,6 +255,7 @@ AudioEngineImpl::~AudioEngineImpl()
|
|||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
|
||||
[s_AudioEngineSessionHandler release];
|
||||
#endif
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
bool AudioEngineImpl::init()
|
||||
|
@ -245,6 +282,7 @@ bool AudioEngineImpl::init()
|
|||
|
||||
for (int i = 0; i < MAX_AUDIOINSTANCES; ++i) {
|
||||
_alSourceUsed[_alSources[i]] = false;
|
||||
alSourceAddNotificationExt(_alSources[i], AL_BUFFERS_PROCESSED, myAlSourceNotificationCallback, nullptr);
|
||||
}
|
||||
|
||||
// fixed #16170: Random crash in alGenBuffers(AudioCache::readDataTask) at startup
|
||||
|
@ -308,7 +346,6 @@ bool AudioEngineImpl::init()
|
|||
|
||||
// ================ Workaround end ================ //
|
||||
|
||||
|
||||
_scheduler = Director::getInstance()->getScheduler();
|
||||
ret = true;
|
||||
ALOGI("OpenAL was initialized successfully!");
|
||||
|
|
|
@ -27,12 +27,14 @@
|
|||
#include "platform/CCPlatformConfig.h"
|
||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC
|
||||
|
||||
#include "platform/CCPlatformMacros.h"
|
||||
#include "audio/apple/AudioMacros.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#import <OpenAL/al.h>
|
||||
#include "platform/CCPlatformMacros.h"
|
||||
#include <OpenAL/al.h>
|
||||
|
||||
NS_CC_BEGIN
|
||||
namespace experimental{
|
||||
|
@ -57,6 +59,7 @@ protected:
|
|||
void setCache(AudioCache* cache);
|
||||
void rotateBufferThread(int offsetFrame);
|
||||
bool play2d();
|
||||
void wakeupRotateThread();
|
||||
|
||||
AudioCache* _audioCache;
|
||||
|
||||
|
@ -72,12 +75,13 @@ protected:
|
|||
//play by circular buffer
|
||||
float _currTime;
|
||||
bool _streamingSource;
|
||||
ALuint _bufferIds[3];
|
||||
ALuint _bufferIds[QUEUEBUFFER_NUM];
|
||||
std::thread* _rotateBufferThread;
|
||||
std::condition_variable _sleepCondition;
|
||||
std::mutex _sleepMutex;
|
||||
bool _timeDirty;
|
||||
bool _isRotateThreadExited;
|
||||
std::atomic_bool _needWakeupRotateThread;
|
||||
|
||||
std::mutex _play2dMutex;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ AudioPlayer::AudioPlayer()
|
|||
, _rotateBufferThread(nullptr)
|
||||
, _timeDirty(false)
|
||||
, _isRotateThreadExited(false)
|
||||
, _needWakeupRotateThread(false)
|
||||
, _id(++__idIndex)
|
||||
{
|
||||
memset(_bufferIds, 0, sizeof(_bufferIds));
|
||||
|
@ -71,7 +72,7 @@ AudioPlayer::~AudioPlayer()
|
|||
|
||||
if (_streamingSource)
|
||||
{
|
||||
alDeleteBuffers(3, _bufferIds);
|
||||
alDeleteBuffers(QUEUEBUFFER_NUM, _bufferIds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +173,7 @@ bool AudioPlayer::play2d()
|
|||
}
|
||||
else
|
||||
{
|
||||
alGenBuffers(3, _bufferIds);
|
||||
alGenBuffers(QUEUEBUFFER_NUM, _bufferIds);
|
||||
|
||||
auto alError = alGetError();
|
||||
if (alError == AL_NO_ERROR)
|
||||
|
@ -302,7 +303,12 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
|||
break;
|
||||
}
|
||||
|
||||
_sleepCondition.wait_for(lk,std::chrono::milliseconds(75));
|
||||
if (!_needWakeupRotateThread)
|
||||
{
|
||||
_sleepCondition.wait_for(lk,std::chrono::milliseconds(75));
|
||||
}
|
||||
|
||||
_needWakeupRotateThread = false;
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
@ -313,6 +319,12 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
|||
_isRotateThreadExited = true;
|
||||
}
|
||||
|
||||
void AudioPlayer::wakeupRotateThread()
|
||||
{
|
||||
_needWakeupRotateThread = true;
|
||||
_sleepCondition.notify_all();
|
||||
}
|
||||
|
||||
bool AudioPlayer::setLoop(bool loop)
|
||||
{
|
||||
if (!_isDestroyed ) {
|
||||
|
|
Loading…
Reference in New Issue