From a651879ee6a8e9d9efd8883bbdfc066d7e41d2b3 Mon Sep 17 00:00:00 2001 From: halx99 Date: Mon, 3 Jan 2022 11:34:58 +0800 Subject: [PATCH] Tidy audio folder --- core/CMakeLists.txt | 2 +- core/audio/CMakeLists.txt | 46 +- core/audio/include/AudioCache.h | 111 --- core/audio/include/AudioDecoder.h | 151 --- core/audio/include/AudioDecoderEXT.h | 109 --- core/audio/include/AudioDecoderManager.h | 44 - core/audio/include/AudioDecoderMp3.h | 93 -- core/audio/include/AudioDecoderOgg.h | 81 -- core/audio/include/AudioDecoderWav.h | 174 ---- core/audio/include/AudioEngine.h | 371 -------- core/audio/include/AudioEngineImpl.h | 100 -- core/audio/include/AudioMacros.h | 93 -- core/audio/include/AudioPlayer.h | 101 -- core/audio/include/alconfig.h | 56 -- core/audio/src/AudioCache.cpp | 426 --------- core/audio/src/AudioDecoder.cpp | 105 --- core/audio/src/AudioDecoderEXT.mm | 225 ----- core/audio/src/AudioDecoderManager.cpp | 96 -- core/audio/src/AudioDecoderMp3.cpp | 301 ------ core/audio/src/AudioDecoderOgg.cpp | 119 --- core/audio/src/AudioDecoderWav.cpp | 261 ------ core/audio/src/AudioEngine.cpp | 611 ------------ core/audio/src/AudioEngineImpl.mm | 872 ------------------ core/audio/src/AudioPlayer.cpp | 465 ---------- core/audio/src/linux-link.cpp | 2 - core/base/CCDirector.cpp | 2 +- extensions/cocostudio/CCComAudio.cpp | 1 - extensions/cocostudio/CCSSceneReader.cpp | 1 - .../auto/lua_cocos2dx_audioengine_auto.cpp | 2 +- .../lua_cocos2dx_audioengine_manual.cpp | 2 +- templates/cpp-template-default/CMakeLists.txt | 2 +- .../Classes/AppDelegate.cpp | 2 +- .../runtime-src/Classes/AppDelegate.cpp | 2 +- .../NewAudioEngineTest/NewAudioEngineTest.h | 2 +- tests/cpp-tests/Classes/testBasic.h | 1 - tests/fairygui-tests/Classes/AppDelegate.cpp | 31 +- tools/tolua/cocos2dx_audioengine.ini | 2 +- 37 files changed, 33 insertions(+), 5032 deletions(-) delete mode 100644 core/audio/include/AudioCache.h delete mode 100644 core/audio/include/AudioDecoder.h delete mode 100644 core/audio/include/AudioDecoderEXT.h delete mode 100644 core/audio/include/AudioDecoderManager.h delete mode 100644 core/audio/include/AudioDecoderMp3.h delete mode 100644 core/audio/include/AudioDecoderOgg.h delete mode 100644 core/audio/include/AudioDecoderWav.h delete mode 100644 core/audio/include/AudioEngine.h delete mode 100644 core/audio/include/AudioEngineImpl.h delete mode 100644 core/audio/include/AudioMacros.h delete mode 100644 core/audio/include/AudioPlayer.h delete mode 100644 core/audio/include/alconfig.h delete mode 100644 core/audio/src/AudioCache.cpp delete mode 100644 core/audio/src/AudioDecoder.cpp delete mode 100644 core/audio/src/AudioDecoderEXT.mm delete mode 100644 core/audio/src/AudioDecoderManager.cpp delete mode 100644 core/audio/src/AudioDecoderMp3.cpp delete mode 100644 core/audio/src/AudioDecoderOgg.cpp delete mode 100644 core/audio/src/AudioDecoderWav.cpp delete mode 100644 core/audio/src/AudioEngine.cpp delete mode 100644 core/audio/src/AudioEngineImpl.mm delete mode 100644 core/audio/src/AudioPlayer.cpp delete mode 100644 core/audio/src/linux-link.cpp diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 5fdcf80776..b63f3c5e29 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -135,7 +135,7 @@ target_include_directories(${ADXE_CORE_LIB} INTERFACE ${ADXE_ROOT_PATH}/thirdparty INTERFACE ${ADXE_ROOT_PATH}/extensions INTERFACE ${ADXE_ROOT_PATH}/core/base - INTERFACE ${ADXE_ROOT_PATH}/core/audio/include + INTERFACE ${ADXE_ROOT_PATH}/core/audio INTERFACE ${ADXE_ROOT_PATH}/core/platform/${PLATFORM_FOLDER} ) diff --git a/core/audio/CMakeLists.txt b/core/audio/CMakeLists.txt index 411b78b092..48e219f6aa 100644 --- a/core/audio/CMakeLists.txt +++ b/core/audio/CMakeLists.txt @@ -1,50 +1,50 @@ # common headers and sources set(COCOS_AUDIO_HEADER - audio/include/alconfig.h - audio/include/AudioEngine.h - audio/include/AudioMacros.h - audio/include/AudioDecoderManager.h - audio/include/AudioDecoder.h - audio/include/AudioDecoderOgg.h - audio/include/AudioPlayer.h - audio/include/AudioCache.h - audio/include/AudioEngineImpl.h + audio/alconfig.h + audio/AudioEngine.h + audio/AudioMacros.h + audio/AudioDecoderManager.h + audio/AudioDecoder.h + audio/AudioDecoderOgg.h + audio/AudioPlayer.h + audio/AudioCache.h + audio/AudioEngineImpl.h ) set(COCOS_AUDIO_SRC - audio/src/AudioEngine.cpp - audio/src/AudioDecoderManager.cpp - audio/src/AudioDecoder.cpp - audio/src/AudioDecoderOgg.cpp - audio/src/AudioPlayer.cpp - audio/src/AudioCache.cpp + audio/AudioEngine.cpp + audio/AudioDecoderManager.cpp + audio/AudioDecoder.cpp + audio/AudioDecoderOgg.cpp + audio/AudioPlayer.cpp + audio/AudioCache.cpp ) # stupid, clang always compie .mm as objc/cpp mix obj if(ANDROID OR LINUX) set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC} - audio/src/linux-link.cpp + audio/linux-link.cpp ) else() set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC} - audio/src/AudioEngineImpl.mm + audio/AudioEngineImpl.mm ) endif() # Apple, we use system audio decoder if(APPLE) set(COCOS_AUDIO_HEADER ${COCOS_AUDIO_HEADER} - audio/include/AudioDecoderEXT.h) + audio/AudioDecoderEXT.h) set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC} - audio/src/AudioDecoderEXT.mm) + audio/AudioDecoderEXT.mm) else() set(COCOS_AUDIO_HEADER ${COCOS_AUDIO_HEADER} - audio/include/AudioDecoderMp3.h - audio/include/AudioDecoderWav.h + audio/AudioDecoderMp3.h + audio/AudioDecoderWav.h ) set(COCOS_AUDIO_SRC ${COCOS_AUDIO_SRC} - audio/src/AudioDecoderMp3.cpp - audio/src/AudioDecoderWav.cpp + audio/AudioDecoderMp3.cpp + audio/AudioDecoderWav.cpp ) endif() diff --git a/core/audio/include/AudioCache.h b/core/audio/include/AudioCache.h deleted file mode 100644 index 74ea29ad6a..0000000000 --- a/core/audio/include/AudioCache.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018-2020 simdsoft.com, @HALX99 - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "platform/CCPlatformConfig.h" - -#include -#include -#include -#include - -#include "platform/CCPlatformMacros.h" -#include "audio/include/AudioMacros.h" -#include "audio/include/alconfig.h" - -NS_CC_BEGIN - -class AudioEngineImpl; -class AudioPlayer; - -class CC_DLL AudioCache -{ -public: - enum class State - { - INITIAL, - LOADING, - READY, - FAILED - }; - - AudioCache(); - ~AudioCache(); - - void addPlayCallback(const std::function& callback); - - void addLoadCallback(const std::function& callback); - -protected: - void setSkipReadDataTask(bool isSkip) { _isSkipReadDataTask = isSkip; }; - void readDataTask(unsigned int selfId); - - void invokingPlayCallbacks(); - - void invokingLoadCallbacks(); - - // pcm data related stuff - ALenum _format; - ALsizei _sampleRate; - float _duration; - uint32_t _totalFrames; - uint32_t _framesRead; - - /*Cache related stuff; - * Cache pcm data when sizeInBytes less than PCMDATA_CACHEMAXSIZE - */ - ALuint _alBufferId; - - /*Queue buffer related stuff - * Streaming in OpenAL when sizeInBytes greater then PCMDATA_CACHEMAXSIZE - */ - char* _queBuffers[QUEUEBUFFER_NUM]; - ALsizei _queBufferSize[QUEUEBUFFER_NUM]; - uint32_t _queBufferFrames; - - std::mutex _playCallbackMutex; - std::vector> _playCallbacks; - - // loadCallbacks doesn't need mutex since it's invoked only in Cocos thread. - std::vector> _loadCallbacks; - - std::mutex _readDataTaskMutex; - - State _state; - - std::shared_ptr _isDestroyed; - std::string _fileFullPath; - unsigned int _id; - bool _isLoadingFinished; - bool _isSkipReadDataTask; - - friend class AudioEngineImpl; - friend class AudioPlayer; -}; - -NS_CC_END diff --git a/core/audio/include/AudioDecoder.h b/core/audio/include/AudioDecoder.h deleted file mode 100644 index 780ddc2933..0000000000 --- a/core/audio/include/AudioDecoder.h +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include -#include -#include "platform/CCFileStream.h" - -namespace cocos2d -{ -enum class AUDIO_SOURCE_FORMAT : uint16_t -{ - PCM_UNK, // Unknown - PCM_U8, - PCM_16, - PCM_24, - PCM_32, - PCM_64, - PCM_FLT32, - PCM_FLT64, - MULAW, - ALAW, - ADPCM, // Microsoft ADPCM - IMA_ADPCM, // IMA ADPCM -}; - -/** - * @brief The class for decoding compressed audio file to PCM buffer. - */ -class AudioDecoder -{ -public: - static const uint32_t INVALID_FRAME_INDEX = UINT32_MAX; - - /** - * @brief Opens an audio file specified by a file path. - * @return true if succeed, otherwise false. - */ - virtual bool open(std::string_view path) = 0; - - /** - * @brief Checks whether decoder has opened file successfully. - * @return true if succeed, otherwise false. - */ - virtual bool isOpened() const; - - /** - * @brief Closes opened audio file. - * @note The method will also be automatically invoked in the destructor. - */ - virtual void close() = 0; - - /** - * @brief Reads audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than 'framesToRead'. Returns 0 means reach the end - * of file. - */ - virtual uint32_t read(uint32_t framesToRead, char* pcmBuf) = 0; - - /** - * @brief Reads fixed audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than |framesToRead|. Returns 0 means reach the end - * of file. - * @note The different between |read| and |readFixedFrames| is |readFixedFrames| will do multiple reading operations - * if |framesToRead| frames isn't filled entirely, while |read| just does reading operation once whatever - * |framesToRead| is or isn't filled entirely. If current position reaches the end of frames, the return value may - * smaller than |framesToRead| and the remaining buffer in |pcmBuf| will be set with silence data (0x00). - */ - virtual uint32_t readFixedFrames(uint32_t framesToRead, char* pcmBuf); - - /** - * @brief Sets frame offest to be read. - * @param frameOffset The frame offest to be set. - * @return true if succeed, otherwise false - */ - virtual bool seek(uint32_t frameOffset) = 0; - - /** Gets total frames of current audio.*/ - virtual uint32_t getTotalFrames() const; - - /** - * @brief The helper function for convert frames to bytes - */ - virtual uint32_t framesToBytes(uint32_t frames) const; - - /** - * @brief The helper function for convert bytes to frames - */ - virtual uint32_t bytesToFrames(uint32_t bytes) const; - - /** Gets sample rate of current audio.*/ - virtual uint32_t getSampleRate() const; - - /** Gets the channel count of current audio. - * @note Currently we only support 1 or 2 channels. - */ - virtual uint32_t getChannelCount() const; - - /* - * @brief Gets samples per block, usually is 1 for .mp3 or .ogg, .wav may > 1 - */ - uint32_t getSamplesPerBlock() const; - - virtual AUDIO_SOURCE_FORMAT getSourceFormat() const; - -protected: - AudioDecoder(); - virtual ~AudioDecoder(); - - bool _isOpened; - uint32_t _totalFrames; - uint32_t _bytesPerBlock; // Same as bytesPerFrame when _samplesPerBlock is 1 - uint32_t _samplesPerBlock; - uint32_t _sampleRate; - uint32_t _channelCount; - AUDIO_SOURCE_FORMAT _sourceFormat; - - friend class AudioDecoderManager; -}; - -} // namespace cocos2d diff --git a/core/audio/include/AudioDecoderEXT.h b/core/audio/include/AudioDecoderEXT.h deleted file mode 100644 index f6eea0dbd2..0000000000 --- a/core/audio/include/AudioDecoderEXT.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018 HALX99. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include -#import -#include "audio/include/AudioDecoder.h" -#include "platform/CCFileStream.h" - -namespace cocos2d -{ - -/** - * @brief The class for decoding compressed audio file to PCM buffer. - */ -class AudioDecoderEXT : public AudioDecoder -{ -public: - static const uint32_t INVALID_FRAME_INDEX = UINT32_MAX; - - AudioDecoderEXT(); - ~AudioDecoderEXT(); - - /** - * @brief Opens an audio file specified by a file path. - * @return true if succeed, otherwise false. - */ - bool open(std::string_view path) override; - - /** - * @brief Closes opened audio file. - * @note The method will also be automatically invoked in the destructor. - */ - void close() override; - - /** - * @brief Reads audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than 'framesToRead'. Returns 0 means reach the end - * of file. - */ - uint32_t read(uint32_t framesToRead, char* pcmBuf) override; - - /** - * @brief Reads fixed audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than |framesToRead|. Returns 0 means reach the end - * of file. - * @note The different between |read| and |readFixedFrames| is |readFixedFrames| will do multiple reading operations - * if |framesToRead| frames isn't filled entirely, while |read| just does reading operation once whatever - * |framesToRead| is or isn't filled entirely. If current position reaches the end of frames, the return value may - * smaller than |framesToRead| and the remaining buffer in |pcmBuf| will be set with silence data (0x00). - */ - // uint32_t readFixedFrames(uint32_t framesToRead, char* pcmBuf) override; - - /** - * @brief Sets frame offest to be read. - * @param frameOffset The frame offest to be set. - * @return true if succeed, otherwise false - */ - bool seek(uint32_t frameOffset) override; - -private: - void closeInternal(); - - static OSStatus readCallback(void* inClientData, - SInt64 inPosition, - UInt32 requestCount, - void* buffer, - UInt32* actualCount); - static SInt64 getSizeCallback(void* inClientData); - - ExtAudioFileRef _extRef; - std::unique_ptr _fileStream; - SInt64 _streamSize; - AudioFileID _audioFileId; - - AudioStreamBasicDescription _outputFormat; -}; - -} // namespace cocos2d diff --git a/core/audio/include/AudioDecoderManager.h b/core/audio/include/AudioDecoderManager.h deleted file mode 100644 index 3075bf10d9..0000000000 --- a/core/audio/include/AudioDecoderManager.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -Copyright (c) 2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#pragma once -#include - -namespace cocos2d -{ - -class AudioDecoder; - -class AudioDecoderManager -{ -public: - static bool init(); - static void destroy(); - static AudioDecoder* createDecoder(std::string_view path); - static void destroyDecoder(AudioDecoder* decoder); -}; - -} // namespace cocos2d diff --git a/core/audio/include/AudioDecoderMp3.h b/core/audio/include/AudioDecoderMp3.h deleted file mode 100644 index 9731157397..0000000000 --- a/core/audio/include/AudioDecoderMp3.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "audio/include/AudioDecoder.h" -#include - -#if !defined(CC_USE_MPG123) -# define CC_USE_MPG123 0 -#endif - -#if !CC_USE_MPG123 -typedef struct mp3dec_impl* mp3dec_handle_t; -#else -typedef struct mpg123_handle_struct* mp3dec_handle_t; -#endif - -namespace cocos2d -{ - -/** - * @brief The class for decoding compressed audio file to PCM buffer. - */ -class AudioDecoderMp3 : public AudioDecoder -{ -public: - /** - * @brief Opens an audio file specified by a file path. - * @return true if succeed, otherwise false. - */ - bool open(std::string_view path) override; - - /** - * @brief Closes opened audio file. - * @note The method will also be automatically invoked in the destructor. - */ - void close() override; - - /** - * @brief Reads audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than 'framesToRead'. Returns 0 means reach the end - * of file. - */ - uint32_t read(uint32_t framesToRead, char* pcmBuf) override; - - /** - * @brief Sets frame offest to be read. - * @param frameOffset The frame offest to be set. - * @return true if succeed, otherwise false - */ - bool seek(uint32_t frameOffset) override; - -protected: - AudioDecoderMp3(); - ~AudioDecoderMp3(); - - static bool lazyInit(); - static void destroy(); - - std::unique_ptr _fileStream{}; - mp3dec_handle_t _handle; - - friend class AudioDecoderManager; -}; - -} // namespace cocos2d diff --git a/core/audio/include/AudioDecoderOgg.h b/core/audio/include/AudioDecoderOgg.h deleted file mode 100644 index 18d86ebced..0000000000 --- a/core/audio/include/AudioDecoderOgg.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "audio/include/AudioDecoder.h" - -#include "vorbis/vorbisfile.h" -#include - -namespace cocos2d -{ - -/** - * @brief The class for decoding compressed audio file to PCM buffer. - */ -class AudioDecoderOgg : public AudioDecoder -{ -public: - /** - * @brief Opens an audio file specified by a file path. - * @return true if succeed, otherwise false. - */ - bool open(std::string_view path) override; - - /** - * @brief Closes opened audio file. - * @note The method will also be automatically invoked in the destructor. - */ - void close() override; - - /** - * @brief Reads audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than 'framesToRead'. Returns 0 means reach the end - * of file. - */ - uint32_t read(uint32_t framesToRead, char* pcmBuf) override; - - /** - * @brief Sets frame offest to be read. - * @param frameOffset The frame offest to be set. - * @return true if succeed, otherwise false - */ - bool seek(uint32_t frameOffset) override; - -protected: - AudioDecoderOgg(); - ~AudioDecoderOgg(); - - OggVorbis_File _vf; - - friend class AudioDecoderManager; -}; - -} // namespace cocos2d diff --git a/core/audio/include/AudioDecoderWav.h b/core/audio/include/AudioDecoderWav.h deleted file mode 100644 index 8e9e101dd2..0000000000 --- a/core/audio/include/AudioDecoderWav.h +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018-2019 HALX99. - Copyright (c) 2020 c4games.com. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "audio/include/AudioDecoder.h" -#include - -#if !defined(MAKE_FOURCC) -# define MAKE_FOURCC(a, b, c, d) ((uint32_t)((a) | ((b) << 8) | ((c) << 16) | (((uint32_t)(d)) << 24))) -#endif - -#if !defined(_WIN32) -typedef struct _GUID -{ - uint32_t Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -} GUID; -__inline int IsEqualGUID(const GUID& rguid1, const GUID& rguid2) -{ - return !::memcmp(&rguid1, &rguid2, sizeof(GUID)); -} -#endif - -namespace cocos2d -{ - -// http://soundfile.sapp.org/doc/WaveFormat/ -enum class WAV_FORMAT : uint16_t -{ - UNKNOWN = 0x0, // Unknown Wave Format - PCM = 0x1, // PCM Format - ADPCM = 0x2, // Microsoft ADPCM Format - IEEE = 0x3, // IEEE float/double - ALAW = 0x6, // 8-bit ITU-T G.711 A-law - MULAW = 0x7, // 8-bit ITU-T G.711 MUL-law - IMA_ADPCM = 0x11, // IMA ADPCM Format - EXT = 0xFFFE // Set via subformat -}; - -#pragma pack(push, 1) -struct WAV_CHUNK_HEADER -{ - uint32_t ChunkID; - /* - ** The ChunkSize gives the size of the valid data in the chunk. It does not include the padding, the size of - *chunkID, or the size of chunkSize. - ** see: https://docs.microsoft.com/en-us/windows/win32/xaudio2/resource-interchange-file-format--riff- - */ - uint32_t ChunkSize; -}; -struct WAV_RIFF_CHUNK -{ - WAV_CHUNK_HEADER Header; - uint32_t Format; -}; -struct WAV_FMT_CHUNK -{ - WAV_CHUNK_HEADER Header; - WAV_FORMAT AudioFormat; - uint16_t NumChannels; - uint32_t SampleRate; - uint32_t ByteRate; - uint16_t BlockAlign; - uint16_t BitsPerSample; - struct - { - /* The follow fields is optional */ - uint16_t cbSize; - union - { - uint16_t ValidBitsPerSample; - uint16_t SamplesPerBlock; - uint16_t Reserved; - } Samples; - uint32_t ChannelMask; - GUID SubFormat; - } ExtParams; -}; -struct WAV_FILE_HEADER -{ - WAV_RIFF_CHUNK Riff; - WAV_FMT_CHUNK Fmt; - WAV_CHUNK_HEADER PcmData; -}; -#pragma pack(pop) - -struct WAV_FILE -{ - WAV_FILE_HEADER FileHeader; - AUDIO_SOURCE_FORMAT SourceFormat; - uint32_t PcmDataOffset; - std::unique_ptr Stream{}; -}; - -/** - * @brief The class for decoding compressed audio file to PCM buffer. - */ -class AudioDecoderWav : public AudioDecoder -{ -public: - /** - * @brief Opens an audio file specified by a file path. - * @return true if succeed, otherwise false. - */ - bool open(std::string_view path) override; - - /** - * @brief The helper function for convert frames to bytes - */ - uint32_t framesToBytes(uint32_t frames) const override; - - /** - * @brief The helper function for convert bytes to frames - */ - uint32_t bytesToFrames(uint32_t bytes) const override; - - /** - * @brief Closes opened audio file. - * @note The method will also be automatically invoked in the destructor. - */ - void close() override; - - /** - * @brief Reads audio frames of PCM format. - * @param framesToRead The number of frames excepted to be read. - * @param pcmBuf The buffer to hold the frames to be read, its size should be >= |framesToRead| / samplesPerBlock * - * _bytesPerBlock. - * @return The number of frames actually read, it's probably less than 'framesToRead'. Returns 0 means reach the end - * of file. - */ - uint32_t read(uint32_t framesToRead, char* pcmBuf) override; - - /** - * @brief Sets frame offest to be read. - * @param frameOffset The frame offest to be set. - * @return true if succeed, otherwise false - */ - bool seek(uint32_t frameOffset) override; - -protected: - friend class AudioDecoderManager; - AudioDecoderWav(); - ~AudioDecoderWav(); - - mutable WAV_FILE _wavf; -}; - -} // namespace cocos2d diff --git a/core/audio/include/AudioEngine.h b/core/audio/include/AudioEngine.h deleted file mode 100644 index 2d864b78ee..0000000000 --- a/core/audio/include/AudioEngine.h +++ /dev/null @@ -1,371 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "platform/CCPlatformConfig.h" -#include "platform/CCPlatformMacros.h" -#include "audio/include/AudioMacros.h" -#include -#include -#include -#include - -#ifdef ERROR -# undef ERROR -#endif // ERROR - -/** - * @addtogroup audio - * @{ - */ - -NS_CC_BEGIN - -/** - * @class AudioProfile - * - * @brief - * @js NA - */ -class CC_DLL AudioProfile -{ -public: - // Profile name can't be empty. - std::string name; - // The maximum number of simultaneous audio instance. - unsigned int maxInstances; - - /* Minimum delay in between sounds */ - double minDelay; - - /** - * Default constructor - * - * @lua new - */ - AudioProfile() : maxInstances(0), minDelay(0.0) {} -}; - -class AudioEngineImpl; - -/** - * @class AudioEngine - * - * @brief Offers a interface to play audio. - * - * @note Make sure to call AudioEngine::end() when the audio engine is not needed anymore to release resources. - * @js NA - */ - -class CC_DLL AudioEngine -{ -public: - /** AudioState enum,all possible states of an audio instance.*/ - enum class AudioState - { - ERROR = -1, - INITIALIZING, - PLAYING, - PAUSED - }; - - static const int INVALID_AUDIO_ID; - - static const float TIME_UNKNOWN; - - static bool lazyInit(); - - /** - * Release objects relating to AudioEngine. - * - * @warning It must be called before the application exit. - * @lua endToLua - */ - static void end(); - - /** - * Gets the default profile of audio instances. - * - * @return The default profile of audio instances. - */ - static AudioProfile* getDefaultProfile(); - - /** - * Play 2d sound. - * - * @param filePath The path of an audio file. - * @param loop Whether audio instance loop or not. - * @param volume Volume value (range from 0.0 to 1.0). - * @param profile A profile for audio instance. When profile is not specified, default profile will be used. - * @return An audio ID. It allows you to dynamically change the behavior of an audio instance on the fly. - * - * @see `AudioProfile` - */ - static AUDIO_ID play2d(std::string_view filePath, - bool loop = false, - float volume = 1.0f, - const AudioProfile* profile = nullptr); - - /** - * Sets whether an audio instance loop or not. - * - * @param audioID An audioID returned by the play2d function. - * @param loop Whether audio instance loop or not. - */ - static void setLoop(AUDIO_ID audioID, bool loop); - - /** - * Checks whether an audio instance is loop. - * - * @param audioID An audioID returned by the play2d function. - * @return Whether or not an audio instance is loop. - */ - static bool isLoop(AUDIO_ID audioID); - - /** - * Sets volume for an audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @param volume Volume value (range from 0.0 to 1.0). - */ - static void setVolume(AUDIO_ID audioID, float volume); - - /** - * Gets the volume value of an audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @return Volume value (range from 0.0 to 1.0). - */ - static float getVolume(AUDIO_ID audioID); - - /** - * Pause an audio instance. - * - * @param audioID An audioID returned by the play2d function. - */ - static void pause(AUDIO_ID audioID); - - /** Pause all playing audio instances. */ - static void pauseAll(); - - /** - * Resume an audio instance. - * - * @param audioID An audioID returned by the play2d function. - */ - static void resume(AUDIO_ID audioID); - - /** Resume all suspended audio instances. */ - static void resumeAll(); - - /** - * Stop an audio instance. - * - * @param audioID An audioID returned by the play2d function. - */ - static void stop(AUDIO_ID audioID); - - /** Stop all audio instances. */ - static void stopAll(); - - /** - * Sets the current playback position of an audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @param sec The offset in seconds from the start to seek to. - * @return - */ - static bool setCurrentTime(AUDIO_ID audioID, float sec); - - /** - * Gets the current playback position of an audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @return The current playback position of an audio instance. - */ - static float getCurrentTime(AUDIO_ID audioID); - - /** - * Gets the duration of an audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @return The duration of an audio instance. - */ - static float getDuration(AUDIO_ID audioID); - - /** - * Returns the state of an audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @return The status of an audio instance. - */ - static AudioState getState(AUDIO_ID audioID); - - /** - * Register a callback to be invoked when an audio instance has completed playing. - * - * @param audioID An audioID returned by the play2d function. - * @param callback - */ - static void setFinishCallback(AUDIO_ID audioID, const std::function& callback); - - /** - * Gets the maximum number of simultaneous audio instance of AudioEngine. - */ - static int getMaxAudioInstance() { return _maxInstances; } - - /** - * Sets the maximum number of simultaneous audio instance for AudioEngine. - * - * @param maxInstances The maximum number of simultaneous audio instance. - */ - static bool setMaxAudioInstance(int maxInstances); - - /** - * Uncache the audio data from internal buffer. - * AudioEngine cache audio data on ios,mac, and win32 platform. - * - * @warning This can lead to stop related audio first. - * @param filePath Audio file path. - */ - static void uncache(std::string_view filePath); - - /** - * Uncache all audio data from internal buffer. - * - * @warning All audio will be stopped first. - */ - static void uncacheAll(); - - /** - * Gets the audio profile by id of audio instance. - * - * @param audioID An audioID returned by the play2d function. - * @return The audio profile. - */ - static AudioProfile* getProfile(AUDIO_ID audioID); - - /** - * Gets an audio profile by name. - * - * @param profileName A name of audio profile. - * @return The audio profile. - */ - static AudioProfile* getProfile(std::string_view profileName); - - /** - * Preload audio file. - * @param filePath The file path of an audio. - */ - static void preload(std::string_view filePath) { preload(filePath, nullptr); } - - /** - * Preload audio file. - * @param filePath The file path of an audio. - * @param callback A callback which will be called after loading is finished. - */ - static void preload(std::string_view filePath, std::function callback); - - /** - * Gets playing audio count. - */ - static int getPlayingAudioCount(); - - /** - * Whether to enable playing audios - * @note If it's disabled, current playing audios will be stopped and the later 'preload', 'play2d' methods will - * take no effects. - */ - static void setEnabled(bool isEnabled); - /** - * Check whether AudioEngine is enabled. - */ - static bool isEnabled(); - -protected: - static void addTask(const std::function& task); - static void remove(AUDIO_ID audioID); - - struct ProfileHelper - { - AudioProfile profile; - - std::list audioIDs; - - double lastPlayTime; - - ProfileHelper() : lastPlayTime(0.0) {} - }; - - struct AudioInfo - { - std::string filePath; - ProfileHelper* profileHelper; - - float volume; - bool loop; - float duration; - AudioState state; - - AudioInfo(); - ~AudioInfo(); - - private: - AudioInfo(const AudioInfo& info); - AudioInfo(AudioInfo&& info); - AudioInfo& operator=(const AudioInfo& info); - AudioInfo& operator=(AudioInfo&& info); - }; - - // audioID,audioAttribute - static std::unordered_map _audioIDInfoMap; - - // audio file path,audio IDs - static hlookup::string_map> _audioPathIDMap; - - // profileName,ProfileHelper - static hlookup::string_map _audioPathProfileHelperMap; - - static unsigned int _maxInstances; - - static ProfileHelper* _defaultProfileHelper; - - static AudioEngineImpl* _audioEngineImpl; - - class AudioEngineThreadPool; - static AudioEngineThreadPool* s_threadPool; - - static bool _isEnabled; - - friend class AudioEngineImpl; -}; - -NS_CC_END - -// end group -/// @} diff --git a/core/audio/include/AudioEngineImpl.h b/core/audio/include/AudioEngineImpl.h deleted file mode 100644 index eb1c4c9610..0000000000 --- a/core/audio/include/AudioEngineImpl.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018-2020 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ -#pragma once -#ifndef __AUDIO_ENGINE_IMPL_H_ -# define __AUDIO_ENGINE_IMPL_H_ - -# include "platform/CCPlatformConfig.h" - -# include -# include - -# include "base/CCRef.h" -# include "audio/include/AudioMacros.h" -# include "audio/include/AudioCache.h" -# include "audio/include/AudioPlayer.h" - -NS_CC_BEGIN - -class Scheduler; - -class CC_DLL AudioEngineImpl : public cocos2d::Ref -{ -public: - AudioEngineImpl(); - ~AudioEngineImpl(); - - bool init(); - AUDIO_ID play2d(std::string_view fileFullPath, bool loop, float volume); - void setVolume(AUDIO_ID audioID, float volume); - void setLoop(AUDIO_ID audioID, bool loop); - bool pause(AUDIO_ID audioID); - bool resume(AUDIO_ID audioID); - void stop(AUDIO_ID audioID); - void stopAll(); - float getDuration(AUDIO_ID audioID); - float getCurrentTime(AUDIO_ID audioID); - bool setCurrentTime(AUDIO_ID audioID, float time); - void setFinishCallback(AUDIO_ID audioID, const std::function& callback); - - void uncache(std::string_view filePath); - void uncacheAll(); - AudioCache* preload(std::string_view filePath, std::function callback); - void update(float dt); - -private: - // query players state per frame and dispatch finish callback if possible - void _updatePlayers(bool forStop); - void _play2d(AudioCache* cache, AUDIO_ID audioID); - void _unscheduleUpdate(); - ALuint findValidSource(); -# if defined(__APPLE__) - static ALvoid myAlSourceNotificationCallback(ALuint sid, ALuint notificationID, ALvoid* userData); -# endif - ALuint _alSources[MAX_AUDIOINSTANCES]; - - // available sources - std::queue _unusedSourcesPool; - - // filePath,bufferInfo - hlookup::string_map> _audioCaches; - - // audioID,AudioInfo - std::unordered_map _audioPlayers; - std::recursive_mutex _threadMutex; - - // finish callbacks - std::vector> _finishCallbacks; - - bool _scheduled; - - AUDIO_ID _currentAudioID; - Scheduler* _scheduler; -}; - -NS_CC_END -#endif // __AUDIO_ENGINE_INL_H_ diff --git a/core/audio/include/AudioMacros.h b/core/audio/include/AudioMacros.h deleted file mode 100644 index 1701a98ec7..0000000000 --- a/core/audio/include/AudioMacros.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016-2017 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "platform/CCPlatformConfig.h" - -#include - -#define QUEUEBUFFER_NUM (3) -#define QUEUEBUFFER_TIME_STEP (0.05f) - -#define QUOTEME_(x) #x -#define QUOTEME(x) QUOTEME_(x) - -// log, CCLOG aren't threadsafe, since we uses sub threads for parsing pcm data, threadsafe log output -// is needed. Define the following macros (ALOGV, ALOGD, ALOGI, ALOGW, ALOGE) for threadsafe log output. -#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 -# include "base/ccUTF8.h" // for StringUtils::format -# define AUDIO_LOG(fmt, ...) OutputDebugStringA(StringUtils::format((fmt "\r\n"), ##__VA_ARGS__).c_str()) -#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID -# include -# define AUDIO_LOG(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "AudioEngine", fmt, ##__VA_ARGS__) -#else // other platforms -# define AUDIO_LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__) -#endif - -#if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG > 0 -# define ALOGV(fmt, ...) AUDIO_LOG("V/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__) -#else -# define ALOGV(fmt, ...) \ - do \ - { \ - } while (false) -#endif -#define ALOGD(fmt, ...) AUDIO_LOG("D/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__) -#define ALOGI(fmt, ...) AUDIO_LOG("I/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__) -#define ALOGW(fmt, ...) AUDIO_LOG("W/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__) -#define ALOGE(fmt, ...) AUDIO_LOG("E/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__) - -#if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG > 0 -# define CHECK_AL_ERROR_DEBUG() \ - do \ - { \ - ALenum __error = alGetError(); \ - if (__error) \ - { \ - ALOGE("OpenAL error 0x%04X in %s %s %d\n", __error, __FILE__, __FUNCTION__, __LINE__); \ - } \ - } while (false) -#else -# define CHECK_AL_ERROR_DEBUG() -#endif - -#define BREAK_IF(condition) \ - if (!!(condition)) \ - { \ - break; \ - } - -#define BREAK_IF_ERR_LOG(condition, fmt, ...) \ - if (!!(condition)) \ - { \ - ALOGE("(" QUOTEME(condition) ") failed, message: " fmt, ##__VA_ARGS__); \ - break; \ - } - -#define AUDIO_ID int -#define AUDIO_ID_PRID "%d" diff --git a/core/audio/include/AudioPlayer.h b/core/audio/include/AudioPlayer.h deleted file mode 100644 index 81512b98d9..0000000000 --- a/core/audio/include/AudioPlayer.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "platform/CCPlatformConfig.h" - -#include -#include -#include -#include - -#include "audio/include/AudioMacros.h" -#include "platform/CCPlatformMacros.h" -#include "audio/include/alconfig.h" - -NS_CC_BEGIN - -class AudioCache; -class AudioEngineImpl; - -class CC_DLL AudioPlayer -{ - friend class AudioEngineImpl; - -public: - AudioPlayer(); - ~AudioPlayer(); - - void destroy(); - - // queue buffer related stuff - bool setTime(float time); - float getTime() { return _currTime; } - bool setLoop(bool loop); - - bool isFinished() const; - -protected: - void setCache(AudioCache* cache); - void rotateBufferThread(int offsetFrame); - bool play2d(); -#if defined(__APPLE__) - void wakeupRotateThread(); -#endif - - AudioCache* _audioCache; - - float _volume; - bool _loop; - std::function _finishCallbak; - - bool _isDestroyed; - bool _removeByAudioEngine; - bool _ready; - ALuint _alSource; - - // play by circular buffer - float _currTime; - bool _streamingSource; - ALuint _bufferIds[QUEUEBUFFER_NUM]; - std::thread* _rotateBufferThread; - std::condition_variable _sleepCondition; - std::mutex _sleepMutex; - bool _timeDirty; - bool _isRotateThreadExited; -#if defined(__APPLE__) - std::atomic_bool _needWakeupRotateThread; -#endif - - std::mutex _play2dMutex; - - unsigned int _id; - friend class AudioEngineImpl; -}; - -NS_CC_END diff --git a/core/audio/include/alconfig.h b/core/audio/include/alconfig.h deleted file mode 100644 index e2c9535c97..0000000000 --- a/core/audio/include/alconfig.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2020 c4games.com. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ -#pragma once - -#if !defined(CC_USE_MOJOAL) -# define CC_USE_MOJOAL 0 -#endif - -#if !defined(__APPLE__) -# if !defined(CC_USE_ALSOFT) && !CC_USE_MOJOAL -# define CC_USE_ALSOFT 1 -# endif -#endif - -// if CC_USE_MOJOAL, force disable openal-soft -#if CC_USE_MOJOAL -# define CC_USE_ALSOFT 0 -#endif - -#if !CC_USE_ALSOFT && !CC_USE_MOJOAL -# import -# import -# define MAX_AUDIOINSTANCES 24 -#else -# define AL_ALEXT_PROTOTYPES 1 -# include "AL/al.h" -# include "AL/alc.h" -# if !CC_USE_MOJOAL -# include "AL/alext.h" -# endif -# define MAX_AUDIOINSTANCES 32 -#endif diff --git a/core/audio/src/AudioCache.cpp b/core/audio/src/AudioCache.cpp deleted file mode 100644 index c2e9a597e7..0000000000 --- a/core/audio/src/AudioCache.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/**************************************************************************** - 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. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#define LOG_TAG "AudioCache" - -#include "platform/CCPlatformConfig.h" - -#include "audio/include/AudioCache.h" -#include -#include "base/CCDirector.h" -#include "base/CCScheduler.h" - -#include "audio/include/AudioDecoderManager.h" -#include "audio/include/AudioDecoder.h" - -#define VERY_VERY_VERBOSE_LOGGING -#ifdef VERY_VERY_VERBOSE_LOGGING -# define ALOGVV ALOGV -#else -# define ALOGVV(...) \ - do \ - { \ - } while (false) -#endif - -namespace -{ -unsigned int __idIndex = 0; -} - -#define INVALID_AL_BUFFER_ID 0xFFFFFFFF -#define PCMDATA_CACHEMAXSIZE 1048576 - -using namespace cocos2d; - -AudioCache::AudioCache() - : _totalFrames(0) - , _framesRead(0) - , _format(-1) - , _duration(0.0f) - , _alBufferId(INVALID_AL_BUFFER_ID) - , _queBufferFrames(0) - , _state(State::INITIAL) - , _isDestroyed(std::make_shared(false)) - , _id(++__idIndex) - , _isLoadingFinished(false) - , _isSkipReadDataTask(false) -{ - ALOGVV("AudioCache() %p, id=%u", this, _id); - for (int i = 0; i < QUEUEBUFFER_NUM; ++i) - { - _queBuffers[i] = nullptr; - _queBufferSize[i] = 0; - } -} - -AudioCache::~AudioCache() -{ - ALOGVV("~AudioCache() %p, id=%u, begin", this, _id); - *_isDestroyed = true; - while (!_isLoadingFinished) - { - if (_isSkipReadDataTask) - { - ALOGV("id=%u, Skip read data task, don't continue to wait!", _id); - break; - } - ALOGVV("id=%u, waiting readData thread to finish ...", _id); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - } - // wait for the 'readDataTask' task to exit - _readDataTaskMutex.lock(); - - if (_state == State::READY) - { - 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; - } - } - else - { - ALOGW("AudioCache (%p), id=%u, buffer isn't ready, state=%d", this, _id, (int)_state); - } - - if (_queBufferFrames > 0) - { - for (int index = 0; index < QUEUEBUFFER_NUM; ++index) - { - free(_queBuffers[index]); - } - } - ALOGVV("~AudioCache() %p, id=%u, end", this, _id); - _readDataTaskMutex.unlock(); -} - -void AudioCache::readDataTask(unsigned int selfId) -{ - // Note: It's in sub thread - ALOGVV("readDataTask begin, cache id=%u", selfId); - - _readDataTaskMutex.lock(); - _state = State::LOADING; - - AudioDecoder* decoder = AudioDecoderManager::createDecoder(_fileFullPath); - do - { - if (decoder == nullptr || !decoder->open(_fileFullPath)) - break; - - const uint32_t originalTotalFrames = decoder->getTotalFrames(); - const uint32_t sampleRate = decoder->getSampleRate(); - const uint32_t channelCount = decoder->getChannelCount(); - const auto sourceFormat = decoder->getSourceFormat(); - - uint32_t totalFrames = originalTotalFrames; - uint32_t dataSize = decoder->framesToBytes(totalFrames); - uint32_t remainingFrames = totalFrames; - - switch (sourceFormat) - { - case AUDIO_SOURCE_FORMAT::PCM_16: - _format = channelCount > 1 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; // bits depth: 16bits - break; - case AUDIO_SOURCE_FORMAT::PCM_U8: - _format = channelCount > 1 ? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8; // bits depth: 8bits - break; -#if CC_USE_ALSOFT - case AUDIO_SOURCE_FORMAT::PCM_FLT32: - _format = channelCount > 1 ? AL_FORMAT_STEREO_FLOAT32 : AL_FORMAT_MONO_FLOAT32; - break; - case AUDIO_SOURCE_FORMAT::PCM_FLT64: - _format = channelCount > 1 ? AL_FORMAT_STEREO_DOUBLE_EXT : AL_FORMAT_MONO_DOUBLE_EXT; - break; - case AUDIO_SOURCE_FORMAT::MULAW: - _format = channelCount > 1 ? AL_FORMAT_STEREO_MULAW : AL_FORMAT_MONO_MULAW; - break; - case AUDIO_SOURCE_FORMAT::ALAW: - _format = channelCount > 1 ? AL_FORMAT_STEREO_ALAW_EXT : AL_FORMAT_MONO_ALAW_EXT; - break; - case AUDIO_SOURCE_FORMAT::ADPCM: - _format = channelCount > 1 ? AL_FORMAT_STEREO_MSADPCM_SOFT : AL_FORMAT_MONO_MSADPCM_SOFT; - break; - case AUDIO_SOURCE_FORMAT::IMA_ADPCM: - _format = channelCount > 1 ? AL_FORMAT_STEREO_IMA4 : AL_FORMAT_MONO_IMA4; - break; -#endif - default: - assert(false); - } - - _sampleRate = (ALsizei)sampleRate; - _duration = 1.0f * totalFrames / sampleRate; - _totalFrames = totalFrames; - - if (dataSize <= PCMDATA_CACHEMAXSIZE) - { - uint32_t framesRead = 0; - const uint32_t framesToReadOnce = - std::min(totalFrames, static_cast(sampleRate * QUEUEBUFFER_TIME_STEP * QUEUEBUFFER_NUM)); - - alGenBuffers(1, &_alBufferId); - auto alError = alGetError(); - if (alError != AL_NO_ERROR) - { - ALOGE("%s: attaching audio to buffer fail: %x", __FUNCTION__, alError); - break; - } - - std::vector pcmBuffer(dataSize, 0); - auto pcmData = pcmBuffer.data(); - - if (*_isDestroyed) - break; - - framesRead = decoder->readFixedFrames((std::min)(framesToReadOnce, remainingFrames), - pcmData + decoder->framesToBytes(_framesRead)); - _framesRead += framesRead; - remainingFrames -= framesRead; - - if (*_isDestroyed) - break; - - uint32_t frames = 0; - while (!*_isDestroyed && _framesRead < originalTotalFrames) - { - frames = (std::min)(framesToReadOnce, remainingFrames); - if (_framesRead + frames > originalTotalFrames) - { - frames = originalTotalFrames - _framesRead; - } - framesRead = decoder->read(frames, pcmData + decoder->framesToBytes(_framesRead)); - if (framesRead == 0) - break; - _framesRead += framesRead; - remainingFrames -= framesRead; - } - - if (*_isDestroyed) - break; - - if (_framesRead < originalTotalFrames) - { - memset(pcmData + decoder->framesToBytes(_framesRead), 0x00, - decoder->framesToBytes(totalFrames - _framesRead)); - } - -#if CC_USE_ALSOFT - 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); -#else -# if !CC_USE_ALSOFT - /// Apple OpenAL framework, try adjust frames - /// May don't need, xcode11 sdk works well - uint32_t adjustFrames = 0; - BREAK_IF_ERR_LOG(!decoder->seek(totalFrames), "AudioDecoder::seek(%u) error", totalFrames); - - char* tmpBuf = (char*)malloc(decoder->framesToBytes(framesToReadOnce)); - std::vector adjustFrameBuf; - adjustFrameBuf.reserve(decoder->framesToBytes(framesToReadOnce)); - - // Adjust total frames by setting position to the end of frames and try to read more data. - // This is a workaround for https://github.com/cocos2d/cocos2d-x/issues/16938 - do - { - framesRead = decoder->read(framesToReadOnce, tmpBuf); - if (framesRead > 0) - { - adjustFrames += framesRead; - adjustFrameBuf.insert(adjustFrameBuf.end(), tmpBuf, tmpBuf + decoder->framesToBytes(framesRead)); - } - - } while (framesRead > 0); - - if (adjustFrames > 0) - { - ALOGV("Orignal total frames: %u, adjust frames: %u, current total frames: %u", totalFrames, - adjustFrames, totalFrames + adjustFrames); - totalFrames += adjustFrames; - _totalFrames = remainingFrames = totalFrames; - } - - free(tmpBuf); - - // Reset to frame 0 - BREAK_IF_ERR_LOG(!decoder->seek(0), "AudioDecoder::seek(0) failed!"); - - if (adjustFrames > 0) - { - pcmBuffer.insert(pcmBuffer.end(), adjustFrameBuf.data(), adjustFrameBuf.data() + adjustFrameBuf.size()); - pcmData = pcmBuffer.data(); - dataSize = static_cast(pcmBuffer.size()); - } -# endif /* Adjust frames, may not needed */ - ALOGV( - "pcm buffer was loaded successfully, total frames: %u, total read frames: %u, adjust frames: %u, " - "remainingFrames: %u", - totalFrames, _framesRead, adjustFrames, remainingFrames); - _framesRead += adjustFrames; - alBufferData(_alBufferId, _format, pcmData, (ALsizei)dataSize, (ALsizei)sampleRate); -#endif - alError = alGetError(); - if (alError != AL_NO_ERROR) - { - ALOGE("%s:alBufferData error code:%x", __FUNCTION__, alError); - break; - } - - _state = State::READY; - } - else - { - _queBufferFrames = sampleRate * QUEUEBUFFER_TIME_STEP; - BREAK_IF_ERR_LOG(_queBufferFrames == 0, "_queBufferFrames == 0"); - - const uint32_t queBufferBytes = decoder->framesToBytes(_queBufferFrames); - - for (int index = 0; index < QUEUEBUFFER_NUM; ++index) - { - _queBuffers[index] = (char*)malloc(queBufferBytes); - _queBufferSize[index] = queBufferBytes; - - decoder->readFixedFrames(_queBufferFrames, _queBuffers[index]); - } - - _state = State::READY; - } - - } while (false); - - 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; - - // FIXME: Why to invoke play callback first? Should it be after 'load' callback? - invokingPlayCallbacks(); - invokingLoadCallbacks(); - - _readDataTaskMutex.unlock(); - ALOGVV("readDataTask end, cache id=%u", selfId); -} - -void AudioCache::addPlayCallback(const std::function& callback) -{ - std::lock_guard lk(_playCallbackMutex); - switch (_state) - { - case State::INITIAL: - case State::LOADING: - _playCallbacks.push_back(callback); - break; - - case State::READY: - // If state is failure, we still need to invoke the callback - // since the callback will set the 'AudioPlayer::_removeByAudioEngine' flag to true. - case State::FAILED: - callback(); - break; - - default: - ALOGE("Invalid state: %d", (int)_state); - break; - } -} - -void AudioCache::invokingPlayCallbacks() -{ - std::lock_guard lk(_playCallbackMutex); - - for (auto&& cb : _playCallbacks) - { - cb(); - } - - _playCallbacks.clear(); -} - -void AudioCache::addLoadCallback(const std::function& callback) -{ - switch (_state) - { - case State::INITIAL: - case State::LOADING: - _loadCallbacks.push_back(callback); - break; - - case State::READY: - callback(true); - break; - case State::FAILED: - callback(false); - break; - - default: - ALOGE("Invalid state: %d", (int)_state); - break; - } -} - -void AudioCache::invokingLoadCallbacks() -{ - if (*_isDestroyed) - { - ALOGV("AudioCache (%p) was destroyed, don't invoke preload callback ...", this); - return; - } - - auto isDestroyed = _isDestroyed; - auto scheduler = Director::getInstance()->getScheduler(); - scheduler->performFunctionInCocosThread([&, isDestroyed]() { - if (*isDestroyed) - { - ALOGV("invokingLoadCallbacks perform in cocos thread, AudioCache (%p) was destroyed!", this); - return; - } - - for (auto&& cb : _loadCallbacks) - { - cb(_state == State::READY); - } - - _loadCallbacks.clear(); - }); -} diff --git a/core/audio/src/AudioDecoder.cpp b/core/audio/src/AudioDecoder.cpp deleted file mode 100644 index 41bfe000b1..0000000000 --- a/core/audio/src/AudioDecoder.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "audio/include/AudioDecoder.h" -#include "audio/include/AudioMacros.h" -#include "platform/CCFileUtils.h" - -#define LOG_TAG "AudioDecoder" - -namespace cocos2d -{ - -AudioDecoder::AudioDecoder() - : _isOpened(false) - , _totalFrames(0) - , _bytesPerBlock(0) - , _samplesPerBlock(1) - , _sampleRate(0) - , _channelCount(0) - , _sourceFormat(AUDIO_SOURCE_FORMAT::PCM_16) -{} - -AudioDecoder::~AudioDecoder() {} - -bool AudioDecoder::isOpened() const -{ - return _isOpened; -} - -uint32_t AudioDecoder::readFixedFrames(uint32_t framesToRead, char* pcmBuf) -{ - uint32_t framesRead = 0; - uint32_t framesReadOnce = 0; - do - { - framesReadOnce = read(framesToRead - framesRead, pcmBuf + framesToBytes((framesRead))); - framesRead += framesReadOnce; - } while (framesReadOnce != 0 && framesRead < framesToRead); - - if (framesRead < framesToRead) - { - memset(pcmBuf + framesToBytes(framesRead), 0x0, framesToBytes(framesToRead - framesRead)); - } - - return framesRead; -} - -uint32_t AudioDecoder::getTotalFrames() const -{ - return _totalFrames; -} - -uint32_t AudioDecoder::framesToBytes(uint32_t frames) const -{ - return _bytesPerBlock * frames; -} - -uint32_t AudioDecoder::bytesToFrames(uint32_t bytes) const -{ - return bytes / _bytesPerBlock; -} - -uint32_t AudioDecoder::getSampleRate() const -{ - return _sampleRate; -} - -uint32_t AudioDecoder::getChannelCount() const -{ - return _channelCount; -} - -uint32_t AudioDecoder::getSamplesPerBlock() const -{ - return _samplesPerBlock; -} - -AUDIO_SOURCE_FORMAT AudioDecoder::getSourceFormat() const -{ - return _sourceFormat; -} -} // namespace cocos2d diff --git a/core/audio/src/AudioDecoderEXT.mm b/core/audio/src/AudioDecoderEXT.mm deleted file mode 100644 index eb7f9ceaa4..0000000000 --- a/core/audio/src/AudioDecoderEXT.mm +++ /dev/null @@ -1,225 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018 HALX99. - - http://www.cocos2d-x.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "audio/include/AudioDecoderEXT.h" -#include "audio/include/AudioMacros.h" -#include "platform/CCFileUtils.h" - -#import - -#define LOG_TAG "AudioDecoder" - -namespace cocos2d -{ - -AudioDecoderEXT::AudioDecoderEXT() : _extRef(nullptr), _fileStream(nullptr), _streamSize(0), _audioFileId(nullptr) -{ - memset(&_outputFormat, 0, sizeof(_outputFormat)); -} - -AudioDecoderEXT::~AudioDecoderEXT() -{ - closeInternal(); -} - -bool AudioDecoderEXT::open(std::string_view fullPath) -{ - bool ret = false; - CFURLRef fileURL = nil; - do - { - BREAK_IF_ERR_LOG(fullPath.empty(), "Invalid path!"); - - _fileStream = cocos2d::FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ); - BREAK_IF_ERR_LOG(_fileStream == nullptr, "FileUtils::openFileStream FAILED for file: %s", fullPath.data()); - if (_fileStream) - { - _streamSize = _fileStream->size(); // cache the stream size - } - - OSStatus status = AudioFileOpenWithCallbacks(this, &AudioDecoderEXT::readCallback, nullptr, - &AudioDecoderEXT::getSizeCallback, nullptr, 0, &_audioFileId); - BREAK_IF_ERR_LOG(status != noErr, "AudioFileOpenWithCallbacks FAILED, Error = %d", (int)status); - - status = ExtAudioFileWrapAudioFileID(_audioFileId, false, &_extRef); - BREAK_IF_ERR_LOG(status != noErr, "ExtAudioFileWrapAudioFileID FAILED, Error = %d", (int)status); - - BREAK_IF_ERR_LOG(status != noErr, "ExtAudioFileOpenURL FAILED, Error = %d", (int)status); - - AudioStreamBasicDescription fileFormat; - UInt32 propertySize = sizeof(fileFormat); - - // Get the audio data format - status = ExtAudioFileGetProperty(_extRef, kExtAudioFileProperty_FileDataFormat, &propertySize, &fileFormat); - BREAK_IF_ERR_LOG(status != noErr, - "ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %d", - (int)status); - BREAK_IF_ERR_LOG(fileFormat.mChannelsPerFrame > 2, "Unsupported Format, channel count is greater than stereo!"); - - // Set the client format to 16 bit signed integer (native-endian) data - // Maintain the channel count and sample rate of the original source format - _outputFormat.mSampleRate = fileFormat.mSampleRate; - _outputFormat.mChannelsPerFrame = fileFormat.mChannelsPerFrame; - _outputFormat.mFormatID = kAudioFormatLinearPCM; - _outputFormat.mFramesPerPacket = 1; - _outputFormat.mBitsPerChannel = 16; - _outputFormat.mFormatFlags = - kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; - - _sampleRate = _outputFormat.mSampleRate; - _channelCount = _outputFormat.mChannelsPerFrame; - _bytesPerBlock = 2 * _outputFormat.mChannelsPerFrame; - - _outputFormat.mBytesPerPacket = _bytesPerBlock; - _outputFormat.mBytesPerFrame = _bytesPerBlock; - - status = ExtAudioFileSetProperty(_extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(_outputFormat), - &_outputFormat); - BREAK_IF_ERR_LOG(status != noErr, "ExtAudioFileSetProperty FAILED, Error = %d", (int)status); - - // Get the total frame count - SInt64 totalFrames = 0; - propertySize = sizeof(totalFrames); - status = ExtAudioFileGetProperty(_extRef, kExtAudioFileProperty_FileLengthFrames, &propertySize, &totalFrames); - BREAK_IF_ERR_LOG(status != noErr, - "ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %d", - (int)status); - BREAK_IF_ERR_LOG(totalFrames <= 0, "Total frames is 0, it's an invalid audio file: %s", fullPath.data()); - _totalFrames = static_cast(totalFrames); - _isOpened = true; - - ret = true; - } while (false); - - if (fileURL != nil) - CFRelease(fileURL); - - if (!ret) - { - close(); - } - - return ret; -} - -void AudioDecoderEXT::close() -{ - closeInternal(); -} - -uint32_t AudioDecoderEXT::read(uint32_t framesToRead, char* pcmBuf) -{ - uint32_t ret = 0; - do - { - BREAK_IF_ERR_LOG(!isOpened(), "decoder isn't openned"); - BREAK_IF_ERR_LOG(framesToRead == INVALID_FRAME_INDEX, "frameToRead is INVALID_FRAME_INDEX"); - BREAK_IF_ERR_LOG(framesToRead == 0, "frameToRead is 0"); - BREAK_IF_ERR_LOG(pcmBuf == nullptr, "pcmBuf is nullptr"); - - AudioBufferList bufferList; - bufferList.mNumberBuffers = 1; - bufferList.mBuffers[0].mDataByteSize = framesToRead * _bytesPerBlock; - bufferList.mBuffers[0].mNumberChannels = _outputFormat.mChannelsPerFrame; - bufferList.mBuffers[0].mData = pcmBuf; - - UInt32 frames = framesToRead; - OSStatus status = ExtAudioFileRead(_extRef, &frames, &bufferList); - BREAK_IF(status != noErr); - ret = frames; - } while (false); - - return ret; -} - -bool AudioDecoderEXT::seek(uint32_t frameOffset) -{ - bool ret = false; - do - { - BREAK_IF_ERR_LOG(!isOpened(), "decoder isn't openned"); - BREAK_IF_ERR_LOG(frameOffset == INVALID_FRAME_INDEX, "frameIndex is INVALID_FRAME_INDEX"); - - OSStatus status = ExtAudioFileSeek(_extRef, frameOffset); - BREAK_IF(status != noErr); - ret = true; - } while (false); - return ret; -} - -void AudioDecoderEXT::closeInternal() -{ - if (_extRef != nullptr) - { - ExtAudioFileDispose(_extRef); - AudioFileClose(_audioFileId); - _extRef = nullptr; - _audioFileId = nullptr; - _fileStream = nullptr; - } -} - -OSStatus AudioDecoderEXT::readCallback(void* inClientData, - SInt64 inPosition, - UInt32 requestCount, - void* buffer, - UInt32* actualCount) -{ - if (!inClientData) - { - return kAudioFileNotOpenError; - } - - auto* audioDecoder = (AudioDecoderEXT*)inClientData; - auto* fileStream = audioDecoder->_fileStream.get(); - auto currPos = (SInt64)fileStream->tell(); - auto posDiff = inPosition - currPos; - if (posDiff != 0) - { - if (fileStream->seek(posDiff, SEEK_CUR) < 0) - { - return kAudioFilePositionError; - } - } - - const auto count = fileStream->read(buffer, requestCount); - - if (count < 0) - { - return kAudioFileEndOfFileError; - } - - *actualCount = count; - - return noErr; -} - -SInt64 AudioDecoderEXT::getSizeCallback(void* inClientData) -{ - auto* audioDecoder = (AudioDecoderEXT*)inClientData; - return audioDecoder->_streamSize; -} -} // namespace cocos2d { diff --git a/core/audio/src/AudioDecoderManager.cpp b/core/audio/src/AudioDecoderManager.cpp deleted file mode 100644 index 879d893a63..0000000000 --- a/core/audio/src/AudioDecoderManager.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -Copyright (c) 2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2018-2020 HALX99. -Copyright (c) 2021 Bytedance Inc. - -https://adxe.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#define LOG_TAG "AudioDecoderManager" - -#include "audio/include/AudioDecoderManager.h" -#include "audio/include/AudioDecoderOgg.h" -#include "audio/include/AudioMacros.h" -#include "platform/CCFileUtils.h" -#include "base/CCConsole.h" - -#if !defined(__APPLE__) -# include "audio/include/AudioDecoderMp3.h" -# include "audio/include/AudioDecoderWav.h" -#else -# include "audio/include/AudioDecoderEXT.h" -#endif - -#include "yasio/cxx17/string_view.hpp" - -namespace cocos2d -{ - -bool AudioDecoderManager::init() -{ -#if !defined(__APPLE__) - AudioDecoderMp3::lazyInit(); -#endif - return true; -} - -void AudioDecoderManager::destroy() -{ -#if !defined(__APPLE__) - AudioDecoderMp3::destroy(); -#endif -} - -AudioDecoder* AudioDecoderManager::createDecoder(std::string_view path) -{ - cxx17::string_view svPath(path); - if (cxx20::ic::ends_with(svPath, ".ogg")) - { - return new AudioDecoderOgg(); - } -#if !defined(__APPLE__) - else if (cxx20::ic::ends_with(svPath, ".mp3")) - { - return new AudioDecoderMp3(); - } - else if (cxx20::ic::ends_with(svPath, ".wav")) - { - return new AudioDecoderWav(); - } -#else - else - { - return new AudioDecoderEXT(); - } -#endif - - return nullptr; -} - -void AudioDecoderManager::destroyDecoder(AudioDecoder* decoder) -{ - if (decoder) - decoder->close(); - delete decoder; -} - -} // namespace cocos2d diff --git a/core/audio/src/AudioDecoderMp3.cpp b/core/audio/src/AudioDecoderMp3.cpp deleted file mode 100644 index b02cecc2a1..0000000000 --- a/core/audio/src/AudioDecoderMp3.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2020 c4games.com - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#define LOG_TAG "AudioDecoderMp3" -#include "audio/include/AudioDecoderMp3.h" -#include "audio/include/AudioMacros.h" -#include "platform/CCFileUtils.h" - -#include "base/CCConsole.h" - -#if !CC_USE_MPG123 -# define MINIMP3_IMPLEMENTATION -# include "minimp3/minimp3_ex.h" -#else -// because the cocos2d-x engine has ssize_t typedef, so disable mpg123 ssize_t -# define MPG123_DEF_SSIZE_T -# include "mpg123.h" -#endif - -#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID -# include -# include -#endif - -#if !CC_USE_MPG123 -struct mp3dec_impl -{ - mp3dec_ex_t _dec; - mp3dec_io_t _decIO; -}; -#endif - -namespace cocos2d -{ -#if !CC_USE_MPG123 -static size_t minimp3_read_r(void* buf, size_t size, void* user_data) -{ - return ((FileStream*)user_data)->read(buf, size); -} - -static int minimp3_seek_r(uint64_t position, void* user_data) -{ - return ((FileStream*)user_data)->seek(position, SEEK_SET) < 0 ? -1 : 0; -} -#else -static bool __mp3Inited = false; - -static ssize_t mpg123_read_r(void* handle, void* buffer, size_t count) -{ - return ((FileStream*)handle)->read(buffer, count); -} - -static off_t mpg123_lseek_r(void* handle, off_t offset, int whence) -{ - return ((FileStream*)handle)->seek(offset, whence); -} - -void mpg123_close_r(void* handle) -{ - ((FileStream*)handle)->close(); -} -#endif -bool AudioDecoderMp3::lazyInit() -{ - bool ret = true; -#if CC_USE_MPG123 - if (!__mp3Inited) - { - int error = mpg123_init(); - if (error == MPG123_OK) - { - __mp3Inited = true; - } - else - { - ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error)); - ret = false; - } - } -#endif - return ret; -} - -void AudioDecoderMp3::destroy() -{ -#if CC_USE_MPG123 - if (__mp3Inited) - { - mpg123_exit(); - __mp3Inited = false; - } -#endif -} - -AudioDecoderMp3::AudioDecoderMp3() : _handle(nullptr) -{ - lazyInit(); -} - -AudioDecoderMp3::~AudioDecoderMp3() -{ - close(); -} - -bool AudioDecoderMp3::open(std::string_view fullPath) -{ -#if !CC_USE_MPG123 - do - { - _fileStream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ); - if (!_fileStream) - { - ALOGE("Trouble with minimp3(1): %s\n", strerror(errno)); - break; - } - - auto handle = new mp3dec_impl(); - - handle->_decIO.read = minimp3_read_r; - handle->_decIO.seek = minimp3_seek_r; - handle->_decIO.read_data = handle->_decIO.seek_data = _fileStream.get(); - - if (mp3dec_ex_open_cb(&handle->_dec, &handle->_decIO, MP3D_SEEK_TO_SAMPLE) != 0) - { - delete handle; - break; - } - - auto& info = handle->_dec.info; - _channelCount = info.channels; // the _channelCount is samplesPerFrame - _sampleRate = info.hz; -# ifndef MINIMP3_FLOAT_OUTPUT - _sourceFormat = AUDIO_SOURCE_FORMAT::PCM_16; - _bytesPerBlock = sizeof(uint16_t) * _channelCount; -# else - _sourceFormat = AUDIO_SOURCE_FORMAT::PCM_FLT32; - _bytesPerBlock = sizeof(float) * _channelCount; -# endif - // samples - _totalFrames = handle->_dec.samples / _channelCount; - - // store the handle - _handle = handle; - - _isOpened = true; - return true; - } while (false); - - return false; -#else - int32_t rate = 0; - int error = MPG123_OK; - int mp3Encoding = 0; - int channel = 0; - do - { - _handle = mpg123_new(nullptr, &error); - if (nullptr == _handle) - { - ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error)); - break; - } - - if (!_fileStream.open(fullPath)) - { - ALOGE("Trouble with mpg123(1): %s\n", strerror(errno)); - break; - } - - mpg123_replace_reader_handle(_handle, mpg123_read_r, mpg123_lseek_r, mpg123_close_r); - - if (mpg123_open_handle(_handle, _fileStream) != MPG123_OK || - mpg123_getformat(_handle, &rate, &channel, &mp3Encoding) != MPG123_OK) - { - ALOGE("Trouble with mpg123(2): %s\n", mpg123_strerror(_handle)); - break; - } - - _channelCount = channel; - _sampleRate = rate; - - if (mp3Encoding == MPG123_ENC_SIGNED_16) - { - _bytesPerBlock = 2 * _channelCount; - _sourceFormat = AUDIO_SOURCE_FORMAT::PCM_16; - } - else if (mp3Encoding == MPG123_ENC_FLOAT_32) - { - _bytesPerBlock = 4 * _channelCount; - _sourceFormat = AUDIO_SOURCE_FORMAT::PCM_FLT32; - } - else - { - ALOGE("Bad encoding: 0x%x!\n", mp3Encoding); - break; - } - - /* Ensure that this output format will not change (it could, when we allow it). */ - mpg123_format_none(_handle); - mpg123_format(_handle, rate, channel, mp3Encoding); - /* Ensure that we can get accurate length by call mpg123_length */ - mpg123_scan(_handle); - - _totalFrames = mpg123_length(_handle); - - _isOpened = true; - return true; - } while (false); - - if (_handle != nullptr) - { - mpg123_close(_handle); - mpg123_delete(_handle); - _handle = nullptr; - } - return false; -#endif -} - -void AudioDecoderMp3::close() -{ - if (isOpened()) - { -#if !CC_USE_MPG123 - if (_handle) - { - mp3dec_ex_close(&_handle->_dec); - - delete _handle; - _handle = nullptr; - _fileStream.reset(); - } -#else - if (_handle != nullptr) - { - mpg123_close(_handle); - mpg123_delete(_handle); - _handle = nullptr; - - _fileStream.reset(); - } -#endif - _isOpened = false; - } -} - -uint32_t AudioDecoderMp3::read(uint32_t framesToRead, char* pcmBuf) -{ -#if !CC_USE_MPG123 - auto sampelsToRead = framesToRead * _channelCount; - auto samplesRead = mp3dec_ex_read(&_handle->_dec, (mp3d_sample_t*)pcmBuf, sampelsToRead); - return static_cast(samplesRead / _channelCount); -#else - int bytesToRead = framesToBytes(framesToRead); - size_t bytesRead = 0; - int err = mpg123_read(_handle, (unsigned char*)pcmBuf, bytesToRead, &bytesRead); - if (err == MPG123_ERR) - { - ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(_handle)); - return 0; - } - - return bytesToFrames(bytesRead); -#endif -} - -bool AudioDecoderMp3::seek(uint32_t frameOffset) -{ -#if !CC_USE_MPG123 - return 0 == mp3dec_ex_seek(&_handle->_dec, frameOffset); -#else - off_t offset = mpg123_seek(_handle, frameOffset, SEEK_SET); - // ALOGD("mpg123_seek return: %d", (int)offset); - return (offset >= 0 && offset == frameOffset); -#endif -} -} // namespace cocos2d diff --git a/core/audio/src/AudioDecoderOgg.cpp b/core/audio/src/AudioDecoderOgg.cpp deleted file mode 100644 index bad5a4f6f4..0000000000 --- a/core/audio/src/AudioDecoderOgg.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** - Copyright (c) 2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#define LOG_TAG "AudioDecoderOgg" - -#include "audio/include/AudioDecoderOgg.h" -#include "audio/include/AudioMacros.h" -#include "platform/CCFileUtils.h" - -#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID -# include -# include -#endif - -namespace cocos2d -{ - -static size_t ov_fread_r(void* buffer, size_t element_size, size_t element_count, void* handle) -{ - auto* fs = static_cast(handle); - return fs->read(buffer, static_cast(element_size * element_count)); -} - -static int ov_fseek_r(void* handle, ogg_int64_t offset, int whence) -{ - auto* fs = static_cast(handle); - return fs->seek(offset, whence) < 0 ? -1 : 0; -} - -static long ov_ftell_r(void* handle) -{ - auto* fs = static_cast(handle); - return fs->tell(); -} - -static int ov_fclose_r(void* handle) -{ - auto* fs = static_cast(handle); - delete fs; - return 0; -} - -AudioDecoderOgg::AudioDecoderOgg() {} - -AudioDecoderOgg::~AudioDecoderOgg() -{ - close(); -} - -bool AudioDecoderOgg::open(std::string_view fullPath) -{ - auto fs = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ).release(); - if (!fs) - { - ALOGE("Trouble with ogg(1): %s\n", strerror(errno)); - return false; - } - - static ov_callbacks OV_CALLBACKS_POSIX = {ov_fread_r, ov_fseek_r, ov_fclose_r, ov_ftell_r}; - - if (0 == ov_open_callbacks(fs, &_vf, nullptr, 0, OV_CALLBACKS_POSIX)) - { - // header - vorbis_info* vi = ov_info(&_vf, -1); - _sampleRate = static_cast(vi->rate); - _channelCount = vi->channels; - _bytesPerBlock = vi->channels * sizeof(short); - _totalFrames = static_cast(ov_pcm_total(&_vf, -1)); - _isOpened = true; - return true; - } - return false; -} - -void AudioDecoderOgg::close() -{ - if (isOpened()) - { - ov_clear(&_vf); - _isOpened = false; - } -} - -uint32_t AudioDecoderOgg::read(uint32_t framesToRead, char* pcmBuf) -{ - int currentSection = 0; - int bytesToRead = framesToBytes(framesToRead); - int32_t bytesRead = ov_read(&_vf, pcmBuf, bytesToRead, 0, 2, 1, ¤tSection); - return bytesToFrames(bytesRead); -} - -bool AudioDecoderOgg::seek(uint32_t frameOffset) -{ - return 0 == ov_pcm_seek(&_vf, frameOffset); -} -} // namespace cocos2d diff --git a/core/audio/src/AudioDecoderWav.cpp b/core/audio/src/AudioDecoderWav.cpp deleted file mode 100644 index 3d6be1e0fe..0000000000 --- a/core/audio/src/AudioDecoderWav.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018-2020 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ -#define LOG_TAG "AudioDecoderWav" - -#include -#include -#include "audio/include/AudioDecoderWav.h" -#include "audio/include/AudioMacros.h" -#include "platform/CCFileUtils.h" - -namespace cocos2d -{ -enum : uint32_t -{ - WAV_SIGN_ID = MAKE_FOURCC('W', 'A', 'V', 'E'), - WAV_FMT_ID = MAKE_FOURCC('f', 'm', 't', ' '), - WAV_DATA_ID = MAKE_FOURCC('d', 'a', 't', 'a'), - WAV_HEADER_SIZE = sizeof(struct WAV_CHUNK_HEADER), - WAV_RIFF_SIZE = sizeof(WAV_RIFF_CHUNK), -}; - -// 00000001-0000-0010-8000-00aa00389b71 -static const GUID WAV_SUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - -// 00000003-0000-0010-8000-00aa00389b71 -static const GUID WAV_SUBTYPE_IEEE_FLOAT = {0x00000003, - 0x0000, - 0x0010, - {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; - -static bool wav_scan_chunk(WAV_FILE* wavf, uint32_t chunkID, void* header, void* body, uint32_t bodySize) -{ - auto& fs = wavf->Stream; - auto h = (WAV_CHUNK_HEADER*)header; - for (; fs->read(h, WAV_HEADER_SIZE) == WAV_HEADER_SIZE;) - { - wavf->PcmDataOffset += WAV_HEADER_SIZE; - if (h->ChunkID == chunkID) - { // chunk found - if (body) - { // require read body? - auto readsize = (std::min)(bodySize, h->ChunkSize); - fs->read(body, readsize); - if (h->ChunkSize > bodySize) - fs->seek(h->ChunkSize - bodySize, SEEK_CUR); - wavf->PcmDataOffset += h->ChunkSize; - } - return true; - } - else - { - // Skip other non specified chunk - fs->seek(h->ChunkSize, SEEK_CUR); - wavf->PcmDataOffset += h->ChunkSize; - } - } - return false; -} -static bool wav_open(std::string_view fullPath, WAV_FILE* wavf) -{ - wavf->Stream = FileUtils::getInstance()->openFileStream(fullPath, FileStream::Mode::READ); - if (!wavf->Stream) - return false; - - auto& fileStream = wavf->Stream; - wavf->PcmDataOffset = 0; - - // Parsing RIFF chunk - fileStream->read(&wavf->FileHeader, WAV_RIFF_SIZE); - wavf->PcmDataOffset += WAV_RIFF_SIZE; - - if (wavf->FileHeader.Riff.Format != WAV_SIGN_ID) - return false; // not .wav file - - // check somthings - auto h = &wavf->FileHeader; - - // Parsing FMT chunk - if (!wav_scan_chunk(wavf, WAV_FMT_ID, &wavf->FileHeader.Fmt, &wavf->FileHeader.Fmt.AudioFormat, - sizeof(wavf->FileHeader.Fmt) - sizeof(WAV_RIFF_CHUNK))) - return false; - - auto& fmtInfo = h->Fmt; - - int bitDepth = (fmtInfo.BitsPerSample); - - // Read PCM data or extensible data if exists. - switch (fmtInfo.AudioFormat) - { // Check supported format - case WAV_FORMAT::PCM: - case WAV_FORMAT::IEEE: - switch (bitDepth) - { - case 8: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::PCM_U8; - break; - case 16: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::PCM_16; - break; - case 24: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::PCM_24; - break; - case 32: - wavf->SourceFormat = (fmtInfo.AudioFormat == WAV_FORMAT::IEEE) ? AUDIO_SOURCE_FORMAT::PCM_FLT32 - : AUDIO_SOURCE_FORMAT::PCM_32; - break; - case 64: - wavf->SourceFormat = (fmtInfo.AudioFormat == WAV_FORMAT::IEEE) ? AUDIO_SOURCE_FORMAT::PCM_FLT64 - : AUDIO_SOURCE_FORMAT::PCM_64; - break; - } - break; - case WAV_FORMAT::MULAW: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::MULAW; - break; - case WAV_FORMAT::ALAW: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::MULAW; - break; - case WAV_FORMAT::ADPCM: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::ADPCM; - break; - case WAV_FORMAT::IMA_ADPCM: - wavf->SourceFormat = AUDIO_SOURCE_FORMAT::IMA_ADPCM; - break; - case WAV_FORMAT::EXT: - // Check sub-format. - if (!IsEqualGUID(fmtInfo.ExtParams.SubFormat, WAV_SUBTYPE_PCM) && - !IsEqualGUID(fmtInfo.ExtParams.SubFormat, WAV_SUBTYPE_IEEE_FLOAT)) - { - fileStream.reset(); - return false; - } - break; - default: - ALOGW("The wav format %d doesn't supported currently!", (int)fmtInfo.AudioFormat); - fileStream.reset(); - assert(false); - return false; - } - - return wav_scan_chunk(wavf, WAV_DATA_ID, &h->PcmData, nullptr, 0); -} - -static int wav_read(WAV_FILE* wavf, char* pcmBuf, uint32_t bytesToRead) -{ - return wavf->Stream->read(pcmBuf, bytesToRead); -} - -static int wav_seek(WAV_FILE* wavf, int offset) -{ - wavf->Stream->seek(wavf->PcmDataOffset + offset, SEEK_SET); - const auto newOffset = wavf->Stream->tell(); - return newOffset >= wavf->PcmDataOffset ? newOffset - wavf->PcmDataOffset : -1; -} - -static int wav_close(WAV_FILE* wavf) -{ - const auto result = wavf->Stream->close(); - wavf->Stream.reset(); - return result; -} - -AudioDecoderWav::AudioDecoderWav() -{ - memset(&_wavf, 0, offsetof(WAV_FILE, Stream)); -} - -AudioDecoderWav::~AudioDecoderWav() -{ - close(); -} - -bool AudioDecoderWav::open(std::string_view fullPath) -{ - if (wav_open(fullPath, &_wavf)) - { - auto& fmtInfo = _wavf.FileHeader.Fmt; - _sampleRate = fmtInfo.SampleRate; - _channelCount = fmtInfo.NumChannels; - _bytesPerBlock = fmtInfo.BlockAlign; // == fmtInfo.BitsPerSample * _channelCount / 8; - _sourceFormat = _wavf.SourceFormat; - - // See: https://github.com/openalext/openalext/wiki/AL_SOFT_block_alignment - switch (_sourceFormat) - { - case AUDIO_SOURCE_FORMAT::ADPCM: - _samplesPerBlock = (_bytesPerBlock / _channelCount - 7) * 2 + 2; - break; - case AUDIO_SOURCE_FORMAT::IMA_ADPCM: - _samplesPerBlock = (_bytesPerBlock / _channelCount - 4) / 4 * 8 + 1; - break; - default:; - } - - _totalFrames = bytesToFrames(_wavf.FileHeader.PcmData.ChunkSize); - - _isOpened = true; - return true; - } - return false; -} - -uint32_t AudioDecoderWav::framesToBytes(uint32_t frames) const -{ - if (_samplesPerBlock == 1) - return _bytesPerBlock * frames; - - return frames / _samplesPerBlock * _bytesPerBlock; -} - -uint32_t AudioDecoderWav::bytesToFrames(uint32_t bytes) const -{ - if (_samplesPerBlock == 1) - return bytes / _bytesPerBlock; - return bytes / _bytesPerBlock * _samplesPerBlock; -} - -void AudioDecoderWav::close() -{ - if (isOpened()) - { - wav_close(&_wavf); - _isOpened = false; - } -} - -uint32_t AudioDecoderWav::read(uint32_t framesToRead, char* pcmBuf) -{ - auto bytesToRead = framesToBytes(framesToRead); - int32_t bytesRead = wav_read(&_wavf, pcmBuf, bytesToRead); - return bytesToFrames(bytesRead); -} - -bool AudioDecoderWav::seek(uint32_t frameOffset) -{ - auto offset = framesToBytes(frameOffset); - return wav_seek(&_wavf, offset) == offset; -} -} // namespace cocos2d diff --git a/core/audio/src/AudioEngine.cpp b/core/audio/src/AudioEngine.cpp deleted file mode 100644 index 8590394e97..0000000000 --- a/core/audio/src/AudioEngine.cpp +++ /dev/null @@ -1,611 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "platform/CCPlatformConfig.h" - -#include "audio/include/AudioEngine.h" -#include -#include -#include "platform/CCFileUtils.h" -#include "base/ccUtils.h" - -#include "audio/include/AudioEngineImpl.h" - -#define TIME_DELAY_PRECISION 0.0001 - -#ifdef ERROR -# undef ERROR -#endif // ERROR - -using namespace cocos2d; - -const int AudioEngine::INVALID_AUDIO_ID = -1; -const float AudioEngine::TIME_UNKNOWN = -1.0f; - -// audio file path,audio IDs -hlookup::string_map> AudioEngine::_audioPathIDMap; -// profileName,ProfileHelper -hlookup::string_map AudioEngine::_audioPathProfileHelperMap; -unsigned int AudioEngine::_maxInstances = MAX_AUDIOINSTANCES; -AudioEngine::ProfileHelper* AudioEngine::_defaultProfileHelper = nullptr; -std::unordered_map AudioEngine::_audioIDInfoMap; -AudioEngineImpl* AudioEngine::_audioEngineImpl = nullptr; - -AudioEngine::AudioEngineThreadPool* AudioEngine::s_threadPool = nullptr; -bool AudioEngine::_isEnabled = true; - -AudioEngine::AudioInfo::AudioInfo() - : profileHelper(nullptr), volume(1.0f), loop(false), duration(TIME_UNKNOWN), state(AudioState::INITIALIZING) -{} - -AudioEngine::AudioInfo::~AudioInfo() {} - -class AudioEngine::AudioEngineThreadPool -{ -public: - AudioEngineThreadPool(int threads = 4) : _stop(false) - { - for (int index = 0; index < threads; ++index) - { - _workers.emplace_back(std::thread(std::bind(&AudioEngineThreadPool::threadFunc, this))); - } - } - - void addTask(const std::function& task) - { - std::unique_lock lk(_queueMutex); - _taskQueue.emplace(task); - _taskCondition.notify_one(); - } - - ~AudioEngineThreadPool() - { - { - std::unique_lock lk(_queueMutex); - _stop = true; - _taskCondition.notify_all(); - } - - for (auto&& worker : _workers) - { - worker.join(); - } - } - -private: - void threadFunc() - { - while (true) - { - std::function task = nullptr; - { - std::unique_lock lk(_queueMutex); - if (_stop) - { - break; - } - if (!_taskQueue.empty()) - { - task = std::move(_taskQueue.front()); - _taskQueue.pop(); - } - else - { - _taskCondition.wait(lk); - continue; - } - } - - task(); - } - } - - std::vector _workers; - std::queue> _taskQueue; - - std::mutex _queueMutex; - std::condition_variable _taskCondition; - bool _stop; -}; - -void AudioEngine::end() -{ - // make sure everythings cleanup before delete audio engine - // fix #127 - uncacheAll(); - - if (s_threadPool) - { - delete s_threadPool; - s_threadPool = nullptr; - } - - delete _audioEngineImpl; - _audioEngineImpl = nullptr; - - delete _defaultProfileHelper; - _defaultProfileHelper = nullptr; -} - -bool AudioEngine::lazyInit() -{ - if (_audioEngineImpl == nullptr) - { - _audioEngineImpl = new AudioEngineImpl(); - if (!_audioEngineImpl->init()) - { - delete _audioEngineImpl; - _audioEngineImpl = nullptr; - return false; - } - } - - if (s_threadPool == nullptr) - { - s_threadPool = new AudioEngineThreadPool(); - } - - return true; -} - -AUDIO_ID AudioEngine::play2d(std::string_view filePath, bool loop, float volume, const AudioProfile* profile) -{ - AUDIO_ID ret = AudioEngine::INVALID_AUDIO_ID; - - do - { - if (!isEnabled()) - { - break; - } - - if (!lazyInit()) - { - break; - } - - if (!FileUtils::getInstance()->isFileExist(filePath)) - { - break; - } - - auto profileHelper = _defaultProfileHelper; - if (profile && profile != &profileHelper->profile) - { - CC_ASSERT(!profile->name.empty()); - profileHelper = &_audioPathProfileHelperMap[profile->name]; - profileHelper->profile = *profile; - } - - if (_audioIDInfoMap.size() >= _maxInstances) - { - log("Fail to play %s cause by limited max instance of AudioEngine", filePath.data()); - break; - } - if (profileHelper) - { - if (profileHelper->profile.maxInstances != 0 && - profileHelper->audioIDs.size() >= profileHelper->profile.maxInstances) - { - log("Fail to play %s cause by limited max instance of AudioProfile", filePath.data()); - break; - } - if (profileHelper->profile.minDelay > TIME_DELAY_PRECISION) - { - auto currTime = utils::gettime(); - if (profileHelper->lastPlayTime > TIME_DELAY_PRECISION && - currTime - profileHelper->lastPlayTime <= profileHelper->profile.minDelay) - { - log("Fail to play %s cause by limited minimum delay", filePath.data()); - break; - } - } - } - - if (volume < 0.0f) - { - volume = 0.0f; - } - else if (volume > 1.0f) - { - volume = 1.0f; - } - - ret = _audioEngineImpl->play2d(filePath, loop, volume); - if (ret != INVALID_AUDIO_ID) - { - _audioPathIDMap[filePath.data()].push_back(ret); - auto it = _audioPathIDMap.find(filePath); - - auto& audioRef = _audioIDInfoMap[ret]; - audioRef.volume = volume; - audioRef.loop = loop; - audioRef.filePath = it->first; - - if (profileHelper) - { - profileHelper->lastPlayTime = utils::gettime(); - profileHelper->audioIDs.push_back(ret); - } - audioRef.profileHelper = profileHelper; - } - } while (0); - - return ret; -} - -void AudioEngine::setLoop(AUDIO_ID audioID, bool loop) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end() && it->second.loop != loop) - { - _audioEngineImpl->setLoop(audioID, loop); - it->second.loop = loop; - } -} - -void AudioEngine::setVolume(AUDIO_ID audioID, float volume) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end()) - { - if (volume < 0.0f) - { - volume = 0.0f; - } - else if (volume > 1.0f) - { - volume = 1.0f; - } - - if (it->second.volume != volume) - { - _audioEngineImpl->setVolume(audioID, volume); - it->second.volume = volume; - } - } -} - -void AudioEngine::pause(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end() && it->second.state == AudioState::PLAYING) - { - _audioEngineImpl->pause(audioID); - it->second.state = AudioState::PAUSED; - } -} - -void AudioEngine::pauseAll() -{ - auto itEnd = _audioIDInfoMap.end(); - for (auto it = _audioIDInfoMap.begin(); it != itEnd; ++it) - { - if (it->second.state == AudioState::PLAYING) - { - _audioEngineImpl->pause(it->first); - it->second.state = AudioState::PAUSED; - } - } -} - -void AudioEngine::resume(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end() && it->second.state == AudioState::PAUSED) - { - _audioEngineImpl->resume(audioID); - it->second.state = AudioState::PLAYING; - } -} - -void AudioEngine::resumeAll() -{ - auto itEnd = _audioIDInfoMap.end(); - for (auto it = _audioIDInfoMap.begin(); it != itEnd; ++it) - { - if (it->second.state == AudioState::PAUSED) - { - _audioEngineImpl->resume(it->first); - it->second.state = AudioState::PLAYING; - } - } -} - -void AudioEngine::stop(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end()) - { - _audioEngineImpl->stop(audioID); - - remove(audioID); - } -} - -void AudioEngine::remove(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end()) - { - if (it->second.profileHelper) - { - it->second.profileHelper->audioIDs.remove(audioID); - } - _audioPathIDMap[it->second.filePath].remove(audioID); - _audioIDInfoMap.erase(audioID); - } -} - -void AudioEngine::stopAll() -{ - if (!_audioEngineImpl) - { - return; - } - _audioEngineImpl->stopAll(); - auto itEnd = _audioIDInfoMap.end(); - for (auto it = _audioIDInfoMap.begin(); it != itEnd; ++it) - { - if (it->second.profileHelper) - { - it->second.profileHelper->audioIDs.remove(it->first); - } - } - _audioPathIDMap.clear(); - _audioIDInfoMap.clear(); -} - -void AudioEngine::uncache(std::string_view filePath) -{ - if (!_audioEngineImpl) - { - return; - } - auto audioIDsIter = _audioPathIDMap.find(filePath); - if (audioIDsIter != _audioPathIDMap.end()) - { - //@Note: For safely iterating elements from the audioID list, we need to copy the list - // since 'AudioEngine::remove' may be invoked in '_audioEngineImpl->stop' synchronously. - // If this happens, it will break the iteration, and crash will appear on some devices. - std::list copiedIDs(audioIDsIter->second); - - for (AUDIO_ID audioID : copiedIDs) - { - _audioEngineImpl->stop(audioID); - - auto itInfo = _audioIDInfoMap.find(audioID); - if (itInfo != _audioIDInfoMap.end()) - { - if (itInfo->second.profileHelper) - { - itInfo->second.profileHelper->audioIDs.remove(audioID); - } - _audioIDInfoMap.erase(audioID); - } - } - _audioPathIDMap.erase(filePath); - } - - if (_audioEngineImpl) - { - _audioEngineImpl->uncache(filePath); - } -} - -void AudioEngine::uncacheAll() -{ - if (!_audioEngineImpl) - { - return; - } - stopAll(); - _audioEngineImpl->uncacheAll(); -} - -float AudioEngine::getDuration(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end() && it->second.state != AudioState::INITIALIZING) - { - if (it->second.duration == TIME_UNKNOWN) - { - it->second.duration = _audioEngineImpl->getDuration(audioID); - } - return it->second.duration; - } - - return TIME_UNKNOWN; -} - -bool AudioEngine::setCurrentTime(AUDIO_ID audioID, float time) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end() && it->second.state != AudioState::INITIALIZING) - { - return _audioEngineImpl->setCurrentTime(audioID, time); - } - - return false; -} - -float AudioEngine::getCurrentTime(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end() && it->second.state != AudioState::INITIALIZING) - { - return _audioEngineImpl->getCurrentTime(audioID); - } - return 0.0f; -} - -void AudioEngine::setFinishCallback(AUDIO_ID audioID, const std::function& callback) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end()) - { - _audioEngineImpl->setFinishCallback(audioID, callback); - } -} - -bool AudioEngine::setMaxAudioInstance(int maxInstances) -{ - if (maxInstances > 0 && maxInstances <= MAX_AUDIOINSTANCES) - { - _maxInstances = maxInstances; - return true; - } - - return false; -} - -bool AudioEngine::isLoop(AUDIO_ID audioID) -{ - auto tmpIterator = _audioIDInfoMap.find(audioID); - if (tmpIterator != _audioIDInfoMap.end()) - { - return tmpIterator->second.loop; - } - - log("AudioEngine::isLoop-->The audio instance %d is non-existent", audioID); - return false; -} - -float AudioEngine::getVolume(AUDIO_ID audioID) -{ - auto tmpIterator = _audioIDInfoMap.find(audioID); - if (tmpIterator != _audioIDInfoMap.end()) - { - return tmpIterator->second.volume; - } - - log("AudioEngine::getVolume-->The audio instance %d is non-existent", audioID); - return 0.0f; -} - -AudioEngine::AudioState AudioEngine::getState(AUDIO_ID audioID) -{ - auto tmpIterator = _audioIDInfoMap.find(audioID); - if (tmpIterator != _audioIDInfoMap.end()) - { - return tmpIterator->second.state; - } - - return AudioState::ERROR; -} - -AudioProfile* AudioEngine::getProfile(AUDIO_ID audioID) -{ - auto it = _audioIDInfoMap.find(audioID); - if (it != _audioIDInfoMap.end()) - { - return &it->second.profileHelper->profile; - } - - return nullptr; -} - -AudioProfile* AudioEngine::getDefaultProfile() -{ - if (_defaultProfileHelper == nullptr) - { - _defaultProfileHelper = new ProfileHelper(); - } - - return &_defaultProfileHelper->profile; -} - -AudioProfile* AudioEngine::getProfile(std::string_view name) -{ - auto it = _audioPathProfileHelperMap.find(name); - if (it != _audioPathProfileHelperMap.end()) - { - return &it->second.profile; - } - else - { - return nullptr; - } -} - -void AudioEngine::preload(std::string_view filePath, std::function callback) -{ - if (!isEnabled()) - { - callback(false); - return; - } - - lazyInit(); - - if (_audioEngineImpl) - { - if (!FileUtils::getInstance()->isFileExist(filePath)) - { - if (callback) - { - callback(false); - } - return; - } - - _audioEngineImpl->preload(filePath, callback); - } -} - -void AudioEngine::addTask(const std::function& task) -{ - lazyInit(); - - if (_audioEngineImpl && s_threadPool) - { - s_threadPool->addTask(task); - } -} - -int AudioEngine::getPlayingAudioCount() -{ - return static_cast(_audioIDInfoMap.size()); -} - -void AudioEngine::setEnabled(bool isEnabled) -{ - if (_isEnabled != isEnabled) - { - _isEnabled = isEnabled; - - if (!_isEnabled) - { - stopAll(); - } - } -} - -bool AudioEngine::isEnabled() -{ - return _isEnabled; -} diff --git a/core/audio/src/AudioEngineImpl.mm b/core/audio/src/AudioEngineImpl.mm deleted file mode 100644 index f4aca8818f..0000000000 --- a/core/audio/src/AudioEngineImpl.mm +++ /dev/null @@ -1,872 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018-2020 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ -#define LOG_TAG "AudioEngineImpl" - -#include "platform/CCPlatformConfig.h" - -#include "audio/include/AudioEngineImpl.h" -#include "audio/include/AudioDecoderManager.h" - -#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC -# import -#endif - -#include "audio/include/AudioEngine.h" -#include "platform/CCFileUtils.h" -#include "base/CCDirector.h" -#include "base/CCScheduler.h" -#include "base/ccUtils.h" - -#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS -# import -#endif - -using namespace cocos2d; - -static ALCdevice* s_ALDevice = nullptr; -static ALCcontext* s_ALContext = nullptr; -static AudioEngineImpl* s_instance = nullptr; - -static void ccALPauseDevice() -{ - ALOGD("%s", "===> ccALPauseDevice"); -#if CC_USE_ALSOFT - alcDevicePauseSOFT(s_ALDevice); -#else - if (alcGetCurrentContext()) - alcMakeContextCurrent(nullptr); -#endif -} - -static void ccALResumeDevice() -{ - ALOGD("%s", "===> ccALResumeDevice"); -#if CC_USE_ALSOFT - alcDeviceResumeSOFT(s_ALDevice); -#else - if (alcGetCurrentContext()) - alcMakeContextCurrent(nullptr); - alcMakeContextCurrent(s_ALContext); -#endif -} - -#if defined(__APPLE__) - -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 { -} - -- (id)init; -- (void)handleInterruption:(NSNotification*)notification; - -@end - -@implementation AudioEngineSessionHandler - -- (id)init -{ - if (self = [super init]) - { - int deviceVer = [[[UIDevice currentDevice] systemVersion] intValue]; - ALOGD("===> The device version: %d", deviceVer); - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleInterruption:) - name:AVAudioSessionInterruptionNotification - object:[AVAudioSession sharedInstance]]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleInterruption:) - name:UIApplicationDidBecomeActiveNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleInterruption:) - name:UIApplicationWillResignActiveNotification - object:nil]; - - BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]; - if (!success) - ALOGE("Fail to set audio session."); - } - return self; -} - -- (void)handleInterruption:(NSNotification*)notification -{ - static bool isAudioSessionInterrupted = false; - static bool resumeOnBecomingActive = false; - static bool pauseOnResignActive = false; - - if ([notification.name isEqualToString:AVAudioSessionInterruptionNotification]) - { - NSInteger reason = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] integerValue]; - if (reason == AVAudioSessionInterruptionTypeBegan) - { - isAudioSessionInterrupted = true; - - if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) - { - ALOGD("AVAudioSessionInterruptionTypeBegan, application != UIApplicationStateActive, " - "alcMakeContextCurrent(nullptr)"); - } - else - { - ALOGD("AVAudioSessionInterruptionTypeBegan, application == UIApplicationStateActive, " - "pauseOnResignActive = true"); - } - - // We always pause device when interruption began - ccALPauseDevice(); - } - else if (reason == AVAudioSessionInterruptionTypeEnded) - { - isAudioSessionInterrupted = false; - - if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) - { - ALOGD("AVAudioSessionInterruptionTypeEnded, application == UIApplicationStateActive, " - "alcMakeContextCurrent(s_ALContext)"); - NSError* error = nil; - [[AVAudioSession sharedInstance] setActive:YES error:&error]; - ccALResumeDevice(); - if (Director::getInstance()->isPaused()) - { - ALOGD("AVAudioSessionInterruptionTypeEnded, director was paused, try to resume it."); - Director::getInstance()->resume(); - } - } - else - { - ALOGD("AVAudioSessionInterruptionTypeEnded, application != UIApplicationStateActive, " - "resumeOnBecomingActive = true"); - resumeOnBecomingActive = true; - } - } - } - else if ([notification.name isEqualToString:UIApplicationWillResignActiveNotification]) - { - ALOGD("UIApplicationWillResignActiveNotification"); - if (pauseOnResignActive) - { - pauseOnResignActive = false; - ALOGD("UIApplicationWillResignActiveNotification, alcMakeContextCurrent(nullptr)"); - ccALPauseDevice(); - } - } - else if ([notification.name isEqualToString:UIApplicationDidBecomeActiveNotification]) - { - ALOGD("UIApplicationDidBecomeActiveNotification"); - if (resumeOnBecomingActive) - { - resumeOnBecomingActive = false; - ALOGD("UIApplicationDidBecomeActiveNotification, alcMakeContextCurrent(s_ALContext)"); - NSError* error = nil; - BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&error]; - if (!success) - { - ALOGE("Fail to set audio session."); - return; - } - [[AVAudioSession sharedInstance] setActive:YES error:&error]; - - ccALResumeDevice(); - } - else if (isAudioSessionInterrupted) - { - ALOGD("Audio session is still interrupted!"); - } - } -} - -- (void)dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionInterruptionNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; - [[NSNotificationCenter defaultCenter] removeObserver:self - name:UIApplicationWillResignActiveNotification - object:nil]; - - [super dealloc]; -} -@end - -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; - s_instance->_threadMutex.lock(); - for (const auto& e : s_instance->_audioPlayers) - { - player = e.second; - if (player->_alSource == sid && player->_streamingSource) - { - player->wakeupRotateThread(); - } - } - s_instance->_threadMutex.unlock(); -} - -#endif - -AudioEngineImpl::AudioEngineImpl() : _scheduled(false), _currentAudioID(0), _scheduler(nullptr) -{ - s_instance = this; -} - -AudioEngineImpl::~AudioEngineImpl() -{ - if (_scheduled && _scheduler != nullptr) - { - _scheduler->unschedule(CC_SCHEDULE_SELECTOR(AudioEngineImpl::update), this); - } - - if (s_ALContext) - { - alDeleteSources(MAX_AUDIOINSTANCES, _alSources); - - _audioCaches.clear(); - - alcMakeContextCurrent(nullptr); - alcDestroyContext(s_ALContext); - s_ALContext = nullptr; - } - - if (s_ALDevice) - { - alcCloseDevice(s_ALDevice); - s_ALDevice = nullptr; - } - - AudioDecoderManager::destroy(); - -#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS - [s_AudioEngineSessionHandler release]; -#endif - s_instance = nullptr; -} - -bool AudioEngineImpl::init() -{ - bool ret = false; - do - { -#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS - s_AudioEngineSessionHandler = [[AudioEngineSessionHandler alloc] init]; -#endif - - s_ALDevice = alcOpenDevice(nullptr); - - if (s_ALDevice) - { - alGetError(); - s_ALContext = alcCreateContext(s_ALDevice, nullptr); - alcMakeContextCurrent(s_ALContext); - - alGenSources(MAX_AUDIOINSTANCES, _alSources); - auto alError = alGetError(); - if (alError != AL_NO_ERROR) - { - ALOGE("%s:generating sources failed! error = %x\n", __FUNCTION__, alError); - break; - } - - for (int i = 0; i < MAX_AUDIOINSTANCES; ++i) - { - _unusedSourcesPool.push(_alSources[i]); -#if defined(__APPLE__) - alSourceAddNotificationExt(_alSources[i], AL_BUFFERS_PROCESSED, myAlSourceNotificationCallback, - nullptr); -#endif - } - - // fixed #16170: Random crash in alGenBuffers(AudioCache::readDataTask) at startup - // Please note that, as we know the OpenAL operation is atomic (threadsafe), - // 'alGenBuffers' may be invoked by different threads. But in current implementation of 'alGenBuffers', - // When the first time it's invoked, application may crash!!! - // Why? OpenAL is opensource by Apple and could be found at - // http://opensource.apple.com/source/OpenAL/OpenAL-48.7/Source/OpenAL/oalImp.cpp . - /* - - void InitializeBufferMap() - { - if (gOALBufferMap == NULL) // Position 1 - { - gOALBufferMap = new OALBufferMap (); // Position 2 - - // Position Gap - - gBufferMapLock = new CAGuard("OAL:BufferMapLock"); // Position 3 - gDeadOALBufferMap = new OALBufferMap (); - - OALBuffer *newBuffer = new OALBuffer (AL_NONE); - gOALBufferMap->Add(AL_NONE, &newBuffer); - } - } - - AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *bids) - { - ... - - try { - if (n < 0) - throw ((OSStatus) AL_INVALID_VALUE); - - InitializeBufferMap(); - if (gOALBufferMap == NULL) - throw ((OSStatus) AL_INVALID_OPERATION); - - CAGuard::Locker locked(*gBufferMapLock); // Position 4 - ... - ... - } - - */ - // 'gBufferMapLock' will be initialized in the 'InitializeBufferMap' function, - // that's the problem. It means that 'InitializeBufferMap' may be invoked in different threads. - // It will be very dangerous in multi-threads environment. - // Imagine there're two threads (Thread A, Thread B), they call 'alGenBuffers' simultaneously. - // While A goto 'Position Gap', 'gOALBufferMap' was assigned, then B goto 'Position 1' and find - // that 'gOALBufferMap' isn't NULL, B just jump over 'InitialBufferMap' and goto 'Position 4'. - // Meanwhile, A is still at 'Position Gap', B will crash at '*gBufferMapLock' since 'gBufferMapLock' - // is still a null pointer. Oops, how could Apple implemented this method in this fucking way? - - // Workaround is do an unused invocation in the mainthread right after OpenAL is initialized successfully - // as bellow. - // ================ Workaround begin ================ // -#if !CC_USE_ALSOFT - ALuint unusedAlBufferId = 0; - alGenBuffers(1, &unusedAlBufferId); - alDeleteBuffers(1, &unusedAlBufferId); -#endif - // ================ Workaround end ================ // - - _scheduler = Director::getInstance()->getScheduler(); - ret = AudioDecoderManager::init(); - const char* vender = alGetString(AL_VENDOR); - const char* version = alGetString(AL_VERSION); - ALOGI("OpenAL was initialized successfully, vender:%s, version:%s", vender, version); - } - } while (false); - - return ret; -} - -AudioCache* AudioEngineImpl::preload(std::string_view filePath, std::function callback) -{ - AudioCache* audioCache = nullptr; - - auto it = _audioCaches.find(filePath); - if (it == _audioCaches.end()) - { - audioCache = new AudioCache(); // hlookup_second(it); - _audioCaches.emplace(filePath, std::unique_ptr(audioCache)); - audioCache->_fileFullPath = FileUtils::getInstance()->fullPathForFilename(filePath); - unsigned int cacheId = audioCache->_id; - auto isCacheDestroyed = audioCache->_isDestroyed; - AudioEngine::addTask([audioCache, cacheId, isCacheDestroyed]() { - if (*isCacheDestroyed) - { - ALOGV("AudioCache (id=%u) was destroyed, no need to launch readDataTask.", cacheId); - audioCache->setSkipReadDataTask(true); - return; - } - audioCache->readDataTask(cacheId); - }); - } - else - { - audioCache = it->second.get(); - } - - if (audioCache && callback) - { - audioCache->addLoadCallback(callback); - } - return audioCache; -} - -AUDIO_ID AudioEngineImpl::play2d(std::string_view filePath, bool loop, float volume) -{ - if (s_ALDevice == nullptr) - { - return AudioEngine::INVALID_AUDIO_ID; - } - - ALuint alSource = findValidSource(); - if (alSource == AL_INVALID) - { - return AudioEngine::INVALID_AUDIO_ID; - } - - auto player = new AudioPlayer; - if (player == nullptr) - { - return AudioEngine::INVALID_AUDIO_ID; - } - - player->_alSource = alSource; - player->_loop = loop; - player->_volume = volume; - - auto audioCache = preload(filePath, nullptr); - if (audioCache == nullptr) - { - delete player; - return AudioEngine::INVALID_AUDIO_ID; - } - - player->setCache(audioCache); - _threadMutex.lock(); - _audioPlayers.emplace(++_currentAudioID, player); - _threadMutex.unlock(); - - audioCache->addPlayCallback(std::bind(&AudioEngineImpl::_play2d, this, audioCache, _currentAudioID)); - - if (!_scheduled) - { - _scheduled = true; - _scheduler->schedule(CC_SCHEDULE_SELECTOR(AudioEngineImpl::update), this, 0.05f, false); - } - - return _currentAudioID; -} - -void AudioEngineImpl::_play2d(AudioCache* cache, AUDIO_ID audioID) -{ - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return; - auto player = iter->second; - - // Note: It maybe in sub thread or main thread :( - if (!*cache->_isDestroyed && cache->_state == AudioCache::State::READY) - { - if (player->play2d()) - { - _scheduler->performFunctionInCocosThread([audioID]() { - if (AudioEngine::_audioIDInfoMap.find(audioID) != AudioEngine::_audioIDInfoMap.end()) - { - AudioEngine::_audioIDInfoMap[audioID].state = AudioEngine::AudioState::PLAYING; - } - }); - } - } - else - { - ALOGD("AudioEngineImpl::_play2d, cache was destroyed or not ready!"); - player->_removeByAudioEngine = true; - } -} - -ALuint AudioEngineImpl::findValidSource() -{ - ALuint sourceId = AL_INVALID; - if (!_unusedSourcesPool.empty()) - { - sourceId = _unusedSourcesPool.front(); - _unusedSourcesPool.pop(); - } - - return sourceId; -} - -void AudioEngineImpl::setVolume(AUDIO_ID audioID, float volume) -{ - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return; - - auto player = iter->second; - lck.unlock(); - - player->_volume = volume; - - if (player->_ready) - { - alSourcef(player->_alSource, AL_GAIN, volume); - - auto error = alGetError(); - if (error != AL_NO_ERROR) - { - ALOGE("%s: audio id = " AUDIO_ID_PRID ", error = %x", __FUNCTION__, audioID, error); - } - } -} - -void AudioEngineImpl::setLoop(AUDIO_ID audioID, bool loop) -{ - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return; - - auto player = iter->second; - - lck.unlock(); - - if (player->_ready) - { - if (player->_streamingSource) - { - player->setLoop(loop); - } - else - { - if (loop) - { - alSourcei(player->_alSource, AL_LOOPING, AL_TRUE); - } - else - { - alSourcei(player->_alSource, AL_LOOPING, AL_FALSE); - } - - auto error = alGetError(); - if (error != AL_NO_ERROR) - { - ALOGE("%s: audio id = " AUDIO_ID_PRID ", error = %x", __FUNCTION__, audioID, error); - } - } - } - else - { - player->_loop = loop; - } -} - -bool AudioEngineImpl::pause(AUDIO_ID audioID) -{ - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return false; - - auto player = iter->second; - - lck.unlock(); - - bool ret = true; - alSourcePause(player->_alSource); - - auto error = alGetError(); - if (error != AL_NO_ERROR) - { - ret = false; - ALOGE("%s: audio id = " AUDIO_ID_PRID ", error = %x\n", __FUNCTION__, audioID, error); - } - - return ret; -} - -bool AudioEngineImpl::resume(AUDIO_ID audioID) -{ - bool ret = true; - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return false; - - auto player = iter->second; - lck.unlock(); - - alSourcePlay(player->_alSource); - - auto error = alGetError(); - if (error != AL_NO_ERROR) - { - ret = false; - ALOGE("%s: audio id = " AUDIO_ID_PRID ", error = %x\n", __FUNCTION__, audioID, error); - } - - return ret; -} - -void AudioEngineImpl::stop(AUDIO_ID audioID) -{ - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return; - - auto player = iter->second; - player->destroy(); - - // Call '_updatePlayersState' method to cleanup immediately since the schedule may be cancelled without any - // notification. - _updatePlayers(true); -} - -void AudioEngineImpl::stopAll() -{ - std::lock_guard lck(_threadMutex); - for (auto&& player : _audioPlayers) - { - player.second->destroy(); - } - // Note: Don't set the flag to false here, it should be set in 'update' function. - // Otherwise, the state got from alSourceState may be wrong - // for(int index = 0; index < MAX_AUDIOINSTANCES; ++index) - // { - // _alSourceUsed[_alSources[index]] = false; - // } - - // Call '_updatePlayers' method to cleanup immediately since the schedule may be cancelled without any notification. - _updatePlayers(true); -} - -float AudioEngineImpl::getDuration(AUDIO_ID audioID) -{ - std::lock_guard lck(_threadMutex); - auto it = _audioPlayers.find(audioID); - if (it != _audioPlayers.end()) - { - auto player = it->second; - if (player->_ready) - { - return player->_audioCache->_duration; - } - } - return AudioEngine::TIME_UNKNOWN; -} - -float AudioEngineImpl::getCurrentTime(AUDIO_ID audioID) -{ - std::unique_lock lck(_threadMutex); - auto it = _audioPlayers.find(audioID); - if (it == _audioPlayers.end()) - return 0.0f; - - float ret = 0.0f; - auto player = it->second; - if (player->_ready) - { - if (player->_streamingSource) - { - ret = player->getTime(); - } - else - { - alGetSourcef(player->_alSource, AL_SEC_OFFSET, &ret); - - auto error = alGetError(); - if (error != AL_NO_ERROR) - { - ALOGE("%s, audio id:" AUDIO_ID_PRID ",error code:%x", __FUNCTION__, audioID, error); - } - } - } - - return ret; -} - -bool AudioEngineImpl::setCurrentTime(AUDIO_ID audioID, float time) -{ - bool ret = false; - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return false; - - auto player = iter->second; - - do - { - if (!player->_ready) - { - break; - } - - if (player->_streamingSource) - { - ret = player->setTime(time); - break; - } - else - { - if (player->_audioCache->_framesRead != player->_audioCache->_totalFrames && - (time * player->_audioCache->_sampleRate) > player->_audioCache->_framesRead) - { - ALOGE("%s: audio id = " AUDIO_ID_PRID, __FUNCTION__, audioID); - break; - } - - alSourcef(player->_alSource, AL_SEC_OFFSET, time); - - auto error = alGetError(); - if (error != AL_NO_ERROR) - { - ALOGE("%s: audio id = " AUDIO_ID_PRID ", error = %x", __FUNCTION__, audioID, error); - } - ret = true; - } - } while (0); - - return ret; -} - -void AudioEngineImpl::setFinishCallback(AUDIO_ID audioID, - const std::function& callback) -{ - std::unique_lock lck(_threadMutex); - auto iter = _audioPlayers.find(audioID); - if (iter == _audioPlayers.end()) - return; - - auto player = iter->second; - lck.unlock(); - - player->_finishCallbak = callback; -} - -void AudioEngineImpl::update(float /*dt*/) -{ - std::unique_lock lck(_threadMutex); - _updatePlayers(false); -} - -void AudioEngineImpl::_updatePlayers(bool forStop) -{ - AUDIO_ID audioID; - AudioPlayer* player; - ALuint alSource; - - // ALOGV("AudioPlayer count: %d", (int)_audioPlayers.size()); - for (auto it = _audioPlayers.begin(); it != _audioPlayers.end();) - { - audioID = it->first; - player = it->second; - alSource = player->_alSource; - - if (player->_removeByAudioEngine) - { - AudioEngine::remove(audioID); - - it = _audioPlayers.erase(it); - delete player; - _unusedSourcesPool.push(alSource); - } - else if (player->_ready && player->isFinished()) - { - - std::string filePath; - if (player->_finishCallbak) - { - auto& audioInfo = AudioEngine::_audioIDInfoMap[audioID]; - filePath = audioInfo.filePath; - } - - AudioEngine::remove(audioID); - - it = _audioPlayers.erase(it); - - if (player->_finishCallbak) - { - /// ###IMPORTANT: don't call immidiately, because at callback, user-end may play a new audio - /// cause _audioPlayers' iterator goan to invalid. - _finishCallbacks.push_back([finishCallback = std::move(player->_finishCallbak), audioID, - filePath = std::move(filePath)]() { finishCallback(audioID, filePath); }); - } - // clear cache when audio player finsihed properly - player->setCache(nullptr); - delete player; - _unusedSourcesPool.push(alSource); - } - else - { - ++it; - } - } - - // don't invoke finish callback when stop/stopAll to avoid stack overflow - if (UTILS_LIKELY(!forStop)) - { - if (!_finishCallbacks.empty()) - { - for (auto& finishCallback : _finishCallbacks) - finishCallback(); - _finishCallbacks.clear(); - } - - if (_audioPlayers.empty()) - _unscheduleUpdate(); - } - else if (!_audioPlayers.empty() && !_finishCallbacks.empty()) - _unscheduleUpdate(); -} - -void AudioEngineImpl::_unscheduleUpdate() -{ - if (_scheduled) - { - _scheduled = false; - _scheduler->unschedule(CC_SCHEDULE_SELECTOR(AudioEngineImpl::update), this); - } -} - -void AudioEngineImpl::uncache(std::string_view filePath) -{ - _audioCaches.erase(filePath); -} - -void AudioEngineImpl::uncacheAll() -{ - // prevent player hold invalid AudioCache* pointer, since all audio caches purged - for (auto& player : _audioPlayers) - player.second->setCache(nullptr); - - _audioCaches.clear(); -} diff --git a/core/audio/src/AudioPlayer.cpp b/core/audio/src/AudioPlayer.cpp deleted file mode 100644 index f31dde381e..0000000000 --- a/core/audio/src/AudioPlayer.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2018-2020 HALX99. - Copyright (c) 2021 Bytedance Inc. - - https://adxe.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#define LOG_TAG "AudioPlayer" - -#include "platform/CCPlatformConfig.h" -#include "audio/include/AudioPlayer.h" -#include "audio/include/AudioCache.h" -#include "platform/CCFileUtils.h" -#include "audio/include/AudioDecoder.h" -#include "audio/include/AudioDecoderManager.h" - -#ifdef VERY_VERY_VERBOSE_LOGGING -# define ALOGVV ALOGV -#else -# define ALOGVV(...) \ - do \ - { \ - } while (false) -#endif - -using namespace cocos2d; - -namespace -{ -unsigned int __idIndex = 0; -} - -AudioPlayer::AudioPlayer() - : _audioCache(nullptr) - , _finishCallbak(nullptr) - , _isDestroyed(false) - , _removeByAudioEngine(false) - , _ready(false) - , _currTime(0.0f) - , _streamingSource(false) - , _rotateBufferThread(nullptr) - , _timeDirty(false) - , _isRotateThreadExited(false) -#if defined(__APPLE__) - , _needWakeupRotateThread(false) -#endif - , _id(++__idIndex) -{ - memset(_bufferIds, 0, sizeof(_bufferIds)); -} - -AudioPlayer::~AudioPlayer() -{ - ALOGVV("~AudioPlayer() (%p), id=%u", this, _id); - destroy(); - - if (_streamingSource) - { - alDeleteBuffers(QUEUEBUFFER_NUM, _bufferIds); - } -} - -void AudioPlayer::destroy() -{ - std::unique_lock lck(_play2dMutex); - if (_isDestroyed) - return; - - ALOGVV("AudioPlayer::destroy begin, id=%u", _id); - - _isDestroyed = true; - - do - { - if (_audioCache != nullptr) - { - if (_audioCache->_state == AudioCache::State::INITIAL) - { - ALOGV("AudioPlayer::destroy, id=%u, cache isn't ready!", _id); - break; - } - - while (!_audioCache->_isLoadingFinished) - { - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - } - } - - if (_streamingSource) - { - if (_rotateBufferThread != nullptr) - { - while (!_isRotateThreadExited) - { - _sleepCondition.notify_one(); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - } - - if (_rotateBufferThread->joinable()) - { - _rotateBufferThread->join(); - } - - delete _rotateBufferThread; - _rotateBufferThread = nullptr; - ALOGVV("rotateBufferThread exited!"); - -#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS - // some specific OpenAL implement defects existed on iOS platform - // refer to: https://github.com/cocos2d/cocos2d-x/issues/18597 - ALint sourceState; - ALint bufferProcessed = 0; - alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState); - if (sourceState == AL_PLAYING) - { - alGetSourcei(_alSource, AL_BUFFERS_PROCESSED, &bufferProcessed); - while (bufferProcessed < QUEUEBUFFER_NUM) - { - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - alGetSourcei(_alSource, AL_BUFFERS_PROCESSED, &bufferProcessed); - } - alSourceUnqueueBuffers(_alSource, QUEUEBUFFER_NUM, _bufferIds); - CHECK_AL_ERROR_DEBUG(); - } - ALOGVV("UnqueueBuffers Before alSourceStop"); -#endif - } - } - } while (false); - - ALOGVV("Before alSourceStop"); - alSourceStop(_alSource); - CHECK_AL_ERROR_DEBUG(); - ALOGVV("Before alSourcei"); - alSourcei(_alSource, AL_BUFFER, 0); - CHECK_AL_ERROR_DEBUG(); - - _removeByAudioEngine = true; - - _ready = false; - ALOGVV("AudioPlayer::destroy end, id=%u", _id); -} - -void AudioPlayer::setCache(AudioCache* cache) -{ - _audioCache = cache; -} - -bool AudioPlayer::play2d() -{ - std::unique_lock lck(_play2dMutex); - ALOGV("AudioPlayer::play2d, _alSource: %u, player id=%u", _alSource, _id); - - if (_isDestroyed) - return false; - - /*********************************************************************/ - /* Note that it may be in sub thread or in main thread. **/ - /*********************************************************************/ - bool ret = false; - do - { - if (_audioCache->_state != AudioCache::State::READY) - { - ALOGE("alBuffer isn't ready for play!"); - break; - } - - alSourcei(_alSource, AL_BUFFER, 0); - CHECK_AL_ERROR_DEBUG(); - alSourcef(_alSource, AL_PITCH, 1.0f); - CHECK_AL_ERROR_DEBUG(); - alSourcef(_alSource, AL_GAIN, _volume); - CHECK_AL_ERROR_DEBUG(); - alSourcei(_alSource, AL_LOOPING, AL_FALSE); - CHECK_AL_ERROR_DEBUG(); - - if (_audioCache->_queBufferFrames == 0) - { - if (_loop) - { - alSourcei(_alSource, AL_LOOPING, AL_TRUE); - CHECK_AL_ERROR_DEBUG(); - } - } - else - { - alGenBuffers(QUEUEBUFFER_NUM, _bufferIds); - - auto alError = alGetError(); - if (alError == AL_NO_ERROR) - { - for (int index = 0; index < QUEUEBUFFER_NUM; ++index) - { - alBufferData(_bufferIds[index], _audioCache->_format, _audioCache->_queBuffers[index], - _audioCache->_queBufferSize[index], _audioCache->_sampleRate); - } - CHECK_AL_ERROR_DEBUG(); - } - else - { - ALOGE("%s:alGenBuffers error code:%x", __FUNCTION__, alError); - break; - } - _streamingSource = true; - } - - { - std::unique_lock lk(_sleepMutex); - if (_isDestroyed) - break; - - if (_streamingSource) - { - // To continuously stream audio from a source without interruption, buffer queuing is required. - alSourceQueueBuffers(_alSource, QUEUEBUFFER_NUM, _bufferIds); - CHECK_AL_ERROR_DEBUG(); - _rotateBufferThread = new std::thread(&AudioPlayer::rotateBufferThread, this, - _audioCache->_queBufferFrames * QUEUEBUFFER_NUM + 1); - } - else - { - alSourcei(_alSource, AL_BUFFER, _audioCache->_alBufferId); - CHECK_AL_ERROR_DEBUG(); - } - - alSourcePlay(_alSource); - } - - auto alError = alGetError(); - if (alError != AL_NO_ERROR) - { - ALOGE("%s:alSourcePlay error code:%x", __FUNCTION__, alError); - break; - } - - ALint state; - alGetSourcei(_alSource, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING) - ALOGE("state isn't playing, %d, %s, cache id=%u, player id=%u", state, _audioCache->_fileFullPath.c_str(), - _audioCache->_id, _id); - - // OpenAL framework: sometime when switch audio too fast, the result state will error, but there is no any - // alError, so just skip for workaround. - assert(state == AL_PLAYING); - _ready = true; - ret = true; - } while (false); - - if (!ret) - { - _removeByAudioEngine = true; - } - - return ret; -} - -// rotateBufferThread is used to rotate alBufferData for _alSource when playing big audio file -void AudioPlayer::rotateBufferThread(int offsetFrame) -{ -#if defined(__APPLE__) - pthread_setname_np("ALStreaming"); -#endif - - char* tmpBuffer = nullptr; - auto& fullPath = _audioCache->_fileFullPath; - AudioDecoder* decoder = AudioDecoderManager::createDecoder(fullPath); - long long rotateSleepTime = static_cast(QUEUEBUFFER_TIME_STEP * 1000) / 2; - do - { - BREAK_IF(decoder == nullptr || !decoder->open(fullPath)); - - uint32_t framesRead = 0; - const uint32_t framesToRead = _audioCache->_queBufferFrames; - const uint32_t bufferSize = decoder->framesToBytes(framesToRead); -#if CC_USE_ALSOFT - const auto sourceFormat = decoder->getSourceFormat(); -#endif - tmpBuffer = (char*)malloc(bufferSize); - memset(tmpBuffer, 0, bufferSize); - - if (offsetFrame != 0) - { - decoder->seek(offsetFrame); - } - - ALint sourceState; - ALint bufferProcessed = 0; - bool needToExitThread = false; - - while (!_isDestroyed) - { - alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState); - if (sourceState == AL_PLAYING) - { - alGetSourcei(_alSource, AL_BUFFERS_PROCESSED, &bufferProcessed); - while (bufferProcessed > 0) - { - bufferProcessed--; - if (_timeDirty) - { - _timeDirty = false; - offsetFrame = _currTime * decoder->getSampleRate(); - decoder->seek(offsetFrame); - } - else - { - _currTime += QUEUEBUFFER_TIME_STEP; - if (_currTime > _audioCache->_duration) - { - if (_loop) - { - _currTime = 0.0f; - } - else - { - _currTime = _audioCache->_duration; - } - } - } - - framesRead = decoder->readFixedFrames(framesToRead, tmpBuffer); - - if (framesRead == 0) - { - if (_loop) - { - decoder->seek(0); - framesRead = decoder->readFixedFrames(framesToRead, tmpBuffer); - } - else - { - needToExitThread = true; - break; - } - } - /* - While the source is playing, alSourceUnqueueBuffers can be called to remove buffers which have - already played. Those buffers can then be filled with new data or discarded. New or refilled - buffers can then be attached to the playing source using alSourceQueueBuffers. As long as there is - always a new buffer to play in the queue, the source will continue to play. - */ - ALuint bid; - alSourceUnqueueBuffers(_alSource, 1, &bid); -#if CC_USE_ALSOFT - if (sourceFormat == AUDIO_SOURCE_FORMAT::ADPCM || sourceFormat == AUDIO_SOURCE_FORMAT::IMA_ADPCM) - alBufferi(bid, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, decoder->getSamplesPerBlock()); -#endif - alBufferData(bid, _audioCache->_format, tmpBuffer, decoder->framesToBytes(framesRead), - decoder->getSampleRate()); - alSourceQueueBuffers(_alSource, 1, &bid); - } - } - /* Make sure the source hasn't underrun */ - else if (sourceState != AL_PAUSED) - { - ALint queued; - - /* If no buffers are queued, playback is finished */ - alGetSourcei(_alSource, AL_BUFFERS_QUEUED, &queued); - if (queued == 0) - { - needToExitThread = true; - } - else - { - alSourcePlay(_alSource); - if (alGetError() != AL_NO_ERROR) - { - ALOGE("Error restarting playback!"); - needToExitThread = true; - } - } - } - - std::unique_lock lk(_sleepMutex); - if (_isDestroyed || needToExitThread) - { - break; - } -#if defined(__APPLE__) - if (!_needWakeupRotateThread) - { - _sleepCondition.wait_for(lk, std::chrono::milliseconds(rotateSleepTime)); - } - - _needWakeupRotateThread = false; -#else - _sleepCondition.wait_for(lk, std::chrono::milliseconds(rotateSleepTime)); -#endif - } - - } while (false); - - ALOGVV("Exit rotate buffer thread ..."); - if (decoder) - decoder->close(); - AudioDecoderManager::destroyDecoder(decoder); - free(tmpBuffer); - _isRotateThreadExited = true; -} - -#if defined(__APPLE__) -void AudioPlayer::wakeupRotateThread() -{ - _needWakeupRotateThread = true; - _sleepCondition.notify_all(); -} -#endif - -bool AudioPlayer::isFinished() const -{ - if (_streamingSource) - return _isRotateThreadExited; - else - { - ALint sourceState; - alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState); - return sourceState == AL_STOPPED; - } -} - -bool AudioPlayer::setLoop(bool loop) -{ - if (!_isDestroyed) - { - _loop = loop; - return true; - } - - return false; -} - -bool AudioPlayer::setTime(float time) -{ - if (!_isDestroyed && time >= 0.0f && time < _audioCache->_duration) - { - - _currTime = time; - _timeDirty = true; - - return true; - } - return false; -} diff --git a/core/audio/src/linux-link.cpp b/core/audio/src/linux-link.cpp deleted file mode 100644 index ba11dcfaa5..0000000000 --- a/core/audio/src/linux-link.cpp +++ /dev/null @@ -1,2 +0,0 @@ -/* linux-link.cpp: the workaround for solving clang link issue, said: unrefenreced "gnu_objc_personality_v0" */ -#include "AudioEngineImpl.mm" diff --git a/core/base/CCDirector.cpp b/core/base/CCDirector.cpp index 6ce1e09441..2836be2ab3 100644 --- a/core/base/CCDirector.cpp +++ b/core/base/CCDirector.cpp @@ -61,7 +61,7 @@ THE SOFTWARE. #include "base/ObjectFactory.h" #include "platform/CCApplication.h" #include "renderer/backend/ProgramCache.h" -#include "audio/include/AudioEngine.h" +#include "audio/AudioEngine.h" #if CC_ENABLE_SCRIPT_BINDING # include "base/CCScriptSupport.h" diff --git a/extensions/cocostudio/CCComAudio.cpp b/extensions/cocostudio/CCComAudio.cpp index c511abf3e6..545c90a814 100644 --- a/extensions/cocostudio/CCComAudio.cpp +++ b/extensions/cocostudio/CCComAudio.cpp @@ -23,7 +23,6 @@ THE SOFTWARE. ****************************************************************************/ #include "CCComAudio.h" -// #include "audio/include/SimpleAudioEngine.h" #include "platform/CCFileUtils.h" namespace cocostudio diff --git a/extensions/cocostudio/CCSSceneReader.cpp b/extensions/cocostudio/CCSSceneReader.cpp index 938f080b08..90a46d4249 100644 --- a/extensions/cocostudio/CCSSceneReader.cpp +++ b/extensions/cocostudio/CCSSceneReader.cpp @@ -25,7 +25,6 @@ THE SOFTWARE. #include "CocoStudio.h" #include "ui/CocosGUI.h" -// #include "audio/include/SimpleAudioEngine.h" #include "base/ObjectFactory.h" #include "base/ccUtils.h" #include "platform/CCFileUtils.h" diff --git a/extensions/scripting/lua-bindings/auto/lua_cocos2dx_audioengine_auto.cpp b/extensions/scripting/lua-bindings/auto/lua_cocos2dx_audioengine_auto.cpp index fbc51b0072..10585e205f 100644 --- a/extensions/scripting/lua-bindings/auto/lua_cocos2dx_audioengine_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/lua_cocos2dx_audioengine_auto.cpp @@ -1,6 +1,6 @@ #include "scripting/lua-bindings/auto/lua_cocos2dx_audioengine_auto.hpp" #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX -#include "audio/include/AudioEngine.h" +#include "audio/AudioEngine.h" #include "scripting/lua-bindings/manual/tolua_fix.h" #include "scripting/lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/manual/audioengine/lua_cocos2dx_audioengine_manual.cpp b/extensions/scripting/lua-bindings/manual/audioengine/lua_cocos2dx_audioengine_manual.cpp index a43793b275..a0492f63a9 100644 --- a/extensions/scripting/lua-bindings/manual/audioengine/lua_cocos2dx_audioengine_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/audioengine/lua_cocos2dx_audioengine_manual.cpp @@ -27,7 +27,7 @@ #include "scripting/lua-bindings/manual/tolua_fix.h" #include "scripting/lua-bindings/manual/LuaBasicConversions.h" #include "scripting/lua-bindings/manual/CCLuaEngine.h" -#include "audio/include/AudioEngine.h" +#include "audio/AudioEngine.h" static int lua_get_AudioProfile_name(lua_State* L) { diff --git a/templates/cpp-template-default/CMakeLists.txt b/templates/cpp-template-default/CMakeLists.txt index d99553fa31..fcffc73c08 100644 --- a/templates/cpp-template-default/CMakeLists.txt +++ b/templates/cpp-template-default/CMakeLists.txt @@ -143,7 +143,7 @@ endif() target_include_directories(${APP_NAME} PRIVATE Classes - PRIVATE ${ADXE_ROOT_PATH}/core/audio/include/ + PRIVATE ${ADXE_ROOT_PATH}/core/audio ) # mark app resources diff --git a/templates/cpp-template-default/Classes/AppDelegate.cpp b/templates/cpp-template-default/Classes/AppDelegate.cpp index 0119494ae1..84790c7464 100644 --- a/templates/cpp-template-default/Classes/AppDelegate.cpp +++ b/templates/cpp-template-default/Classes/AppDelegate.cpp @@ -29,7 +29,7 @@ #define USE_AUDIO_ENGINE 1 #if USE_AUDIO_ENGINE -# include "audio/include/AudioEngine.h" +# include "audio/AudioEngine.h" #endif USING_NS_CC; diff --git a/templates/lua-template-default/frameworks/runtime-src/Classes/AppDelegate.cpp b/templates/lua-template-default/frameworks/runtime-src/Classes/AppDelegate.cpp index abbab833fd..8d249c4dc8 100644 --- a/templates/lua-template-default/frameworks/runtime-src/Classes/AppDelegate.cpp +++ b/templates/lua-template-default/frameworks/runtime-src/Classes/AppDelegate.cpp @@ -31,7 +31,7 @@ #define USE_AUDIO_ENGINE 1 #if USE_AUDIO_ENGINE -# include "audio/include/AudioEngine.h" +# include "audio/AudioEngine.h" #endif USING_NS_CC; diff --git a/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h index f5f4e2fbff..7a095f263d 100644 --- a/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h +++ b/tests/cpp-tests/Classes/NewAudioEngineTest/NewAudioEngineTest.h @@ -32,7 +32,7 @@ # include "cocos2d.h" # include "../BaseTest.h" -# include "audio/include/AudioEngine.h" +# include "audio/AudioEngine.h" DEFINE_TEST_SUITE(AudioEngineTests); diff --git a/tests/cpp-tests/Classes/testBasic.h b/tests/cpp-tests/Classes/testBasic.h index 1907aa629d..8c9eeda9fd 100644 --- a/tests/cpp-tests/Classes/testBasic.h +++ b/tests/cpp-tests/Classes/testBasic.h @@ -26,7 +26,6 @@ #define _TEST_BASIC_H_ #include "cocos2d.h" -#include "audio/include/SimpleAudioEngine.h" #include "VisibleRect.h" /** diff --git a/tests/fairygui-tests/Classes/AppDelegate.cpp b/tests/fairygui-tests/Classes/AppDelegate.cpp index 1f08ae7aef..216f19bec6 100644 --- a/tests/fairygui-tests/Classes/AppDelegate.cpp +++ b/tests/fairygui-tests/Classes/AppDelegate.cpp @@ -1,20 +1,7 @@ #include "AppDelegate.h" #include "MenuScene.h" -// #define USE_AUDIO_ENGINE 1 -// #define USE_SIMPLE_AUDIO_ENGINE 1 - -#if USE_AUDIO_ENGINE && USE_SIMPLE_AUDIO_ENGINE -#error "Don't use AudioEngine and SimpleAudioEngine at the same time. Please just select one in your game!" -#endif - -#if USE_AUDIO_ENGINE -#include "audio/include/AudioEngine.h" -using namespace cocos2d::experimental; -#elif USE_SIMPLE_AUDIO_ENGINE -#include "audio/include/SimpleAudioEngine.h" -using namespace CocosDenshion; -#endif +#include "audio/AudioEngine.h" USING_NS_CC; @@ -29,11 +16,7 @@ AppDelegate::AppDelegate() AppDelegate::~AppDelegate() { -#if USE_AUDIO_ENGINE AudioEngine::end(); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::end(); -#endif } // if you want a different context, modify the value of glContextAttrs @@ -112,23 +95,11 @@ bool AppDelegate::applicationDidFinishLaunching() { // This function will be called when the app is inactive. Note, when receiving a phone call it is invoked. void AppDelegate::applicationDidEnterBackground() { Director::getInstance()->stopAnimation(); - -#if USE_AUDIO_ENGINE AudioEngine::pauseAll(); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->pauseBackgroundMusic(); - SimpleAudioEngine::getInstance()->pauseAllEffects(); -#endif } // this function will be called when the app is active again void AppDelegate::applicationWillEnterForeground() { Director::getInstance()->startAnimation(); - -#if USE_AUDIO_ENGINE AudioEngine::resumeAll(); -#elif USE_SIMPLE_AUDIO_ENGINE - SimpleAudioEngine::getInstance()->resumeBackgroundMusic(); - SimpleAudioEngine::getInstance()->resumeAllEffects(); -#endif } diff --git a/tools/tolua/cocos2dx_audioengine.ini b/tools/tolua/cocos2dx_audioengine.ini index 23bb8b4f7a..1e5134e4ec 100644 --- a/tools/tolua/cocos2dx_audioengine.ini +++ b/tools/tolua/cocos2dx_audioengine.ini @@ -26,7 +26,7 @@ cxxgenerator_headers = extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s %(extra_flags)s # what headers to parse -headers = %(adxedir)s/core/audio/include/AudioEngine.h +headers = %(adxedir)s/core/audio/AudioEngine.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$".