2011-11-28 18:05:38 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
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.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2011-10-14 18:33:14 +08:00
|
|
|
#include "CCAudioOut.h"
|
2011-10-14 17:57:44 +08:00
|
|
|
#include <stdio.h>
|
2011-10-18 09:45:04 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <FSystem.h>
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-29 14:47:13 +08:00
|
|
|
#define OGG_SUPPORT
|
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
#ifdef OGG_SUPPORT
|
2011-10-29 14:47:13 +08:00
|
|
|
#include "vorbis/vorbisfile.h"
|
2011-10-18 18:10:53 +08:00
|
|
|
#endif
|
|
|
|
|
2011-10-14 17:57:44 +08:00
|
|
|
using namespace Osp::Base;
|
|
|
|
using namespace Osp::Base::Collection;
|
|
|
|
using namespace Osp::Media;
|
2011-10-18 09:45:04 +08:00
|
|
|
using namespace Osp::Io;
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
namespace CocosDenshion {
|
|
|
|
|
|
|
|
#define PRE_BUFFERING_NUM 2
|
|
|
|
#define DEFAULT_VOLUME_LEVEL 5
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-14 18:33:14 +08:00
|
|
|
typedef struct wave_tag
|
|
|
|
{
|
|
|
|
char ChunkID[5];
|
|
|
|
unsigned long int ChunkSize;
|
|
|
|
char Format[5];
|
|
|
|
char SubChunk1ID[5];
|
|
|
|
unsigned long int SubChunk1Size;
|
|
|
|
unsigned short int AudioFormat;
|
|
|
|
unsigned short int NumChannels;
|
|
|
|
unsigned long int SampleRate;
|
|
|
|
unsigned long int ByteRate;
|
|
|
|
unsigned short int BlockAlign;
|
|
|
|
unsigned short int BitsPerSample;
|
|
|
|
char SubChunk2ID[5];
|
|
|
|
unsigned long int SubChunk2Size;
|
|
|
|
}WAVE;
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
static void GetWaveHeadInfo(File* pFile, WAVE& outWavHead)
|
2011-10-14 18:33:14 +08:00
|
|
|
{
|
|
|
|
char szTmp[100] = {0};
|
|
|
|
int i = 0;
|
2011-10-18 09:45:04 +08:00
|
|
|
memset(&outWavHead, 0, sizeof(WAVE));
|
|
|
|
pFile->Read(outWavHead.ChunkID, 4);
|
|
|
|
pFile->Read(&(outWavHead.ChunkSize),4);
|
|
|
|
pFile->Read(outWavHead.Format, 4);
|
|
|
|
pFile->Read(outWavHead.SubChunk1ID, 4);
|
|
|
|
pFile->Read(&(outWavHead.SubChunk1Size), 4);
|
|
|
|
pFile->Read(&(outWavHead.AudioFormat), 2);
|
|
|
|
pFile->Read(&(outWavHead.NumChannels), 2);
|
|
|
|
pFile->Read(&(outWavHead.SampleRate), 4);
|
|
|
|
pFile->Read(&(outWavHead.ByteRate), 4);
|
|
|
|
pFile->Read(&(outWavHead.BlockAlign), 2);
|
|
|
|
pFile->Read(&(outWavHead.BitsPerSample), 2);
|
|
|
|
|
|
|
|
pFile->Seek(FILESEEKPOSITION_BEGIN, 0);
|
|
|
|
pFile->Read(szTmp, 64);
|
2011-10-14 18:33:14 +08:00
|
|
|
|
|
|
|
for (i = 0; i <= 60; i++)
|
|
|
|
{
|
|
|
|
if (szTmp[i] == 'd' && szTmp[i+1] == 'a' && szTmp[i+2] == 't' && szTmp[i+3] == 'a')
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
pFile->Seek(FILESEEKPOSITION_BEGIN, i);
|
|
|
|
pFile->Read(outWavHead.SubChunk2ID, 4);
|
|
|
|
pFile->Read(&(outWavHead.SubChunk2Size), 4);
|
|
|
|
}
|
2011-10-14 18:33:14 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
int CCAudioOut::DecodeOgg(const char *infile)
|
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
#ifdef OGG_SUPPORT
|
2011-10-18 09:45:04 +08:00
|
|
|
FILE *in=NULL;
|
|
|
|
OggVorbis_File vf;
|
|
|
|
int bs = 0;
|
|
|
|
char buf[8192];
|
|
|
|
int buflen = 8192;
|
|
|
|
unsigned int written = 0;
|
|
|
|
int ret;
|
|
|
|
ogg_int64_t length = 0;
|
|
|
|
ogg_int64_t done = 0;
|
|
|
|
int size;
|
|
|
|
int seekable = 0;
|
|
|
|
int percent = 0;
|
|
|
|
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter, %s", infile);
|
2011-10-18 09:45:04 +08:00
|
|
|
in = fopen(infile, "rb");
|
|
|
|
if(!in) {
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("ERROR: Failed to open input file:\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
if(ov_open(in, &vf, NULL, 0) < 0) {
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("ERROR: Failed to open input as vorbis\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
fclose(in);
|
|
|
|
// fclose(out);
|
|
|
|
return 1;
|
|
|
|
}
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
if(ov_seekable(&vf)) {
|
|
|
|
seekable = 1;
|
|
|
|
length = ov_pcm_total(&vf, 0);
|
2011-11-28 15:49:37 +08:00
|
|
|
size = 16/8 * ov_info(&vf, 0)->channels;
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
if (ov_info(&vf,0)->channels == 2)
|
|
|
|
{
|
|
|
|
__sampleChannelType = AUDIO_CHANNEL_TYPE_STEREO;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__sampleChannelType = AUDIO_CHANNEL_TYPE_MONO;
|
|
|
|
}
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
__sampleRate = ov_info(&vf,0)->rate;
|
|
|
|
__sampleBitdepth = AUDIO_TYPE_PCM_S16_LE;
|
|
|
|
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-11-28 15:49:37 +08:00
|
|
|
while((ret = ov_read(&vf, buf, buflen, 0, 16/8, 1, &bs)) != 0) {
|
2011-10-18 09:45:04 +08:00
|
|
|
if(bs != 0) {
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("Only one logical bitstream currently supported\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-11-28 15:49:37 +08:00
|
|
|
if(ret < 0) {
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("Warning: hole in data\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (__pAllPcmBuffer == null)
|
|
|
|
{
|
|
|
|
__pAllPcmBuffer = (char*)malloc(ret);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__pAllPcmBuffer = (char*)realloc(__pAllPcmBuffer, written+ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(__pAllPcmBuffer+written, buf, ret);
|
|
|
|
|
|
|
|
written += ret;
|
2011-11-28 15:49:37 +08:00
|
|
|
if(seekable) {
|
2011-10-18 09:45:04 +08:00
|
|
|
done += ret/size;
|
|
|
|
if((double)done/(double)length * 200. > (double)percent) {
|
|
|
|
percent = (double)done/(double)length *200;
|
2011-11-13 00:57:54 +08:00
|
|
|
// //AppLog("[%5.1f%%]", (double)percent/2.);
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
__iAllPcmBufferSize = written;
|
|
|
|
|
|
|
|
// if(seekable && !quiet)
|
2011-11-13 00:57:54 +08:00
|
|
|
// //AppLog("\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
|
|
|
|
// if(!raw)
|
|
|
|
// rewrite_header(out, written); /* We don't care if it fails, too late */
|
|
|
|
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
ov_clear(&vf);
|
|
|
|
fclose(in);
|
|
|
|
// fclose(out);
|
2011-10-18 18:10:53 +08:00
|
|
|
#endif
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
return 0;
|
2011-10-14 18:33:14 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
|
|
|
|
CCAudioOut::CCAudioOut()
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("Enter");
|
2011-10-18 18:10:53 +08:00
|
|
|
__volumeLevel = -1;
|
2011-10-18 09:45:04 +08:00
|
|
|
__pAllPcmBuffer = null;
|
|
|
|
__iAllPcmBufferSize = 0;
|
|
|
|
__iAllPcmPos = 0;
|
2011-10-21 09:50:30 +08:00
|
|
|
__pAudioOut = null;
|
2011-10-18 09:45:04 +08:00
|
|
|
__iFileType = 0;
|
|
|
|
__pFile = null;
|
2011-10-18 18:10:53 +08:00
|
|
|
__bShortPcmBuffer = false;
|
|
|
|
__bBufferConstruted = false;
|
|
|
|
__checkInitFiniPair = false;
|
|
|
|
__iUsedBufferCount = 0;
|
2011-11-28 15:49:37 +08:00
|
|
|
__bLoop = false;
|
|
|
|
__bPause = false;
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
CCAudioOut::~CCAudioOut()
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("Enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
Finalize();
|
|
|
|
if(__pAudioOut)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
|
|
|
delete __pAudioOut;
|
|
|
|
__pAudioOut = null;
|
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
|
|
|
|
if (__pAllPcmBuffer)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 09:45:04 +08:00
|
|
|
free(__pAllPcmBuffer);
|
|
|
|
__pAllPcmBuffer = null;
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
result CCAudioOut::Initialize(const char* pszFilePath)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("Enter");
|
2011-10-18 09:45:04 +08:00
|
|
|
// This is called when AudioOut form is moving on the foreground.
|
|
|
|
result r = E_SUCCESS;
|
2011-10-18 18:10:53 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
__pAllPcmBuffer = null;
|
|
|
|
__iAllPcmBufferSize = 0;
|
|
|
|
__iAllPcmPos = 0;
|
2011-10-18 18:10:53 +08:00
|
|
|
__iUsedBufferCount = 0;
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
if(__checkInitFiniPair == false)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 09:45:04 +08:00
|
|
|
// Reset the configure variables
|
|
|
|
__finishChecker =0;
|
|
|
|
__bufWrittenCnt = PRE_BUFFERING_NUM;
|
|
|
|
__buffReadCnt = 0;
|
|
|
|
__buffWriteCnt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
result r = E_FAILURE;
|
|
|
|
if (__pAudioOut == NULL)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 09:45:04 +08:00
|
|
|
__pAudioOut = new AudioOut();
|
|
|
|
if (!__pAudioOut)
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[E_OUT_OF_MEMORY] m_pAudio new failed\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = __pAudioOut->Construct(*this);
|
|
|
|
if (IsFailed(r))
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.Construct failed");
|
2011-10-18 09:45:04 +08:00
|
|
|
return r;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] __pAudioOut is already existed\n");
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
String strFile(pszFilePath);
|
|
|
|
if (strFile.EndsWith(".wav"))
|
|
|
|
{
|
|
|
|
__iFileType = 0;
|
|
|
|
// Construct File for feeding buffers
|
|
|
|
__pFile = new File();
|
|
|
|
if(!__pFile)
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] __pFile new failed\n");
|
2011-10-18 09:45:04 +08:00
|
|
|
return E_SYSTEM;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
r = __pFile->Construct(pszFilePath, L"rb");
|
|
|
|
if (IsFailed(r)) {
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] __pFile.Construct failed : %d \n", r);
|
2011-10-18 09:45:04 +08:00
|
|
|
return r;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
WAVE wavHead;
|
|
|
|
GetWaveHeadInfo(__pFile, wavHead);
|
2011-10-18 18:10:53 +08:00
|
|
|
__iAllPcmBufferSize = wavHead.SubChunk2Size;
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
if (wavHead.BitsPerSample == 8)
|
|
|
|
{
|
|
|
|
__sampleBitdepth = AUDIO_TYPE_PCM_U8;
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
else if (wavHead.BitsPerSample == 16)
|
|
|
|
{
|
|
|
|
__sampleBitdepth = AUDIO_TYPE_PCM_S16_LE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__sampleBitdepth = AUDIO_TYPE_NONE;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
if (wavHead.NumChannels == 1)
|
|
|
|
{
|
|
|
|
__sampleChannelType = AUDIO_CHANNEL_TYPE_MONO;
|
|
|
|
}
|
|
|
|
else if (wavHead.NumChannels == 2)
|
|
|
|
{
|
|
|
|
__sampleChannelType = AUDIO_CHANNEL_TYPE_STEREO;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__sampleChannelType = AUDIO_CHANNEL_TYPE_NONE;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
__sampleRate = wavHead.SampleRate;
|
2011-10-18 18:10:53 +08:00
|
|
|
__pAllPcmBuffer = (char*)malloc(__iAllPcmBufferSize);
|
|
|
|
if (__pAllPcmBuffer != NULL)
|
|
|
|
{
|
|
|
|
__pFile->Read(__pAllPcmBuffer, __iAllPcmBufferSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("not more memory...");
|
2011-10-18 18:10:53 +08:00
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
else if (strFile.EndsWith(".ogg"))
|
|
|
|
{
|
|
|
|
__iFileType = 1;
|
|
|
|
long long curTick, oldTick;
|
|
|
|
Osp::System::SystemTime::GetTicks(oldTick);
|
|
|
|
DecodeOgg(pszFilePath);
|
|
|
|
Osp::System::SystemTime::GetTicks(curTick);
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("decode ogg to pcm waste %ld", (long)(curTick-oldTick));
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
// Prepare AudioOut
|
|
|
|
r = __pAudioOut->Prepare( __sampleBitdepth, __sampleChannelType, __sampleRate );
|
|
|
|
if (IsFailed(r))
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.Prepare failed");
|
2011-10-18 09:45:04 +08:00
|
|
|
return r;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
__bufferSize = __pAudioOut->GetMinBufferSize();
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Info] __bufferSize=%d (MaxBuf=%d Min Size %d)\n", __bufferSize, __pAudioOut->GetMaxBufferSize(),__pAudioOut->GetMinBufferSize());
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
// Reset Volume or keeping a volume level
|
|
|
|
__volumeLevel = __volumeLevel == -1 ? DEFAULT_VOLUME_LEVEL : __volumeLevel;
|
|
|
|
r = __pAudioOut->SetVolume(DEFAULT_VOLUME_LEVEL);
|
|
|
|
if (IsFailed(r))
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.SetVolume failed");
|
2011-10-18 09:45:04 +08:00
|
|
|
return r;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
if (!__bBufferConstruted)
|
2011-10-18 09:45:04 +08:00
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
__bBufferConstruted = true;
|
|
|
|
r = __byteBuffer[0].Construct(__bufferSize);
|
|
|
|
if (E_SUCCESS != r)
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog( "[Error] __byteBuffer[0].Construct failed..%d ",r);
|
2011-10-18 18:10:53 +08:00
|
|
|
return E_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
r = __byteBuffer[1].Construct(__bufferSize);
|
|
|
|
if (E_SUCCESS != r)
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog( "[Error] __byteBuffer[1].Construct failed..%d ",r);
|
2011-10-18 18:10:53 +08:00
|
|
|
return E_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
r = __byteBuffer[2].Construct(__bufferSize);
|
|
|
|
if (E_SUCCESS != r)
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog( "[Error] __byteBuffer[2].Construct failed..%d ",r);
|
2011-10-18 18:10:53 +08:00
|
|
|
return E_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
r = __byteBuffer[3].Construct(__bufferSize);
|
|
|
|
if (E_SUCCESS != r)
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog( "[Error] __byteBuffer[3].Construct failed..%d ",r);
|
2011-10-18 18:10:53 +08:00
|
|
|
return E_OUT_OF_MEMORY;
|
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
if (__iAllPcmBufferSize <= __bufferSize * 4)
|
2011-10-18 09:45:04 +08:00
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
__bShortPcmBuffer = true;
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
else
|
2011-10-18 09:45:04 +08:00
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
__bShortPcmBuffer = false;
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
ReWriteBuffer();
|
2011-10-18 09:45:04 +08:00
|
|
|
__checkInitFiniPair = true;
|
|
|
|
|
|
|
|
}else{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[WANRNING] The application state is not proper");
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
result CCAudioOut::FeedBuffer (void)
|
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
result ret = E_FAILURE;
|
|
|
|
|
|
|
|
// if (__iFileType == 0)
|
|
|
|
// {
|
|
|
|
// /*
|
|
|
|
// * Read buffer from file
|
|
|
|
// */
|
|
|
|
// if(__pFile)
|
|
|
|
// {
|
|
|
|
// readSize = __pFile->Read((char *)__byteBuffer[__buffWriteCnt].GetPointer (), __bufferSize);
|
|
|
|
// if(readSize != 0)
|
|
|
|
// {
|
|
|
|
// __buffWriteCnt ++;
|
|
|
|
// if (4 == __buffWriteCnt)
|
|
|
|
// {
|
|
|
|
// __buffWriteCnt = 0;
|
|
|
|
// }
|
|
|
|
// }else
|
|
|
|
// {
|
|
|
|
// __finishChecker = PRE_BUFFERING_NUM;
|
|
|
|
// __buffWriteCnt = 0;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else if (__iFileType == 1)
|
2011-10-18 09:45:04 +08:00
|
|
|
{// ogg
|
|
|
|
int iRemainSize = __iAllPcmBufferSize - __iAllPcmPos;
|
|
|
|
if (iRemainSize < __bufferSize)
|
|
|
|
{
|
|
|
|
memcpy((void*)__byteBuffer[__buffWriteCnt].GetPointer (), __pAllPcmBuffer+__iAllPcmPos, iRemainSize);
|
|
|
|
__iAllPcmPos += iRemainSize;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy((void*)__byteBuffer[__buffWriteCnt].GetPointer (), __pAllPcmBuffer+__iAllPcmPos, __bufferSize);
|
|
|
|
__iAllPcmPos += __bufferSize;
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-19 17:15:21 +08:00
|
|
|
__iUsedBufferCount++;
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
if (__iAllPcmPos < __iAllPcmBufferSize)
|
|
|
|
{
|
|
|
|
__buffWriteCnt ++;
|
|
|
|
if (4 == __buffWriteCnt)
|
|
|
|
{
|
|
|
|
__buffWriteCnt = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
__finishChecker = PRE_BUFFERING_NUM;
|
|
|
|
__buffWriteCnt = 0;
|
|
|
|
__iAllPcmPos = 0;
|
2011-10-18 18:10:53 +08:00
|
|
|
ret = E_SUCCESS;
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
return ret;
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
result CCAudioOut::ReWriteBuffer(void)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
result r = E_FAILURE;
|
|
|
|
__iAllPcmPos = 0;
|
|
|
|
__iUsedBufferCount = 0;
|
|
|
|
if (__bShortPcmBuffer)
|
|
|
|
{
|
|
|
|
for (i=0; i<4; i++)
|
|
|
|
{
|
|
|
|
r = FeedBuffer();
|
|
|
|
if (!IsFailed(r)) // Feeding buffers(4)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < __iUsedBufferCount; i++)
|
|
|
|
{
|
|
|
|
r = __pAudioOut->WriteBuffer(__byteBuffer[i]);
|
|
|
|
if (IsFailed(r))
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.WriteBuffer failed : %d\n", r);
|
2011-10-18 18:10:53 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i=0; i<4; i++)
|
|
|
|
{
|
|
|
|
FeedBuffer(); // Feeding buffers(4)
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
r = __pAudioOut->WriteBuffer(__byteBuffer[i]);
|
|
|
|
if (IsFailed(r))
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.WriteBuffer failed : %d\n", r);
|
2011-10-18 18:10:53 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
|
|
|
|
void CCAudioOut::ReFeedBuffer(void)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 09:45:04 +08:00
|
|
|
result r = E_SUCCESS;
|
|
|
|
for (int i=0; i<4; i++)
|
|
|
|
{
|
|
|
|
FeedBuffer(); // Feeding buffers(4)
|
|
|
|
}
|
|
|
|
|
|
|
|
r = __pAudioOut->WriteBuffer(__byteBuffer[0]);
|
|
|
|
if (IsFailed(r))
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.WriteBuffer failed : %d\n", r);
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
r = __pAudioOut->WriteBuffer(__byteBuffer[1]);
|
|
|
|
if (IsFailed(r))
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("[Error] m_AudioOut.WriteBuffer failed : %d\n", r);
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-28 15:49:37 +08:00
|
|
|
result CCAudioOut::Play(bool bLoop/* = false*/)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
result ret = E_FAILURE;
|
2011-10-18 09:45:04 +08:00
|
|
|
AudioOutState state = __pAudioOut->GetState();
|
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
if(state == AUDIOOUT_STATE_PREPARED || state == AUDIOOUT_STATE_STOPPED)
|
2011-10-18 09:45:04 +08:00
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
__bLoop = bLoop;
|
2011-10-18 09:45:04 +08:00
|
|
|
ret = __pAudioOut->Start();
|
|
|
|
if (IsFailed(ret))
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
AppLog("[Error] m_AudioOut.Start failed : %d\n", ret);
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
return ret;
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
result CCAudioOut::Stop(void)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
AudioOutState state = __pAudioOut->GetState();
|
|
|
|
result r = E_SUCCESS;
|
|
|
|
|
2011-11-28 18:05:38 +08:00
|
|
|
__bPause = false;
|
2011-11-28 15:49:37 +08:00
|
|
|
if(state == AUDIOOUT_STATE_PLAYING)
|
|
|
|
{
|
|
|
|
r = __pAudioOut->Reset();
|
|
|
|
if(IsFailed(r))
|
|
|
|
{
|
2011-11-28 16:09:01 +08:00
|
|
|
AppLog("[Error] AudioOut Reset is failed");
|
2011-11-28 15:49:37 +08:00
|
|
|
}
|
|
|
|
ReWriteBuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
result CCAudioOut::Pause(void)
|
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
result ret = E_FAILURE;
|
2011-10-18 09:45:04 +08:00
|
|
|
|
|
|
|
if( __pAudioOut->GetState() == AUDIOOUT_STATE_PLAYING )
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
__bPause = true;
|
2011-10-18 09:45:04 +08:00
|
|
|
ret = __pAudioOut->Stop();
|
|
|
|
if (IsFailed(ret))
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
AppLog("[Error] m_AudioOut.Stop failed : %d\n", ret);
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-11-28 15:49:37 +08:00
|
|
|
result CCAudioOut::Resume(void)
|
2011-10-18 18:10:53 +08:00
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
result ret = E_FAILURE;
|
2011-10-18 18:10:53 +08:00
|
|
|
|
2011-11-28 15:49:37 +08:00
|
|
|
if(__bPause && __pAudioOut->GetState() == AUDIOOUT_STATE_STOPPED )
|
2011-10-18 09:45:04 +08:00
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
__bPause = false;
|
|
|
|
ret = __pAudioOut->Start();
|
|
|
|
if (IsFailed(ret))
|
2011-10-18 18:10:53 +08:00
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
AppLog("[Error] m_AudioOut.Stop failed : %d\n", ret);
|
2011-10-18 18:10:53 +08:00
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
|
2011-11-28 15:49:37 +08:00
|
|
|
return ret;
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
void CCAudioOut::OnAudioOutBufferEndReached(Osp::Media::AudioOut& src)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
if (__bShortPcmBuffer)
|
2011-10-18 09:45:04 +08:00
|
|
|
{
|
2011-10-29 14:47:13 +08:00
|
|
|
__iUsedBufferCount--;
|
|
|
|
if (__iUsedBufferCount <= 0)
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
Stop();
|
|
|
|
if (__bLoop)
|
|
|
|
{
|
|
|
|
Play(__bLoop);
|
|
|
|
}
|
2011-10-29 14:47:13 +08:00
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
}
|
|
|
|
else
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
int ret = 0;
|
2011-11-13 00:57:54 +08:00
|
|
|
// //AppLog("thread name is %S", Thread::GetCurrentThread()->GetName().GetPointer());
|
|
|
|
//AppLog("__buffReadCnt = %d", __buffReadCnt);
|
2011-10-18 18:10:53 +08:00
|
|
|
__byteBuffer[__buffReadCnt++].Clear ();
|
|
|
|
|
|
|
|
if (4 == __buffReadCnt)
|
|
|
|
__buffReadCnt = 0;
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
if(__finishChecker == 0)
|
|
|
|
{
|
2011-10-18 18:10:53 +08:00
|
|
|
ret = src.WriteBuffer(__byteBuffer[__bufWrittenCnt++]);
|
|
|
|
if (4 == __bufWrittenCnt)
|
|
|
|
__bufWrittenCnt = 0;
|
|
|
|
FeedBuffer();
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-11-13 00:57:54 +08:00
|
|
|
//AppLog("__finishChecker = %d", __finishChecker);
|
2011-10-18 18:10:53 +08:00
|
|
|
__finishChecker--;
|
|
|
|
if(__finishChecker == 0)
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
Stop();
|
2011-10-18 18:10:53 +08:00
|
|
|
__bufWrittenCnt = PRE_BUFFERING_NUM;
|
|
|
|
__buffReadCnt = 0;
|
|
|
|
__buffWriteCnt = 0;
|
2011-11-28 15:49:37 +08:00
|
|
|
if (__bLoop)
|
|
|
|
{
|
|
|
|
Play(__bLoop);
|
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
}
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
|
2011-10-18 09:45:04 +08:00
|
|
|
void CCAudioOut::OnAudioOutInterrupted(Osp::Media::AudioOut& src)
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
Pause();
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCAudioOut::OnAudioOutReleased(Osp::Media::AudioOut& src)
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
Resume();
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCAudioOut::Finalize(void)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 09:45:04 +08:00
|
|
|
if(__checkInitFiniPair)
|
2011-10-14 17:57:44 +08:00
|
|
|
{
|
2011-10-18 09:45:04 +08:00
|
|
|
|
|
|
|
// Set OnAudioOutBufferEndReached stop.
|
|
|
|
__finishChecker = PRE_BUFFERING_NUM;
|
|
|
|
|
|
|
|
if(__pAudioOut)
|
|
|
|
{
|
|
|
|
|
|
|
|
AudioOutState state = __pAudioOut->GetState();
|
|
|
|
result r = E_SUCCESS;
|
|
|
|
|
|
|
|
if(state == AUDIOOUT_STATE_PLAYING)
|
|
|
|
{
|
|
|
|
r = __pAudioOut->Reset();
|
|
|
|
if(IsFailed(r))
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
AppLog("[Error] AudioOut Reset is failed");
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
state = __pAudioOut->GetState();
|
|
|
|
|
|
|
|
if(state == AUDIOOUT_STATE_PREPARED || state == AUDIOOUT_STATE_STOPPED)
|
|
|
|
{
|
|
|
|
r = __pAudioOut->Unprepare();
|
|
|
|
if(IsFailed(r))
|
|
|
|
{
|
2011-11-28 15:49:37 +08:00
|
|
|
AppLog("[Error] AudioOut UnPrepare is failed");
|
2011-10-18 09:45:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(__pFile)
|
|
|
|
{
|
|
|
|
delete __pFile;
|
|
|
|
__pFile = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
__checkInitFiniPair = false;
|
|
|
|
}else{
|
2011-11-28 15:49:37 +08:00
|
|
|
AppLog("[WANRNING] This application state is not proper");
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-18 18:10:53 +08:00
|
|
|
void CCAudioOut::SetVolume(int volume)
|
|
|
|
{
|
|
|
|
if (__pAudioOut)
|
|
|
|
__pAudioOut->SetVolume(volume);
|
2011-10-14 17:57:44 +08:00
|
|
|
}
|
2011-10-18 18:10:53 +08:00
|
|
|
|
|
|
|
int CCAudioOut::GetVolume(void) const
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
if (__pAudioOut)
|
|
|
|
ret = __pAudioOut->GetVolume();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
Osp::Media::AudioOutState CCAudioOut::GetState(void) const
|
|
|
|
{
|
|
|
|
AudioOutState state = AUDIOOUT_STATE_ERROR;
|
|
|
|
if (__pAudioOut)
|
|
|
|
state = __pAudioOut->GetState();
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|