Files
cocos-engine/native/cocos/audio/android/AudioDecoderOgg.cpp
2017-01-09 17:50:30 +08:00

80 lines
2.2 KiB
C++

#include "audio/android/AudioDecoderOgg.h"
#include "platform/CCFileUtils.h"
#define LOG_TAG "AudioDecoderOgg"
namespace cocos2d { namespace experimental {
AudioDecoderOgg::AudioDecoderOgg()
{
ALOGV("Create AudioDecoderOgg");
}
AudioDecoderOgg::~AudioDecoderOgg()
{
}
int AudioDecoderOgg::fseek64Wrap(void* datasource, ogg_int64_t off, int whence)
{
return AudioDecoder::fileSeek(datasource, (long)off, whence);
}
bool AudioDecoderOgg::decodeToPcm()
{
_fileData = FileUtils::getInstance()->getDataFromFile(_url);
if (_fileData.isNull())
{
return false;
}
ov_callbacks callbacks;
callbacks.read_func = AudioDecoder::fileRead;
callbacks.seek_func = AudioDecoderOgg::fseek64Wrap;
callbacks.close_func = AudioDecoder::fileClose;
callbacks.tell_func = AudioDecoder::fileTell;
_fileCurrPos = 0;
OggVorbis_File vf;
int ret = ov_open_callbacks(this, &vf, NULL, 0, callbacks);
if (ret != 0)
{
ALOGE("Open file error, file: %s, ov_open_callbacks return %d", _url.c_str(), ret);
return false;
}
// header
auto vi = ov_info(&vf, -1);
uint32_t uiPCMSamples = (uint32_t) ov_pcm_total(&vf, -1);
uint32_t bufferSize = uiPCMSamples * vi->channels * sizeof(short);
char* pvPCMBuffer = (char*)malloc(bufferSize);
memset(pvPCMBuffer, 0, bufferSize);
int current_section = 0;
int uiCurrPos = 0;
long iRead = 0;
// decode
do {
iRead = ov_read(&vf, pvPCMBuffer + uiCurrPos, 4096, &current_section);
uiCurrPos += (unsigned int) iRead;
} while (iRead != 0);
_result.pcmBuffer->insert(_result.pcmBuffer->end(), pvPCMBuffer, pvPCMBuffer + bufferSize);
_result.numChannels = vi->channels;
_result.sampleRate = vi->rate;
_result.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
_result.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
_result.channelMask = vi->channels == 1 ? SL_SPEAKER_FRONT_CENTER : (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
_result.endianness = SL_BYTEORDER_LITTLEENDIAN;
_result.numFrames = uiPCMSamples;
_result.duration = 1.0f * uiPCMSamples / vi->rate;
ov_clear(&vf);
free(pvPCMBuffer);
return true;
}
}} // namespace cocos2d { namespace experimental {