diff --git a/cocos/audio/AudioCache.cpp b/cocos/audio/AudioCache.cpp index 8cf1d4adeb..f06cd322d3 100644 --- a/cocos/audio/AudioCache.cpp +++ b/cocos/audio/AudioCache.cpp @@ -2,6 +2,7 @@ Copyright (c) 2014-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2018-2020 HALX99. + Copyright (c) 2020 c4games.com. http://www.cocos2d-x.org @@ -58,7 +59,6 @@ AudioCache::AudioCache() , _format(-1) , _duration(0.0f) , _alBufferId(INVALID_AL_BUFFER_ID) -, _pcmData(nullptr) , _queBufferFrames(0) , _state(State::INITIAL) , _isDestroyed(std::make_shared(false)) @@ -90,25 +90,19 @@ AudioCache::~AudioCache() } //wait for the 'readDataTask' task to exit _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); - _alBufferId = INVALID_AL_BUFFER_ID; - } + ALOGV("~AudioCache(id=%u), delete buffer: %u", _id, _alBufferId); + alDeleteBuffers(1, &_alBufferId); + _alBufferId = INVALID_AL_BUFFER_ID; } - else - { - ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, (int)_state); - } - - free(_pcmData); + } + else + { + ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, (int)_state); } if (_queBufferFrames > 0) @@ -119,6 +113,7 @@ AudioCache::~AudioCache() } } ALOGVV("~AudioCache() %p, id=%u, end", this, _id); + _readDataTaskMutex.unlock(); } void AudioCache::readDataTask(unsigned int selfId) @@ -181,8 +176,8 @@ void AudioCache::readDataTask(unsigned int selfId) uint32_t framesRead = 0; uint32_t framesToReadOnce = (std::min)(totalFrames, static_cast(sampleRate * QUEUEBUFFER_TIME_STEP * QUEUEBUFFER_NUM)); - _pcmData = (char*)malloc(dataSize); - memset(_pcmData, 0x00, dataSize); + std::vector pcmBuffer(dataSize, 0); + auto pcmData = pcmBuffer.data(); alGenBuffers(1, &_alBufferId); auto alError = alGetError(); @@ -194,7 +189,7 @@ void AudioCache::readDataTask(unsigned int selfId) if (*_isDestroyed) 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; remainingFrames -= framesRead; @@ -209,7 +204,7 @@ void AudioCache::readDataTask(unsigned int selfId) { frames = originalTotalFrames - _framesRead; } - framesRead = decoder->read(frames, _pcmData + decoder->framesToBytes(_framesRead)); + framesRead = decoder->read(frames, pcmData + decoder->framesToBytes(_framesRead)); if (framesRead == 0) break; _framesRead += framesRead; @@ -221,13 +216,13 @@ void AudioCache::readDataTask(unsigned int selfId) 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); if(sourceFormat == AUDIO_SOURCE_FORMAT::ADPCM || sourceFormat == AUDIO_SOURCE_FORMAT::IMA_ADPCM) 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(); if (alError != AL_NO_ERROR) @@ -258,11 +253,6 @@ void AudioCache::readDataTask(unsigned int selfId) } while (false); - if (decoder != nullptr) - { - decoder->close(); - } - AudioDecoderManager::destroyDecoder(decoder); if (_state != State::READY) diff --git a/cocos/audio/AudioDecoderManager.cpp b/cocos/audio/AudioDecoderManager.cpp index 9b4a55f10a..a5d42476a0 100644 --- a/cocos/audio/AudioDecoderManager.cpp +++ b/cocos/audio/AudioDecoderManager.cpp @@ -83,6 +83,7 @@ AudioDecoder* AudioDecoderManager::createDecoder(const std::string& path) void AudioDecoderManager::destroyDecoder(AudioDecoder* decoder) { + if (decoder) decoder->close(); delete decoder; } diff --git a/cocos/audio/apple/AudioCache.mm b/cocos/audio/apple/AudioCache.mm index ed42c863f8..72c2607436 100644 --- a/cocos/audio/apple/AudioCache.mm +++ b/cocos/audio/apple/AudioCache.mm @@ -1,7 +1,8 @@ /**************************************************************************** Copyright (c) 2014-2016 Chukong Technologies Inc. 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 @@ -53,52 +54,14 @@ unsigned int __idIndex = 0; #define INVALID_AL_BUFFER_ID 0xFFFFFFFF #define PCMDATA_CACHEMAXSIZE 1048576 -@interface NSTimerWrapper : NSObject -{ - std::function _timeoutCallback; -} - -@end - -@implementation NSTimerWrapper - --(id) initWithTimeInterval:(double) seconds callback:(const std::function&) 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; AudioCache::AudioCache() -: _format(-1) -, _duration(0.0f) -, _totalFrames(0) +: _totalFrames(0) , _framesRead(0) +, _format(-1) +, _duration(0.0f) , _alBufferId(INVALID_AL_BUFFER_ID) -, _pcmData(nullptr) , _queBufferFrames(0) , _state(State::INITIAL) , _isDestroyed(std::make_shared(false)) @@ -142,7 +105,7 @@ AudioCache::~AudioCache() } 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) @@ -159,7 +122,7 @@ AudioCache::~AudioCache() void AudioCache::readDataTask(unsigned int selfId) { //Note: It's in sub thread - ALOGVV("readDataTask, cache id=%u", selfId); + ALOGVV("readDataTask begin, cache id=%u", selfId); _readDataTaskMutex.lock(); _state = State::LOADING; @@ -223,19 +186,19 @@ void AudioCache::readDataTask(unsigned int selfId) // Reset to frame 0 BREAK_IF_ERR_LOG(!decoder->seek(0), "AudioDecoder::seek(0) failed!"); - _pcmData = (char*)malloc(dataSize); - memset(_pcmData, 0x00, dataSize); - ALOGV(" id=%u _pcmData alloc: %p", selfId, _pcmData); + std::vector pcmBuffer(dataSize, 0); + auto pcmData = pcmBuffer.data(); + ALOGV(" id=%u pcmData alloc: %p", selfId, pcmData); if (adjustFrames > 0) { - memcpy(_pcmData + (dataSize - adjustFrameBuf.size()), adjustFrameBuf.data(), adjustFrameBuf.size()); + memcpy(pcmData + (dataSize - adjustFrameBuf.size()), adjustFrameBuf.data(), adjustFrameBuf.size()); } if (*_isDestroyed) 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; remainingFrames -= framesRead; @@ -250,7 +213,7 @@ void AudioCache::readDataTask(unsigned int selfId) { frames = originalTotalFrames - _framesRead; } - framesRead = decoder->read(frames, _pcmData + decoder->framesToBytes(_framesRead)); + framesRead = decoder->read(frames, pcmData + decoder->framesToBytes(_framesRead)); if (framesRead == 0) break; _framesRead += framesRead; @@ -259,7 +222,7 @@ void AudioCache::readDataTask(unsigned int selfId) 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); @@ -271,9 +234,9 @@ void AudioCache::readDataTask(unsigned int selfId) ALOGE("%s: attaching audio to buffer fail: %x", __PRETTY_FUNCTION__, alError); break; } - ALOGV(" id=%u generated alGenBuffers: %u for _pcmData: %p", selfId, _alBufferId, _pcmData); - ALOGV(" id=%u _pcmData alBufferData: %p", selfId, _pcmData); - alBufferData(_alBufferId, _format, _pcmData, (ALsizei)dataSize, (ALsizei)sampleRate); + ALOGV(" id=%u generated alGenBuffers: %u for pcmData: %p", selfId, _alBufferId, pcmData); + ALOGV(" id=%u pcmData alBufferData: %p", selfId, pcmData); + alBufferData(_alBufferId, _format, pcmData, (ALsizei)dataSize, (ALsizei)sampleRate); _state = State::READY; invokingPlayCallbacks(); @@ -298,14 +261,19 @@ void AudioCache::readDataTask(unsigned int selfId) } while (false); - if (_pcmData != nullptr){ - CC_SAFE_FREE(_pcmData); - } - - if(decoder) - decoder->close(); 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 _isLoadingFinished = true; @@ -313,18 +281,8 @@ void AudioCache::readDataTask(unsigned int selfId) invokingPlayCallbacks(); 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(); + ALOGVV("readDataTask end, cache id=%u", selfId); } void AudioCache::addPlayCallback(const std::function& callback) @@ -345,7 +303,7 @@ void AudioCache::addPlayCallback(const std::function& callback) break; default: - ALOGE("Invalid state: %d", _state); + ALOGE("Invalid state: %d", (int)_state); break; } } @@ -379,7 +337,7 @@ void AudioCache::addLoadCallback(const std::function& callback) break; default: - ALOGE("Invalid state: %d", _state); + ALOGE("Invalid state: %d", (int)_state); break; } } diff --git a/cocos/audio/include/AudioCache.h b/cocos/audio/include/AudioCache.h index ec6c9b7201..d5f54aab5e 100644 --- a/cocos/audio/include/AudioCache.h +++ b/cocos/audio/include/AudioCache.h @@ -91,7 +91,6 @@ protected: * Cache pcm data when sizeInBytes less than PCMDATA_CACHEMAXSIZE */ ALuint _alBufferId; - char* _pcmData; /*Queue buffer related stuff * Streaming in OpenAL when sizeInBytes greater then PCMDATA_CACHEMAXSIZE