Use std::vector<char> to manage pcmData buffer on AudioCache, remove unused source from AudioCache.mm

This commit is contained in:
halx99 2020-07-30 18:09:50 +08:00
parent e250fe3707
commit 0d8457e9af
4 changed files with 49 additions and 101 deletions

View File

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

View File

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

View File

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

View File

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