mirror of https://github.com/axmolengine/axmol.git
* fixed #10482: New AudioEngine class can't play large ogg file on Win32. * [win32] Small logic fix in AudioPlayer::readPcmData.
This commit is contained in:
parent
6eaf15a2c2
commit
cc9871b71d
|
@ -21,6 +21,9 @@
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define LOG_TAG "AudioCache"
|
||||||
|
|
||||||
#include "platform/CCPlatformConfig.h"
|
#include "platform/CCPlatformConfig.h"
|
||||||
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||||
|
@ -35,10 +38,68 @@
|
||||||
#include "base/CCDirector.h"
|
#include "base/CCDirector.h"
|
||||||
#include "base/CCScheduler.h"
|
#include "base/CCScheduler.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#define PCMDATA_CACHEMAXSIZE 2621440
|
#define PCMDATA_CACHEMAXSIZE 2621440
|
||||||
|
|
||||||
using namespace cocos2d::experimental;
|
using namespace cocos2d::experimental;
|
||||||
|
|
||||||
|
//FIXME: Move _winLog, winLog to a separated file
|
||||||
|
static void _winLog(const char *format, va_list args)
|
||||||
|
{
|
||||||
|
static const int MAX_LOG_LENGTH = 16 * 1024;
|
||||||
|
int bufferSize = MAX_LOG_LENGTH;
|
||||||
|
char* buf = nullptr;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buf = new (std::nothrow) char[bufferSize];
|
||||||
|
if (buf == nullptr)
|
||||||
|
return; // not enough memory
|
||||||
|
|
||||||
|
int ret = vsnprintf(buf, bufferSize - 3, format, args);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
bufferSize *= 2;
|
||||||
|
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
strcat(buf, "\n");
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
int len = strlen(buf);
|
||||||
|
char tempBuf[MAX_LOG_LENGTH + 1] = { 0 };
|
||||||
|
WCHAR wszBuf[MAX_LOG_LENGTH + 1] = { 0 };
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::copy(buf + pos, buf + pos + MAX_LOG_LENGTH, tempBuf);
|
||||||
|
|
||||||
|
tempBuf[MAX_LOG_LENGTH] = 0;
|
||||||
|
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, tempBuf, -1, wszBuf, sizeof(wszBuf));
|
||||||
|
OutputDebugStringW(wszBuf);
|
||||||
|
|
||||||
|
pos += MAX_LOG_LENGTH;
|
||||||
|
|
||||||
|
} while (pos < len);
|
||||||
|
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audioLog(const char * format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
_winLog(format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
AudioCache::AudioCache()
|
AudioCache::AudioCache()
|
||||||
: _pcmData(nullptr)
|
: _pcmData(nullptr)
|
||||||
, _pcmDataSize(0)
|
, _pcmDataSize(0)
|
||||||
|
@ -100,7 +161,7 @@ void AudioCache::readDataTask()
|
||||||
vf = new OggVorbis_File;
|
vf = new OggVorbis_File;
|
||||||
int openCode;
|
int openCode;
|
||||||
if (openCode = ov_fopen(FileUtils::getInstance()->getSuitableFOpen(_fileFullPath).c_str(), vf)){
|
if (openCode = ov_fopen(FileUtils::getInstance()->getSuitableFOpen(_fileFullPath).c_str(), vf)){
|
||||||
log("Input does not appear to be an Ogg bitstream: %s. Code: 0x%x\n", _fileFullPath.c_str(), openCode);
|
ALOGE("Input does not appear to be an Ogg bitstream: %s. Code: 0x%x\n", _fileFullPath.c_str(), openCode);
|
||||||
goto ExitThread;
|
goto ExitThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,13 +180,13 @@ void AudioCache::readDataTask()
|
||||||
int error = MPG123_OK;
|
int error = MPG123_OK;
|
||||||
mpg123handle = mpg123_new(nullptr, &error);
|
mpg123handle = mpg123_new(nullptr, &error);
|
||||||
if (!mpg123handle){
|
if (!mpg123handle){
|
||||||
log("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
|
ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
|
||||||
goto ExitThread;
|
goto ExitThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpg123_open(mpg123handle,_fileFullPath.c_str()) != MPG123_OK ||
|
if (mpg123_open(mpg123handle,_fileFullPath.c_str()) != MPG123_OK ||
|
||||||
mpg123_getformat(mpg123handle, &rate, &_channels, &_mp3Encoding) != MPG123_OK) {
|
mpg123_getformat(mpg123handle, &rate, &_channels, &_mp3Encoding) != MPG123_OK) {
|
||||||
log("Trouble with mpg123: %s\n", mpg123_strerror(mpg123handle) );
|
ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(mpg123handle) );
|
||||||
goto ExitThread;
|
goto ExitThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,38 @@
|
||||||
#define QUEUEBUFFER_NUM 5
|
#define QUEUEBUFFER_NUM 5
|
||||||
#define QUEUEBUFFER_TIME_STEP 0.1f
|
#define QUEUEBUFFER_TIME_STEP 0.1f
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//FIXME:Move the definition of the following macros to a separated file.
|
||||||
|
|
||||||
|
void audioLog(const char * format, ...);
|
||||||
|
|
||||||
|
#define QUOTEME_(x) #x
|
||||||
|
#define QUOTEME(x) QUOTEME_(x)
|
||||||
|
|
||||||
|
#if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG > 0
|
||||||
|
#define ALOGV(fmt, ...) audioLog("V/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define ALOGV(fmt, ...) do {} while(false)
|
||||||
|
#endif
|
||||||
|
#define ALOGD(fmt, ...) audioLog("D/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__)
|
||||||
|
#define ALOGI(fmt, ...) audioLog("I/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__)
|
||||||
|
#define ALOGW(fmt, ...) audioLog("W/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__)
|
||||||
|
#define ALOGE(fmt, ...) audioLog("E/" LOG_TAG " (" QUOTEME(__LINE__) "): " fmt "", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#if defined(COCOS2D_DEBUG) && COCOS2D_DEBUG > 0
|
||||||
|
#define CHECK_AL_ERROR_DEBUG() \
|
||||||
|
do { \
|
||||||
|
GLenum __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
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
namespace experimental{
|
namespace experimental{
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
#define LOG_TAG "AudioEngine-Win32"
|
||||||
|
|
||||||
#include "platform/CCPlatformConfig.h"
|
#include "platform/CCPlatformConfig.h"
|
||||||
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||||
|
@ -88,7 +90,7 @@ bool AudioEngineImpl::init()
|
||||||
alGenSources(MAX_AUDIOINSTANCES, _alSources);
|
alGenSources(MAX_AUDIOINSTANCES, _alSources);
|
||||||
alError = alGetError();
|
alError = alGetError();
|
||||||
if(alError != AL_NO_ERROR){
|
if(alError != AL_NO_ERROR){
|
||||||
log("%s:generating sources fail! error = %x\n", __FUNCTION__, alError);
|
ALOGE("%s:generating sources fail! error = %x\n", __FUNCTION__, alError);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,14 +142,14 @@ AudioCache* AudioEngineImpl::preload(const std::string& filePath, std::function<
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
|
ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log("Unsupported media type file: %s\n", filePath.c_str());
|
ALOGE("Unsupported media type file: %s\n", filePath.c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +247,7 @@ void AudioEngineImpl::setVolume(int audioID,float volume)
|
||||||
|
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
log("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
ALOGE("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,7 +268,7 @@ void AudioEngineImpl::setLoop(int audioID, bool loop)
|
||||||
|
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
log("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
ALOGE("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,7 +285,7 @@ bool AudioEngineImpl::pause(int audioID)
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
ret = false;
|
ret = false;
|
||||||
log("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
ALOGE("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -297,7 +299,7 @@ bool AudioEngineImpl::resume(int audioID)
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
ret = false;
|
ret = false;
|
||||||
log("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
ALOGE("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -313,7 +315,7 @@ bool AudioEngineImpl::stop(int audioID)
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
ret = false;
|
ret = false;
|
||||||
log("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
ALOGE("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +382,7 @@ float AudioEngineImpl::getCurrentTime(int audioID)
|
||||||
|
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
log("%s, audio id:%d,error code:%x", __FUNCTION__,audioID,error);
|
ALOGE("%s, audio id:%d,error code:%x", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,7 +409,7 @@ bool AudioEngineImpl::setCurrentTime(int audioID, float time)
|
||||||
|
|
||||||
auto error = alGetError();
|
auto error = alGetError();
|
||||||
if (error != AL_NO_ERROR) {
|
if (error != AL_NO_ERROR) {
|
||||||
log("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
ALOGE("%s: audio id = %d, error = %x\n", __FUNCTION__,audioID,error);
|
||||||
}
|
}
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define LOG_TAG "AudioPlayer"
|
||||||
|
|
||||||
#include "platform/CCPlatformConfig.h"
|
#include "platform/CCPlatformConfig.h"
|
||||||
|
|
||||||
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
|
||||||
|
@ -109,7 +112,7 @@ bool AudioPlayer::play2d(AudioCache* cache)
|
||||||
alSourceQueueBuffers(_alSource, QUEUEBUFFER_NUM, _bufferIds);
|
alSourceQueueBuffers(_alSource, QUEUEBUFFER_NUM, _bufferIds);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log("%s:alGenBuffers error code:%x", __FUNCTION__,alError);
|
ALOGE("%s:alGenBuffers error code:%x", __FUNCTION__,alError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +128,7 @@ bool AudioPlayer::play2d(AudioCache* cache)
|
||||||
|
|
||||||
auto alError = alGetError();
|
auto alError = alGetError();
|
||||||
if (alError != AL_NO_ERROR) {
|
if (alError != AL_NO_ERROR) {
|
||||||
log("%s:alSourcePlay error code:%x\n", __FUNCTION__, alError);
|
ALOGE("%s:alSourcePlay error code:%x\n", __FUNCTION__, alError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +138,26 @@ bool AudioPlayer::play2d(AudioCache* cache)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AudioPlayer::readPcmData(char* buffer, int bufferSize, const std::function<int/*readBytes*/(char* /*buf*/, int /*bytesToRead*/)>& fileReader)
|
||||||
|
{
|
||||||
|
assert(buffer != nullptr && bufferSize > 0);
|
||||||
|
|
||||||
|
int readBytes = 0;
|
||||||
|
int readBytesOnce = 0;
|
||||||
|
int remainBytes = bufferSize;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
readBytesOnce = fileReader(buffer + readBytes, remainBytes);
|
||||||
|
if (readBytesOnce > 0)
|
||||||
|
{
|
||||||
|
readBytes += readBytesOnce;
|
||||||
|
remainBytes -= readBytesOnce;
|
||||||
|
}
|
||||||
|
} while (readBytesOnce > 0 && readBytes < bufferSize);
|
||||||
|
|
||||||
|
return readBytes;
|
||||||
|
}
|
||||||
|
|
||||||
void AudioPlayer::rotateBufferThread(int offsetFrame)
|
void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
{
|
{
|
||||||
ALint sourceState;
|
ALint sourceState;
|
||||||
|
@ -142,6 +165,9 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
mpg123_handle* mpg123handle = nullptr;
|
mpg123_handle* mpg123handle = nullptr;
|
||||||
OggVorbis_File* vorbisFile = nullptr;
|
OggVorbis_File* vorbisFile = nullptr;
|
||||||
|
|
||||||
|
std::function<int(char*, int)> fileReader = nullptr;
|
||||||
|
std::function<void(int)> fileSeeker = nullptr;
|
||||||
|
|
||||||
auto audioFileFormat = _audioCache->_fileFormat;
|
auto audioFileFormat = _audioCache->_fileFormat;
|
||||||
char* tmpBuffer = (char*)malloc(_audioCache->_queBufferBytes);
|
char* tmpBuffer = (char*)malloc(_audioCache->_queBufferBytes);
|
||||||
|
|
||||||
|
@ -152,7 +178,7 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
int error = MPG123_OK;
|
int error = MPG123_OK;
|
||||||
mpg123handle = mpg123_new(nullptr, &error);
|
mpg123handle = mpg123_new(nullptr, &error);
|
||||||
if (!mpg123handle){
|
if (!mpg123handle){
|
||||||
log("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
|
ALOGE("Basic setup goes wrong: %s", mpg123_plain_strerror(error));
|
||||||
goto ExitBufferThread;
|
goto ExitBufferThread;
|
||||||
}
|
}
|
||||||
long rate = 0;
|
long rate = 0;
|
||||||
|
@ -160,7 +186,7 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
int mp3Encoding = 0;
|
int mp3Encoding = 0;
|
||||||
if (mpg123_open(mpg123handle,_audioCache->_fileFullPath.c_str()) != MPG123_OK
|
if (mpg123_open(mpg123handle,_audioCache->_fileFullPath.c_str()) != MPG123_OK
|
||||||
|| mpg123_getformat(mpg123handle, &rate, &channels, &mp3Encoding) != MPG123_OK){
|
|| mpg123_getformat(mpg123handle, &rate, &channels, &mp3Encoding) != MPG123_OK){
|
||||||
log("Trouble with mpg123: %s\n", mpg123_strerror(mpg123handle) );
|
ALOGE("Trouble with mpg123: %s\n", mpg123_strerror(mpg123handle) );
|
||||||
goto ExitBufferThread;
|
goto ExitBufferThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +204,7 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
vorbisFile = new OggVorbis_File;
|
vorbisFile = new OggVorbis_File;
|
||||||
int openCode;
|
int openCode;
|
||||||
if (openCode = ov_fopen(FileUtils::getInstance()->getSuitableFOpen(_audioCache->_fileFullPath).c_str(), vorbisFile)){
|
if (openCode = ov_fopen(FileUtils::getInstance()->getSuitableFOpen(_audioCache->_fileFullPath).c_str(), vorbisFile)){
|
||||||
log("Input does not appear to be an Ogg bitstream: %s. Code: 0x%x\n", _audioCache->_fileFullPath.c_str(), openCode);
|
ALOGE("Input does not appear to be an Ogg bitstream: %s. Code: 0x%x\n", _audioCache->_fileFullPath.c_str(), openCode);
|
||||||
goto ExitBufferThread;
|
goto ExitBufferThread;
|
||||||
}
|
}
|
||||||
if (offsetFrame != 0) {
|
if (offsetFrame != 0) {
|
||||||
|
@ -192,6 +218,30 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
|
|
||||||
alSourcePlay(_alSource);
|
alSourcePlay(_alSource);
|
||||||
|
|
||||||
|
if (audioFileFormat == AudioCache::FileFormat::MP3)
|
||||||
|
{
|
||||||
|
fileReader = [&](char* buffer, int bufferSize) -> int {
|
||||||
|
size_t ret = 0;
|
||||||
|
mpg123_read(mpg123handle, (unsigned char*)buffer, bufferSize, &ret);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSeeker = [&](int pos) {
|
||||||
|
mpg123_seek(mpg123handle, pos, SEEK_SET);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (audioFileFormat == AudioCache::FileFormat::OGG)
|
||||||
|
{
|
||||||
|
fileReader = [&](char* buffer, int bufferSize) -> int {
|
||||||
|
int current_section = 0;
|
||||||
|
return ov_read(vorbisFile, buffer, bufferSize, 0, 2, 1, ¤t_section);
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSeeker = [&](int pos) {
|
||||||
|
ov_pcm_seek(vorbisFile, pos);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
while (!_exitThread) {
|
while (!_exitThread) {
|
||||||
alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState);
|
alGetSourcei(_alSource, AL_SOURCE_STATE, &sourceState);
|
||||||
if (sourceState == AL_PLAYING) {
|
if (sourceState == AL_PLAYING) {
|
||||||
|
@ -203,18 +253,7 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
if (_timeDirty) {
|
if (_timeDirty) {
|
||||||
_timeDirty = false;
|
_timeDirty = false;
|
||||||
offsetFrame = _currTime * _audioCache->_sampleRate;
|
offsetFrame = _currTime * _audioCache->_sampleRate;
|
||||||
|
fileSeeker(offsetFrame);
|
||||||
switch (audioFileFormat)
|
|
||||||
{
|
|
||||||
case AudioCache::FileFormat::MP3:
|
|
||||||
mpg123_seek(mpg123handle,offsetFrame,SEEK_SET);
|
|
||||||
break;
|
|
||||||
case AudioCache::FileFormat::OGG:
|
|
||||||
ov_pcm_seek(vorbisFile,offsetFrame);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_currTime += QUEUEBUFFER_TIME_STEP;
|
_currTime += QUEUEBUFFER_TIME_STEP;
|
||||||
|
@ -227,49 +266,37 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readRet = 0;
|
int readRet = readPcmData(tmpBuffer, _audioCache->_queBufferBytes, fileReader);
|
||||||
if(audioFileFormat == AudioCache::FileFormat::MP3)
|
if (readRet <= 0) {
|
||||||
{
|
if (_loop) {
|
||||||
mpg123_read(mpg123handle,(unsigned char*)tmpBuffer, _audioCache->_queBufferBytes,&readRet);
|
fileSeeker(0);
|
||||||
if (readRet <= 0) {
|
readRet = readPcmData(tmpBuffer, _audioCache->_queBufferBytes, fileReader);
|
||||||
if (_loop) {
|
|
||||||
mpg123_seek(mpg123handle,0,SEEK_SET);
|
|
||||||
mpg123_read(mpg123handle,(unsigned char*)tmpBuffer, _audioCache->_queBufferBytes,&readRet);
|
|
||||||
} else {
|
|
||||||
_exitThread = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
_exitThread = true;
|
||||||
_audioCache->_bytesOfRead += readRet;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(audioFileFormat == AudioCache::FileFormat::OGG)
|
else
|
||||||
{
|
{
|
||||||
int current_section;
|
_audioCache->_bytesOfRead += readRet;
|
||||||
readRet = ov_read(vorbisFile,tmpBuffer,_audioCache->_queBufferBytes,0,2,1,¤t_section);
|
|
||||||
if (readRet <= 0) {
|
|
||||||
if (_loop) {
|
|
||||||
ov_pcm_seek(vorbisFile,0);
|
|
||||||
readRet = ov_read(vorbisFile,tmpBuffer,_audioCache->_queBufferBytes,0,2,1,¤t_section);
|
|
||||||
} else {
|
|
||||||
_exitThread = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ALOGV("readRet: %d, queBufferBytes: %d", (int)readRet, _audioCache->_queBufferBytes);
|
||||||
ALuint bid;
|
ALuint bid;
|
||||||
alSourceUnqueueBuffers(_alSource, 1, &bid);
|
alSourceUnqueueBuffers(_alSource, 1, &bid);
|
||||||
|
CHECK_AL_ERROR_DEBUG();
|
||||||
alBufferData(bid, _audioCache->_alBufferFormat, tmpBuffer, readRet, _audioCache->_sampleRate);
|
alBufferData(bid, _audioCache->_alBufferFormat, tmpBuffer, readRet, _audioCache->_sampleRate);
|
||||||
|
CHECK_AL_ERROR_DEBUG();
|
||||||
alSourceQueueBuffers(_alSource, 1, &bid);
|
alSourceQueueBuffers(_alSource, 1, &bid);
|
||||||
|
CHECK_AL_ERROR_DEBUG();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lk(_sleepMutex);
|
std::unique_lock<std::mutex> lk(_sleepMutex);
|
||||||
if (_exitThread)
|
if (_exitThread)
|
||||||
{
|
{
|
||||||
|
ALOGV("thread exit...");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +319,7 @@ ExitBufferThread:
|
||||||
}
|
}
|
||||||
free(tmpBuffer);
|
free(tmpBuffer);
|
||||||
_readForRemove = true;
|
_readForRemove = true;
|
||||||
|
ALOGV("%s exited.\n", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioPlayer::setLoop(bool loop)
|
bool AudioPlayer::setLoop(bool loop)
|
||||||
|
|
|
@ -61,7 +61,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void rotateBufferThread(int offsetFrame);
|
void rotateBufferThread(int offsetFrame);
|
||||||
bool play2d(AudioCache* cache);
|
bool play2d(AudioCache* cache);
|
||||||
|
int readPcmData(char* buffer, int bufferSize, const std::function<int/*readBytes*/(char* /*buf*/, int /*bytesToRead*/)>& fileReader);
|
||||||
|
|
||||||
AudioCache* _audioCache;
|
AudioCache* _audioCache;
|
||||||
|
|
||||||
float _volume;
|
float _volume;
|
||||||
|
|
|
@ -88,13 +88,13 @@ void MciPlayer::Open(const char* pFileName, UINT uId)
|
||||||
MCI_OPEN_PARMS mciOpen = {0};
|
MCI_OPEN_PARMS mciOpen = {0};
|
||||||
MCIERROR mciError;
|
MCIERROR mciError;
|
||||||
mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID;
|
mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID;
|
||||||
WCHAR* fileNameWideChar = new WCHAR[nLen + 1];
|
WCHAR* fileNameWideChar = new WCHAR[nLen + 1];
|
||||||
BREAK_IF(! fileNameWideChar);
|
BREAK_IF(! fileNameWideChar);
|
||||||
MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, fileNameWideChar, nLen + 1);
|
MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, fileNameWideChar, nLen + 1);
|
||||||
mciOpen.lpstrElementName = fileNameWideChar;
|
mciOpen.lpstrElementName = fileNameWideChar;
|
||||||
|
|
||||||
mciError = mciSendCommand(0,MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen));
|
mciError = mciSendCommand(0,MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen));
|
||||||
CC_SAFE_DELETE_ARRAY(mciOpen.lpstrElementName);
|
CC_SAFE_DELETE_ARRAY(mciOpen.lpstrElementName);
|
||||||
BREAK_IF(mciError);
|
BREAK_IF(mciError);
|
||||||
|
|
||||||
_dev = mciOpen.wDeviceID;
|
_dev = mciOpen.wDeviceID;
|
||||||
|
|
Loading…
Reference in New Issue