no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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/common/decoder/AudioDecoder.h"
#include <cstdint>
#include <cstring>
#include "audio/include/AudioMacros.h"
#include "platform/FileUtils.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "AudioDecoder"
namespace cc {
AudioDecoder::AudioDecoder()
: _isOpened(false) {}
AudioDecoder::~AudioDecoder() = default;
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 + framesRead * _pcmHeader.bytesPerFrame);
framesRead += framesReadOnce;
} while (framesReadOnce != 0 && framesRead < framesToRead);
if (framesRead < framesToRead) {
memset(pcmBuf + framesRead * _pcmHeader.bytesPerFrame, 0x00, (framesToRead - framesRead) * _pcmHeader.bytesPerFrame);
}
return framesRead;
}
uint32_t AudioDecoder::getTotalFrames() const {
return _pcmHeader.totalFrames;
}
uint32_t AudioDecoder::getBytesPerFrame() const {
return _pcmHeader.bytesPerFrame;
}
uint32_t AudioDecoder::getSampleRate() const {
return _pcmHeader.sampleRate;
}
uint32_t AudioDecoder::getChannelCount() const {
return _pcmHeader.channelCount;
}
AudioDataFormat AudioDecoder::getDataFormat() const {
return _pcmHeader.dataFormat;
}
PCMHeader AudioDecoder::getPCMHeader() const {
return _pcmHeader;
}
} // namespace cc

View File

@@ -0,0 +1,130 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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 <cstdint>
#include <functional>
#include "audio/include/AudioDef.h"
#if CC_PLATFORM == CC_PLATFORM_WINDOWS
#include "vorbis/vorbisfile.h"
#elif CC_PLATFORM == CC_PLATFORM_LINUX || CC_PLATFORM == CC_PLATFORM_QNX
#include "vorbis/vorbisfile.h"
#elif CC_PLATFORM == CC_PLATFORM_OHOS
#include "ivorbisfile.h"
#endif
namespace cc {
/**
* @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(const char *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| * _bytesPerFrame.
* @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| * _bytesPerFrame.
* @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;
/**
* @brief Tells the current frame offset.
* @return The current frame offset.
*/
virtual uint32_t tell() const = 0;
/** Gets total frames of current audio.*/
virtual uint32_t getTotalFrames() const;
/** Gets bytes per frame of current audio.*/
virtual uint32_t getBytesPerFrame() 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;
virtual AudioDataFormat getDataFormat() const;
virtual PCMHeader getPCMHeader() const;
protected:
AudioDecoder();
virtual ~AudioDecoder();
bool _isOpened;
PCMHeader _pcmHeader;
void *_fsHooks = nullptr;
friend class AudioDecoderManager;
};
} // namespace cc

View File

@@ -0,0 +1,68 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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/common/decoder/AudioDecoderManager.h"
#include "audio/common/decoder/AudioDecoderMp3.h"
#include "audio/common/decoder/AudioDecoderOgg.h"
#include "audio/common/decoder/AudioDecoderWav.h"
#include "audio/include/AudioMacros.h"
#include "base/memory/Memory.h"
#include "platform/FileUtils.h"
namespace cc {
bool AudioDecoderManager::init() {
return true;
}
void AudioDecoderManager::destroy() {
AudioDecoderMp3::destroy();
}
AudioDecoder *AudioDecoderManager::createDecoder(const char *path) {
ccstd::string suffix = FileUtils::getInstance()->getFileExtension(path);
if (suffix == ".ogg") {
return ccnew AudioDecoderOgg();
}
if (suffix == ".mp3") {
return ccnew AudioDecoderMp3();
}
#if CC_PLATFORM == CC_PLATFORM_OHOS || CC_PLATFORM == CC_PLATFORM_WINDOWS
if (suffix == ".wav") {
return ccnew AudioDecoderWav();
}
#endif
return nullptr;
}
void AudioDecoderManager::destroyDecoder(AudioDecoder *decoder) {
delete decoder;
}
} // namespace cc

View File

@@ -0,0 +1,40 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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
namespace cc {
class AudioDecoder;
class AudioDecoderManager {
public:
static bool init();
static void destroy();
static AudioDecoder *createDecoder(const char *path);
static void destroyDecoder(AudioDecoder *decoder);
};
} // namespace cc

View File

@@ -0,0 +1,179 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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/common/decoder/AudioDecoderMp3.h"
#include <malloc.h>
#include <cstdint>
#include "audio/include/AudioMacros.h"
#include "platform/FileUtils.h"
#if CC_PLATFORM == CC_PLATFORM_WINDOWS || CC_PLATFORM == CC_PLATFORM_LINUX || CC_PLATFORM == CC_PLATFORM_QNX
#include "mpg123/mpg123.h"
#elif CC_PLATFORM == CC_PLATFORM_OHOS
#include <unistd.h>
#include "cocos/platform/ohos/FileUtils-ohos.h"
#include "mpg123.h"
#endif
#include <sys/stat.h>
#include <cstdlib>
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "AudioDecoderMp3"
namespace cc {
static bool sMp3Inited = false;
bool AudioDecoderMp3::lazyInit() {
bool ret = true;
if (!sMp3Inited) {
int error = mpg123_init();
if (error == MPG123_OK) {
sMp3Inited = true;
} else {
ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
ret = false;
}
}
return ret;
}
void AudioDecoderMp3::destroy() {
if (sMp3Inited) {
mpg123_exit();
sMp3Inited = false;
}
}
AudioDecoderMp3::AudioDecoderMp3() {
lazyInit();
}
AudioDecoderMp3::~AudioDecoderMp3() {
close();
}
bool AudioDecoderMp3::open(const char *path) {
ccstd::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
long rate = 0; //NOLINT(google-runtime-int)
int error = MPG123_OK;
int mp3Encoding = 0;
int channel = 0;
do {
_mpg123handle = mpg123_new(nullptr, &error);
if (nullptr == _mpg123handle) {
ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
break;
}
#if CC_PLATFORM_OHOS == CC_PLATFORM
auto *fu = static_cast<FileUtilsOHOS *>(FileUtils::getInstance());
_fdAndDeleter = fu->getFd(fullPath);
if (mpg123_open_fd(_mpg123handle, _fdAndDeleter.first) != MPG123_OK || mpg123_getformat(_mpg123handle, &rate, &channel, &mp3Encoding) != MPG123_OK) {
#else
if (mpg123_open(_mpg123handle, FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str()) != MPG123_OK || mpg123_getformat(_mpg123handle, &rate, &channel, &mp3Encoding) != MPG123_OK) {
#endif
ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(_mpg123handle));
break;
}
_pcmHeader.channelCount = channel;
_pcmHeader.sampleRate = rate;
if (mp3Encoding == MPG123_ENC_SIGNED_16) {
_pcmHeader.bytesPerFrame = 2 * _pcmHeader.channelCount;
_pcmHeader.dataFormat = AudioDataFormat::SIGNED_16;
} else if (mp3Encoding == MPG123_ENC_FLOAT_32) {
_pcmHeader.bytesPerFrame = 4 * _pcmHeader.channelCount;
_pcmHeader.dataFormat = AudioDataFormat::FLOAT_32;
} 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(_mpg123handle);
mpg123_format(_mpg123handle, rate, channel, mp3Encoding);
/* Ensure that we can get accurate length by call mpg123_length */
mpg123_scan(_mpg123handle);
_pcmHeader.totalFrames = mpg123_length(_mpg123handle);
_isOpened = true;
return true;
} while (false);
if (_mpg123handle != nullptr) {
mpg123_close(_mpg123handle);
mpg123_delete(_mpg123handle);
_mpg123handle = nullptr;
}
return false;
}
void AudioDecoderMp3::close() {
if (isOpened()) {
if (_mpg123handle != nullptr) {
mpg123_close(_mpg123handle);
mpg123_delete(_mpg123handle);
_mpg123handle = nullptr;
}
_isOpened = false;
}
#if CC_PLATFORM_OHOS == CC_PLATFORM
if (_fdAndDeleter.second) {
_fdAndDeleter.second();
_fdAndDeleter.second = nullptr;
}
#endif
}
uint32_t AudioDecoderMp3::read(uint32_t framesToRead, char *pcmBuf) {
size_t bytesToRead = framesToRead * _pcmHeader.bytesPerFrame;
size_t bytesRead = 0;
int err = mpg123_read(_mpg123handle, reinterpret_cast<unsigned char *>(pcmBuf), bytesToRead, &bytesRead);
if (err == MPG123_ERR) {
ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(_mpg123handle));
return 0;
}
return static_cast<uint32_t>(bytesRead / _pcmHeader.bytesPerFrame);
}
bool AudioDecoderMp3::seek(uint32_t frameOffset) {
off_t offset = mpg123_seek(_mpg123handle, frameOffset, SEEK_SET);
//ALOGD("mpg123_seek return: %d", (int)offset);
return offset >= 0 && offset == frameOffset;
}
uint32_t AudioDecoderMp3::tell() const {
return static_cast<uint32_t>(mpg123_tell(_mpg123handle));
}
} // namespace cc

View File

@@ -0,0 +1,90 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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/common/decoder/AudioDecoder.h"
#include <functional>
struct mpg123_handle_struct;
namespace cc {
/**
* @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(const char *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| * _bytesPerFrame.
* @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;
/**
* @brief Tells the current frame offset.
* @return The current frame offset.
*/
uint32_t tell() const override;
protected:
AudioDecoderMp3();
~AudioDecoderMp3() override;
static bool lazyInit();
static void destroy();
struct mpg123_handle_struct *_mpg123handle = nullptr;
#if CC_PLATFORM_OHOS == CC_PLATFORM
std::pair<int, std::function<void()>> _fdAndDeleter;
#endif
friend class AudioDecoderManager;
};
} // namespace cc

View File

@@ -0,0 +1,112 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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/common/decoder/AudioDecoderOgg.h"
#include <cstdint>
#include "audio/include/AudioMacros.h"
#include "platform/FileUtils.h"
#if CC_PLATFORM == CC_PLATFORM_OHOS
#include "audio/ohos/FsCallback.h"
namespace {
int ohosSeek_wrap(void *source, ogg_int64_t offset, int whence) { //NOLINT
return cc::ohosSeek(source, static_cast<long>(offset), whence); //NOLINT
}
ov_callbacks ogg_callbacks = { //NOLINT
static_cast<size_t (*)(void *, size_t, size_t, void *)>(cc::ohosRead),
static_cast<int (*)(void *, ogg_int64_t, int)>(ohosSeek_wrap),
static_cast<int (*)(void *)>(cc::ohosClose),
static_cast<long (*)(void *)>(cc::ohosTell)}; //NOLINT
} // namespace
#endif
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "AudioDecoderOgg"
namespace cc {
AudioDecoderOgg::AudioDecoderOgg() = default;
AudioDecoderOgg::~AudioDecoderOgg() {
close();
}
bool AudioDecoderOgg::open(const char *path) {
ccstd::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
#if CC_PLATFORM == CC_PLATFORM_WINDOWS
if (0 == ov_fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), &_vf)) {
#elif CC_PLATFORM == CC_PLATFORM_LINUX || CC_PLATFORM == CC_PLATFORM_QNX
if (0 == ov_fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), &_vf)) {
#elif CC_PLATFORM == CC_PLATFORM_OHOS
auto *fp = cc::ohosOpen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), this);
if (0 == ov_open_callbacks(fp, &_vf, nullptr, 0, ogg_callbacks)) {
#endif
// header
vorbis_info *vi = ov_info(&_vf, -1);
_pcmHeader.sampleRate = static_cast<uint32_t>(vi->rate);
_pcmHeader.channelCount = vi->channels;
_pcmHeader.bytesPerFrame = vi->channels * sizeof(int16_t);
_pcmHeader.dataFormat = AudioDataFormat::SIGNED_16;
_pcmHeader.totalFrames = static_cast<uint32_t>(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;
auto bytesToRead = framesToRead * _pcmHeader.bytesPerFrame;
#if CC_PLATFORM == CC_PLATFORM_WINDOWS
auto bytesRead = ov_read(&_vf, pcmBuf, bytesToRead, 0, 2, 1, &currentSection);
#elif CC_PLATFORM == CC_PLATFORM_OHOS
int bitstream = 0;
auto bytesRead = ov_read(&_vf, pcmBuf, bytesToRead, &bitstream);
#elif CC_PLATFORM == CC_PLATFORM_LINUX || CC_PLATFORM == CC_PLATFORM_QNX
auto bytesRead = ov_read(&_vf, pcmBuf, bytesToRead, 0, 2, 1, &currentSection);
#endif
return static_cast<uint32_t>(bytesRead / _pcmHeader.bytesPerFrame);
}
bool AudioDecoderOgg::seek(uint32_t frameOffset) {
return 0 == ov_pcm_seek(&_vf, frameOffset);
}
uint32_t AudioDecoderOgg::tell() const {
return static_cast<uint32_t>(ov_pcm_tell(const_cast<OggVorbis_File *>(&_vf)));
}
} // namespace cc

View File

@@ -0,0 +1,85 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
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/common/decoder/AudioDecoder.h"
#if CC_PLATFORM == CC_PLATFORM_WINDOWS
#include "vorbis/vorbisfile.h"
#elif CC_PLATFORM == CC_PLATFORM_OHOS
#include "ivorbisfile.h"
#endif
namespace cc {
/**
* @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(const char *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| * _bytesPerFrame.
* @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;
/**
* @brief Tells the current frame offset.
* @return The current frame offset.
*/
uint32_t tell() const override;
protected:
AudioDecoderOgg();
~AudioDecoderOgg() override;
OggVorbis_File _vf;
friend class AudioDecoderManager;
};
} // namespace cc

View File

@@ -0,0 +1,94 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
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.
****************************************************************************/
#define LOG_TAG "AudioDecoderWav"
#include "audio/common/decoder/AudioDecoderWav.h"
#include "base/Log.h"
#include "platform/FileUtils.h"
namespace cc {
AudioDecoderWav::AudioDecoderWav() {
CC_LOG_DEBUG("Create AudioDecoderWav");
}
AudioDecoderWav::~AudioDecoderWav() {
close();
};
bool AudioDecoderWav::open(const char *path) {
bool ret{false};
auto fullPath = FileUtils::getInstance()->fullPathForFilename(path);
if (fullPath.empty()) {
CC_LOG_DEBUG("File does not exist %s", fullPath.c_str());
return false;
}
do {
sf::SF_INFO info;
_sf_handle = sf::sf_open_read(fullPath.c_str(), &info, nullptr, nullptr);
if (_sf_handle == nullptr) {
CC_LOG_ERROR("file %s open failed, it might be invalid", fullPath.c_str());
break;
}
if (info.frames == 0) {
CC_LOG_ERROR("file %s has no frame, is it an invalid wav file?", fullPath.c_str());
break;
}
CC_LOG_DEBUG("wav info: frames: %d, samplerate: %d, channels: %d, format: %d", info.frames, info.samplerate, info.channels, info.format);
_pcmHeader.channelCount = info.channels;
_pcmHeader.bytesPerFrame = 2 * info.channels; // FIXED_16
_pcmHeader.dataFormat = AudioDataFormat::SIGNED_16; //FIXED,
_pcmHeader.sampleRate = info.samplerate;
_pcmHeader.totalFrames = info.frames;
_isOpened = true;
ret = true;
} while (false);
return ret;
}
uint32_t AudioDecoderWav::read(uint32_t framesToRead, char *pcmBuf) {
//size_t bytesToRead = framesToRead * _pcmHeader.bytesPerFrame;
size_t framesRead = sf::sf_readf_short(_sf_handle, reinterpret_cast<int16_t *>(pcmBuf), framesToRead);
return framesRead;
}
bool AudioDecoderWav::seek(uint32_t frameOffset) {
auto offset = sf::sf_seek(_sf_handle, frameOffset, SEEK_SET);
return offset >= 0 && offset == frameOffset;
}
uint32_t AudioDecoderWav::tell() const {
return static_cast<uint32_t>(sf::sf_tell(_sf_handle));
}
void AudioDecoderWav::close() {
if (_isOpened) {
if (_sf_handle) {
sf::sf_close(_sf_handle);
}
_isOpened = false;
}
}
} // namespace cc

View File

@@ -0,0 +1,76 @@
/****************************************************************************
Copyright (c) 2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
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 "audio/common/decoder/AudioDecoder.h"
#include "audio/common/utils/include/tinysndfile.h"
namespace cc {
class AudioDecoderWav : public AudioDecoder {
public:
/**
* @brief Opens an audio file specified by a file path.
* @return true if succeed, otherwise false.
*/
bool open(const char *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| * _bytesPerFrame.
* @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;
/**
* @brief Tells the current frame offset.
* @return The current frame offset.
*/
uint32_t tell() const override;
protected:
AudioDecoderWav();
~AudioDecoderWav() override;
sf::SNDFILE *_sf_handle{nullptr};
friend class AudioDecoderManager;
};
} // namespace cc