axmol/CocosDenshion/bada/CCAudioOut.cpp

296 lines
7.0 KiB
C++
Raw Normal View History

2011-10-14 18:33:14 +08:00
#include "CCAudioOut.h"
2011-10-14 17:57:44 +08:00
#include <stdio.h>
using namespace Osp::Base;
using namespace Osp::Base::Collection;
using namespace Osp::Media;
#define MAX_BUFFER_SIZE 2520 // 840 byte
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;
static bool GetWaveHeadInfo(FILE*stream, WAVE& outWavHead)
{
char szTmp[100] = {0};
int i = 0;
fread(outWavHead.ChunkID, 4, 1, stream);
outWavHead.ChunkID[4] = (char)0;
fread(&(outWavHead.ChunkSize),4, 1, stream);
fread(outWavHead.Format, 4, 1, stream);
outWavHead.Format[4] = (char)0;
fread(outWavHead.SubChunk1ID, 4, 1, stream);
outWavHead.SubChunk1ID[4] = (char)0;
fread(&(outWavHead.SubChunk1Size), 4, 1, stream);
fread(&(outWavHead.AudioFormat), 2, 1, stream);
fread(&(outWavHead.NumChannels), 2, 1, stream);
fread(&(outWavHead.SampleRate), 4, 1, stream);
fread(&(outWavHead.ByteRate), 4, 1, stream);
fread(&(outWavHead.BlockAlign), 2, 1, stream);
fread(&(outWavHead.BitsPerSample), 2, 1, stream);
fseek(stream, 0, SEEK_SET);
fread(szTmp, 64, 1, stream);
for (i = 0; i <= 60; i++)
{
if (szTmp[i] == 'd' && szTmp[i+1] == 'a' && szTmp[i+2] == 't' && szTmp[i+3] == 'a')
{
break;
}
}
fseek(stream, i, SEEK_SET);
fread(outWavHead.SubChunk2ID, 4, 1, stream);
outWavHead.SubChunk2ID[4] = (char)0;
fread(&(outWavHead.SubChunk2Size), 4, 1, stream);
return true;
}
2011-10-14 17:57:44 +08:00
MyAudioOutEventListener::MyAudioOutEventListener()
{
__totalWriteBufferNum = 0;
__playCount = 0;
__pDataArray = null;
__pAudioOut = null;
__pPcmBuffer = null;
__pcmLen = 0;
}
MyAudioOutEventListener::~MyAudioOutEventListener()
{
AppLog("dealoc MyAudioOutEventListener");
if (__pDataArray != null)
{
__pDataArray->RemoveAll(true);
delete __pDataArray;
__pDataArray = null;
}
if (__pAudioOut != null)
{
__pAudioOut->Stop();
__pAudioOut->Unprepare();
delete __pAudioOut;
__pAudioOut = null;
}
if (__pPcmBuffer != null)
{
delete[] __pPcmBuffer;
__pPcmBuffer = null;
}
}
result MyAudioOutEventListener::Construct(const char* pszFilePath)
{
__pAudioOut = new AudioOut();
__pAudioOut->Construct(*this);
WAVE wavHead;
FILE* fp = fopen(pszFilePath, "rb");
if (fp != NULL)
{
if (GetWaveHeadInfo(fp, wavHead))
{
__pPcmBuffer = new char[wavHead.SubChunk2Size];
__pcmLen = wavHead.SubChunk2Size;
fread(__pPcmBuffer, __pcmLen, 1, fp);
fclose(fp);
}
else
{
fclose(fp);
return E_FAILURE;
}
}
__pDataArray = new ArrayList();
// AudioOut Preparation
AudioSampleType audioSampleType;
AudioChannelType audioChannelType;
int audioSampleRate = 0;
if (wavHead.BitsPerSample == 8)
{
audioSampleType = AUDIO_TYPE_PCM_U8;
}
else if (wavHead.BitsPerSample == 16)
{
audioSampleType = AUDIO_TYPE_PCM_S16_LE;
}
else
{
audioSampleType = AUDIO_TYPE_NONE;
}
if (wavHead.NumChannels == 1)
{
audioChannelType = AUDIO_CHANNEL_TYPE_MONO;
}
else if (wavHead.NumChannels == 2)
{
audioChannelType = AUDIO_CHANNEL_TYPE_STEREO;
}
else
{
audioChannelType = AUDIO_CHANNEL_TYPE_NONE;
}
audioSampleRate = wavHead.SampleRate;
result r = __pAudioOut->Prepare(audioSampleType, audioChannelType, audioSampleRate);
AppLog("The audio out prepare result is %s", GetErrorMessage(r));
AppLogDebug("The audio out prepare result in ApplogDebug message");
ByteBuffer* pTotalData = null;
pTotalData = new ByteBuffer();
pTotalData->Construct(__pcmLen);
pTotalData->SetArray((byte*)__pPcmBuffer, 0, __pcmLen);
pTotalData->Flip();
int totalSize = pTotalData->GetLimit();
int currentPosition = 0;
ByteBuffer* pItem = null;
byte givenByte;
// Binding data buffers into the array
if(totalSize > MAX_BUFFER_SIZE)
{
do
{
pItem = new ByteBuffer();
pItem->Construct(MAX_BUFFER_SIZE);
for(int i = 0; i < MAX_BUFFER_SIZE; i++)
{
// Read it per 1 byte
pTotalData->GetByte(currentPosition++,givenByte);
pItem->SetByte(givenByte);
if(currentPosition == totalSize )
break;
}
__pDataArray->Add(*pItem);
}while(currentPosition < totalSize);
__totalWriteBufferNum = __pDataArray->GetCount();
}
else
{
pItem = new ByteBuffer();
pItem->Construct(totalSize);
for(int i = 0; i < totalSize; i++)
{
// Read it per 1 byte
pTotalData->GetByte(i, givenByte);
pItem->SetByte(givenByte);
}
__pDataArray->Add(*pItem);
__totalWriteBufferNum = __pDataArray->GetCount();
// non-case for now, may the size of test file is bigger than MAX size
}
delete pTotalData;
pTotalData = null;
// Start playing until the end of the array
// __pAudioOut->Start();
return r;
}
void MyAudioOutEventListener::play()
{
if (__pAudioOut->GetState() == AUDIOOUT_STATE_PLAYING)
{
__pAudioOut->Reset();
}
ByteBuffer* pWriteBuffer = null;
for (int i = 0; i < __totalWriteBufferNum; i++)
{
pWriteBuffer = static_cast<ByteBuffer*>(__pDataArray->GetAt(i));
__pAudioOut->WriteBuffer(*pWriteBuffer);
}
__pAudioOut->Start();
__playCount++;
}
void MyAudioOutEventListener::stop()
{
__pAudioOut->Stop();
}
void MyAudioOutEventListener::setVolume(int volume)
{
__pAudioOut->SetVolume(volume);
}
/**
* Notifies when the device has written a buffer completely.
*
* @param[in] src A pointer to the AudioOut instance that fired the event
*/
void MyAudioOutEventListener::OnAudioOutBufferEndReached(Osp::Media::AudioOut& src)
{
result r = E_SUCCESS;
if( __playCount == __totalWriteBufferNum)
{
// The End of array, it's time to finish
//cjh r = src.Unprepare();
//Reset Variable
__playCount = 0;
//cjh __totalWriteBufferNum = 0;
}else
{
//Not yet reached the end of array
//Write the next buffer
__playCount++;
// ByteBuffer* pWriteBuffer = static_cast<ByteBuffer*>(__pDataArray->GetAt(__playCount++));
// r = src.WriteBuffer(*pWriteBuffer);
}
}
/**
* Notifies that the output device is being interrupted by a task of higher priority than AudioOut.
*
* @param[in] src A pointer to the AudioOut instance that fired the event
*/
void MyAudioOutEventListener::OnAudioOutInterrupted(Osp::Media::AudioOut& src)
{
AppLog("OnAudioOutInterrupted");
if (__pAudioOut->GetState() == AUDIOOUT_STATE_PLAYING)
{
__pAudioOut->Stop();
}
}
/**
* Notifies that the interrupted output device has been released.
*
* @param[in] src A pointer to the AudioOut instance that fired the event
*/
void MyAudioOutEventListener::OnAudioOutReleased(Osp::Media::AudioOut& src)
{
AppLog("OnAudioOutReleased");
}