mirror of https://github.com/axmolengine/axmol.git
Use std::vector<char> to manage pcmData buffer on AudioCache, remove unused source from AudioCache.mm
This commit is contained in:
parent
e250fe3707
commit
0d8457e9af
|
@ -2,6 +2,7 @@
|
||||||
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
||||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||||
Copyright (c) 2018-2020 HALX99.
|
Copyright (c) 2018-2020 HALX99.
|
||||||
|
Copyright (c) 2020 c4games.com.
|
||||||
|
|
||||||
http://www.cocos2d-x.org
|
http://www.cocos2d-x.org
|
||||||
|
|
||||||
|
@ -58,7 +59,6 @@ AudioCache::AudioCache()
|
||||||
, _format(-1)
|
, _format(-1)
|
||||||
, _duration(0.0f)
|
, _duration(0.0f)
|
||||||
, _alBufferId(INVALID_AL_BUFFER_ID)
|
, _alBufferId(INVALID_AL_BUFFER_ID)
|
||||||
, _pcmData(nullptr)
|
|
||||||
, _queBufferFrames(0)
|
, _queBufferFrames(0)
|
||||||
, _state(State::INITIAL)
|
, _state(State::INITIAL)
|
||||||
, _isDestroyed(std::make_shared<bool>(false))
|
, _isDestroyed(std::make_shared<bool>(false))
|
||||||
|
@ -90,25 +90,19 @@ AudioCache::~AudioCache()
|
||||||
}
|
}
|
||||||
//wait for the 'readDataTask' task to exit
|
//wait for the 'readDataTask' task to exit
|
||||||
_readDataTaskMutex.lock();
|
_readDataTaskMutex.lock();
|
||||||
_readDataTaskMutex.unlock();
|
|
||||||
|
|
||||||
if (_pcmData)
|
if (_state == State::READY)
|
||||||
{
|
{
|
||||||
if (_state == State::READY)
|
if (_alBufferId != INVALID_AL_BUFFER_ID && alIsBuffer(_alBufferId))
|
||||||
{
|
{
|
||||||
if (_alBufferId != INVALID_AL_BUFFER_ID && alIsBuffer(_alBufferId))
|
ALOGV("~AudioCache(id=%u), delete buffer: %u", _id, _alBufferId);
|
||||||
{
|
alDeleteBuffers(1, &_alBufferId);
|
||||||
ALOGV("~AudioCache(id=%u), delete buffer: %u", _id, _alBufferId);
|
_alBufferId = INVALID_AL_BUFFER_ID;
|
||||||
alDeleteBuffers(1, &_alBufferId);
|
|
||||||
_alBufferId = INVALID_AL_BUFFER_ID;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, (int)_state);
|
{
|
||||||
}
|
ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, (int)_state);
|
||||||
|
|
||||||
free(_pcmData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_queBufferFrames > 0)
|
if (_queBufferFrames > 0)
|
||||||
|
@ -119,6 +113,7 @@ AudioCache::~AudioCache()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ALOGVV("~AudioCache() %p, id=%u, end", this, _id);
|
ALOGVV("~AudioCache() %p, id=%u, end", this, _id);
|
||||||
|
_readDataTaskMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioCache::readDataTask(unsigned int selfId)
|
void AudioCache::readDataTask(unsigned int selfId)
|
||||||
|
@ -181,8 +176,8 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
uint32_t framesRead = 0;
|
uint32_t framesRead = 0;
|
||||||
uint32_t framesToReadOnce = (std::min)(totalFrames, static_cast<uint32_t>(sampleRate * QUEUEBUFFER_TIME_STEP * QUEUEBUFFER_NUM));
|
uint32_t framesToReadOnce = (std::min)(totalFrames, static_cast<uint32_t>(sampleRate * QUEUEBUFFER_TIME_STEP * QUEUEBUFFER_NUM));
|
||||||
|
|
||||||
_pcmData = (char*)malloc(dataSize);
|
std::vector<char> pcmBuffer(dataSize, 0);
|
||||||
memset(_pcmData, 0x00, dataSize);
|
auto pcmData = pcmBuffer.data();
|
||||||
|
|
||||||
alGenBuffers(1, &_alBufferId);
|
alGenBuffers(1, &_alBufferId);
|
||||||
auto alError = alGetError();
|
auto alError = alGetError();
|
||||||
|
@ -194,7 +189,7 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
if (*_isDestroyed)
|
if (*_isDestroyed)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
framesRead = decoder->readFixedFrames((std::min)(framesToReadOnce, remainingFrames), _pcmData + decoder->framesToBytes(_framesRead));
|
framesRead = decoder->readFixedFrames((std::min)(framesToReadOnce, remainingFrames), pcmData + decoder->framesToBytes(_framesRead));
|
||||||
_framesRead += framesRead;
|
_framesRead += framesRead;
|
||||||
remainingFrames -= framesRead;
|
remainingFrames -= framesRead;
|
||||||
|
|
||||||
|
@ -209,7 +204,7 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
{
|
{
|
||||||
frames = originalTotalFrames - _framesRead;
|
frames = originalTotalFrames - _framesRead;
|
||||||
}
|
}
|
||||||
framesRead = decoder->read(frames, _pcmData + decoder->framesToBytes(_framesRead));
|
framesRead = decoder->read(frames, pcmData + decoder->framesToBytes(_framesRead));
|
||||||
if (framesRead == 0)
|
if (framesRead == 0)
|
||||||
break;
|
break;
|
||||||
_framesRead += framesRead;
|
_framesRead += framesRead;
|
||||||
|
@ -221,13 +216,13 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
|
|
||||||
if (_framesRead < originalTotalFrames)
|
if (_framesRead < originalTotalFrames)
|
||||||
{
|
{
|
||||||
memset(_pcmData + decoder->framesToBytes(_framesRead), 0x00, decoder->framesToBytes(totalFrames - _framesRead));
|
memset(pcmData + decoder->framesToBytes(_framesRead), 0x00, decoder->framesToBytes(totalFrames - _framesRead));
|
||||||
}
|
}
|
||||||
ALOGV("pcm buffer was loaded successfully, total frames: %u, total read frames: %u, remainingFrames: %u", totalFrames, _framesRead, remainingFrames);
|
ALOGV("pcm buffer was loaded successfully, total frames: %u, total read frames: %u, remainingFrames: %u", totalFrames, _framesRead, remainingFrames);
|
||||||
|
|
||||||
if(sourceFormat == AUDIO_SOURCE_FORMAT::ADPCM || sourceFormat == AUDIO_SOURCE_FORMAT::IMA_ADPCM)
|
if(sourceFormat == AUDIO_SOURCE_FORMAT::ADPCM || sourceFormat == AUDIO_SOURCE_FORMAT::IMA_ADPCM)
|
||||||
alBufferi(_alBufferId, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, decoder->getSamplesPerBlock());
|
alBufferi(_alBufferId, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, decoder->getSamplesPerBlock());
|
||||||
alBufferData(_alBufferId, _format, _pcmData, (ALsizei)dataSize, (ALsizei)sampleRate);
|
alBufferData(_alBufferId, _format, pcmData, (ALsizei)dataSize, (ALsizei)sampleRate);
|
||||||
|
|
||||||
alError = alGetError();
|
alError = alGetError();
|
||||||
if (alError != AL_NO_ERROR)
|
if (alError != AL_NO_ERROR)
|
||||||
|
@ -258,11 +253,6 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
|
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
if (decoder != nullptr)
|
|
||||||
{
|
|
||||||
decoder->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioDecoderManager::destroyDecoder(decoder);
|
AudioDecoderManager::destroyDecoder(decoder);
|
||||||
|
|
||||||
if (_state != State::READY)
|
if (_state != State::READY)
|
||||||
|
|
|
@ -83,6 +83,7 @@ AudioDecoder* AudioDecoderManager::createDecoder(const std::string& path)
|
||||||
|
|
||||||
void AudioDecoderManager::destroyDecoder(AudioDecoder* decoder)
|
void AudioDecoderManager::destroyDecoder(AudioDecoder* decoder)
|
||||||
{
|
{
|
||||||
|
if (decoder) decoder->close();
|
||||||
delete decoder;
|
delete decoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
Copyright (c) 2014-2016 Chukong Technologies Inc.
|
||||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||||
Copyright (c) 2018 HALX99.
|
Copyright (c) 2018-2020 HALX99.
|
||||||
|
Copyright (c) 2020 c4games.com.
|
||||||
|
|
||||||
http://www.cocos2d-x.org
|
http://www.cocos2d-x.org
|
||||||
|
|
||||||
|
@ -53,52 +54,14 @@ unsigned int __idIndex = 0;
|
||||||
#define INVALID_AL_BUFFER_ID 0xFFFFFFFF
|
#define INVALID_AL_BUFFER_ID 0xFFFFFFFF
|
||||||
#define PCMDATA_CACHEMAXSIZE 1048576
|
#define PCMDATA_CACHEMAXSIZE 1048576
|
||||||
|
|
||||||
@interface NSTimerWrapper : NSObject
|
|
||||||
{
|
|
||||||
std::function<void()> _timeoutCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation NSTimerWrapper
|
|
||||||
|
|
||||||
-(id) initWithTimeInterval:(double) seconds callback:(const std::function<void()>&) cb
|
|
||||||
{
|
|
||||||
if (self = [super init])
|
|
||||||
{
|
|
||||||
_timeoutCallback = cb;
|
|
||||||
NSTimer* timer = [NSTimer timerWithTimeInterval:seconds target: self selector:@selector(onTimeoutCallback:) userInfo:nil repeats:NO];
|
|
||||||
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
|
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void) onTimeoutCallback: (NSTimer*) timer
|
|
||||||
{
|
|
||||||
if (_timeoutCallback != nullptr)
|
|
||||||
{
|
|
||||||
_timeoutCallback();
|
|
||||||
_timeoutCallback = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void) dealloc
|
|
||||||
{
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
using namespace cocos2d;
|
using namespace cocos2d;
|
||||||
|
|
||||||
AudioCache::AudioCache()
|
AudioCache::AudioCache()
|
||||||
: _format(-1)
|
: _totalFrames(0)
|
||||||
, _duration(0.0f)
|
|
||||||
, _totalFrames(0)
|
|
||||||
, _framesRead(0)
|
, _framesRead(0)
|
||||||
|
, _format(-1)
|
||||||
|
, _duration(0.0f)
|
||||||
, _alBufferId(INVALID_AL_BUFFER_ID)
|
, _alBufferId(INVALID_AL_BUFFER_ID)
|
||||||
, _pcmData(nullptr)
|
|
||||||
, _queBufferFrames(0)
|
, _queBufferFrames(0)
|
||||||
, _state(State::INITIAL)
|
, _state(State::INITIAL)
|
||||||
, _isDestroyed(std::make_shared<bool>(false))
|
, _isDestroyed(std::make_shared<bool>(false))
|
||||||
|
@ -142,7 +105,7 @@ AudioCache::~AudioCache()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, _state);
|
ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, (int)_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_queBufferFrames > 0)
|
if (_queBufferFrames > 0)
|
||||||
|
@ -159,7 +122,7 @@ AudioCache::~AudioCache()
|
||||||
void AudioCache::readDataTask(unsigned int selfId)
|
void AudioCache::readDataTask(unsigned int selfId)
|
||||||
{
|
{
|
||||||
//Note: It's in sub thread
|
//Note: It's in sub thread
|
||||||
ALOGVV("readDataTask, cache id=%u", selfId);
|
ALOGVV("readDataTask begin, cache id=%u", selfId);
|
||||||
|
|
||||||
_readDataTaskMutex.lock();
|
_readDataTaskMutex.lock();
|
||||||
_state = State::LOADING;
|
_state = State::LOADING;
|
||||||
|
@ -223,19 +186,19 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
// Reset to frame 0
|
// Reset to frame 0
|
||||||
BREAK_IF_ERR_LOG(!decoder->seek(0), "AudioDecoder::seek(0) failed!");
|
BREAK_IF_ERR_LOG(!decoder->seek(0), "AudioDecoder::seek(0) failed!");
|
||||||
|
|
||||||
_pcmData = (char*)malloc(dataSize);
|
std::vector<char> pcmBuffer(dataSize, 0);
|
||||||
memset(_pcmData, 0x00, dataSize);
|
auto pcmData = pcmBuffer.data();
|
||||||
ALOGV(" id=%u _pcmData alloc: %p", selfId, _pcmData);
|
ALOGV(" id=%u pcmData alloc: %p", selfId, pcmData);
|
||||||
|
|
||||||
if (adjustFrames > 0)
|
if (adjustFrames > 0)
|
||||||
{
|
{
|
||||||
memcpy(_pcmData + (dataSize - adjustFrameBuf.size()), adjustFrameBuf.data(), adjustFrameBuf.size());
|
memcpy(pcmData + (dataSize - adjustFrameBuf.size()), adjustFrameBuf.data(), adjustFrameBuf.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*_isDestroyed)
|
if (*_isDestroyed)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
framesRead = decoder->readFixedFrames(std::min(framesToReadOnce, remainingFrames), _pcmData + decoder->framesToBytes(_framesRead));
|
framesRead = decoder->readFixedFrames(std::min(framesToReadOnce, remainingFrames), pcmData + decoder->framesToBytes(_framesRead));
|
||||||
_framesRead += framesRead;
|
_framesRead += framesRead;
|
||||||
remainingFrames -= framesRead;
|
remainingFrames -= framesRead;
|
||||||
|
|
||||||
|
@ -250,7 +213,7 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
{
|
{
|
||||||
frames = originalTotalFrames - _framesRead;
|
frames = originalTotalFrames - _framesRead;
|
||||||
}
|
}
|
||||||
framesRead = decoder->read(frames, _pcmData + decoder->framesToBytes(_framesRead));
|
framesRead = decoder->read(frames, pcmData + decoder->framesToBytes(_framesRead));
|
||||||
if (framesRead == 0)
|
if (framesRead == 0)
|
||||||
break;
|
break;
|
||||||
_framesRead += framesRead;
|
_framesRead += framesRead;
|
||||||
|
@ -259,7 +222,7 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
|
|
||||||
if (_framesRead < originalTotalFrames)
|
if (_framesRead < originalTotalFrames)
|
||||||
{
|
{
|
||||||
memset(_pcmData + decoder->framesToBytes(_framesRead), 0x00, decoder->framesToBytes(totalFrames - _framesRead));
|
memset(pcmData + decoder->framesToBytes(_framesRead), 0x00, decoder->framesToBytes(totalFrames - _framesRead));
|
||||||
}
|
}
|
||||||
|
|
||||||
ALOGV("pcm buffer was loaded successfully, total frames: %u, total read frames: %u, adjust frames: %u, remainingFrames: %u", totalFrames, _framesRead, adjustFrames, remainingFrames);
|
ALOGV("pcm buffer was loaded successfully, total frames: %u, total read frames: %u, adjust frames: %u, remainingFrames: %u", totalFrames, _framesRead, adjustFrames, remainingFrames);
|
||||||
|
@ -271,9 +234,9 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
ALOGE("%s: attaching audio to buffer fail: %x", __PRETTY_FUNCTION__, alError);
|
ALOGE("%s: attaching audio to buffer fail: %x", __PRETTY_FUNCTION__, alError);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ALOGV(" id=%u generated alGenBuffers: %u for _pcmData: %p", selfId, _alBufferId, _pcmData);
|
ALOGV(" id=%u generated alGenBuffers: %u for pcmData: %p", selfId, _alBufferId, pcmData);
|
||||||
ALOGV(" id=%u _pcmData alBufferData: %p", selfId, _pcmData);
|
ALOGV(" id=%u pcmData alBufferData: %p", selfId, pcmData);
|
||||||
alBufferData(_alBufferId, _format, _pcmData, (ALsizei)dataSize, (ALsizei)sampleRate);
|
alBufferData(_alBufferId, _format, pcmData, (ALsizei)dataSize, (ALsizei)sampleRate);
|
||||||
_state = State::READY;
|
_state = State::READY;
|
||||||
invokingPlayCallbacks();
|
invokingPlayCallbacks();
|
||||||
|
|
||||||
|
@ -298,14 +261,19 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
|
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
if (_pcmData != nullptr){
|
|
||||||
CC_SAFE_FREE(_pcmData);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(decoder)
|
|
||||||
decoder->close();
|
|
||||||
AudioDecoderManager::destroyDecoder(decoder);
|
AudioDecoderManager::destroyDecoder(decoder);
|
||||||
|
|
||||||
|
if (_state != State::READY)
|
||||||
|
{
|
||||||
|
_state = State::FAILED;
|
||||||
|
if (_alBufferId != INVALID_AL_BUFFER_ID && alIsBuffer(_alBufferId))
|
||||||
|
{
|
||||||
|
ALOGV("readDataTask failed, delete buffer: %u", _alBufferId);
|
||||||
|
alDeleteBuffers(1, &_alBufferId);
|
||||||
|
_alBufferId = INVALID_AL_BUFFER_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set before invokingPlayCallbacks, otherwise, may cause dead-lock
|
// Set before invokingPlayCallbacks, otherwise, may cause dead-lock
|
||||||
_isLoadingFinished = true;
|
_isLoadingFinished = true;
|
||||||
|
|
||||||
|
@ -313,18 +281,8 @@ void AudioCache::readDataTask(unsigned int selfId)
|
||||||
invokingPlayCallbacks();
|
invokingPlayCallbacks();
|
||||||
invokingLoadCallbacks();
|
invokingLoadCallbacks();
|
||||||
|
|
||||||
if (_state != State::READY)
|
|
||||||
{
|
|
||||||
_state = State::FAILED;
|
|
||||||
if (_alBufferId != INVALID_AL_BUFFER_ID && alIsBuffer(_alBufferId))
|
|
||||||
{
|
|
||||||
ALOGV(" id=%u readDataTask failed, delete buffer: %u", selfId, _alBufferId);
|
|
||||||
alDeleteBuffers(1, &_alBufferId);
|
|
||||||
_alBufferId = INVALID_AL_BUFFER_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_readDataTaskMutex.unlock();
|
_readDataTaskMutex.unlock();
|
||||||
|
ALOGVV("readDataTask end, cache id=%u", selfId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioCache::addPlayCallback(const std::function<void()>& callback)
|
void AudioCache::addPlayCallback(const std::function<void()>& callback)
|
||||||
|
@ -345,7 +303,7 @@ void AudioCache::addPlayCallback(const std::function<void()>& callback)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ALOGE("Invalid state: %d", _state);
|
ALOGE("Invalid state: %d", (int)_state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +337,7 @@ void AudioCache::addLoadCallback(const std::function<void(bool)>& callback)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ALOGE("Invalid state: %d", _state);
|
ALOGE("Invalid state: %d", (int)_state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@ protected:
|
||||||
* Cache pcm data when sizeInBytes less than PCMDATA_CACHEMAXSIZE
|
* Cache pcm data when sizeInBytes less than PCMDATA_CACHEMAXSIZE
|
||||||
*/
|
*/
|
||||||
ALuint _alBufferId;
|
ALuint _alBufferId;
|
||||||
char* _pcmData;
|
|
||||||
|
|
||||||
/*Queue buffer related stuff
|
/*Queue buffer related stuff
|
||||||
* Streaming in OpenAL when sizeInBytes greater then PCMDATA_CACHEMAXSIZE
|
* Streaming in OpenAL when sizeInBytes greater then PCMDATA_CACHEMAXSIZE
|
||||||
|
|
Loading…
Reference in New Issue