open source
This commit is contained in:
@@ -0,0 +1,417 @@
|
||||
/**
|
||||
@file JCAudioWavPlayer.cpp
|
||||
@brief
|
||||
@author James
|
||||
@version 1.0
|
||||
@date 2014_4_22
|
||||
*/
|
||||
|
||||
#include "JCAudioWavPlayer.h"
|
||||
#include "../../util/JCCommonMethod.h"
|
||||
#include "../../util/Log.h"
|
||||
#include "JCWaveParser.h"
|
||||
#include "JCOggParser.h"
|
||||
#include "../JCFileResManager.h"
|
||||
//------------------------------------------------------------------------------
|
||||
namespace laya
|
||||
{
|
||||
int JCAudioWavPlayer::s_nGarbageCollectionTime = 30000; //30Ãë
|
||||
//------------------------------------------------------------------------------
|
||||
JCAudioWavPlayer::JCAudioWavPlayer(JCFileResManager* pFileResManager)
|
||||
{
|
||||
m_pFileResManager = pFileResManager;
|
||||
m_pOpenALSource.reserve(128);
|
||||
m_nCurrentIndex = 0;
|
||||
m_bStop=false;
|
||||
m_pDevice = alcOpenDevice(NULL);
|
||||
m_pContext = alcCreateContext( m_pDevice, NULL );
|
||||
alcMakeContextCurrent( m_pContext );
|
||||
createOpenALSource();
|
||||
}
|
||||
void JCAudioWavPlayer::createOpenALSource()
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
m_pOpenALSource.resize(m_nALCount + OPENAL_SOURCE_NUM);
|
||||
ALuint pOpenALBuffer[OPENAL_SOURCE_NUM];
|
||||
alGenBuffers(OPENAL_SOURCE_NUM, pOpenALBuffer);
|
||||
ALuint pOpenALSouceID[OPENAL_SOURCE_NUM];
|
||||
alGenSources(OPENAL_SOURCE_NUM, pOpenALSouceID);
|
||||
for (int i = 0; i < OPENAL_SOURCE_NUM; i++)
|
||||
{
|
||||
m_pOpenALSource[m_nALCount + i] = new OpenALSourceInfo;
|
||||
m_pOpenALSource[m_nALCount + i]->m_nOpenALSouceID = pOpenALSouceID[i];
|
||||
m_pOpenALSource[m_nALCount + i]->m_nBufferID = 0;
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
m_pOpenALSource[m_nALCount + i]->m_vSourcePos[j] = 0;
|
||||
m_pOpenALSource[m_nALCount + i]->m_vSourceVel[j] = 0;
|
||||
}
|
||||
m_pOpenALSource[m_nALCount + i]->m_bPlaying = false;
|
||||
m_pOpenALSource[m_nALCount + i]->m_pAudio = NULL;
|
||||
}
|
||||
LOGI("createOpenALSource current num=%d",m_pOpenALSource.size());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
JCAudioWavPlayer::~JCAudioWavPlayer()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
OpenALSourceInfo* JCAudioWavPlayer::getOpenALSource()
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
bool bFind = false;
|
||||
OpenALSourceInfo* pInfo = NULL;
|
||||
for( int i = 0; i < m_nALCount; i++ )
|
||||
{
|
||||
int n = (m_nCurrentIndex + i) % m_nALCount;
|
||||
pInfo= m_pOpenALSource[n];
|
||||
if( pInfo->m_bPlaying == false )
|
||||
{
|
||||
m_nCurrentIndex = n + 1;
|
||||
bFind = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bFind==false)
|
||||
{
|
||||
int nLastCount = m_nALCount;
|
||||
createOpenALSource();
|
||||
pInfo = m_pOpenALSource[nLastCount];
|
||||
m_nCurrentIndex = nLastCount;
|
||||
}
|
||||
return pInfo;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::checkWavePlayEnd()
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
ALint nState = 0;
|
||||
for ( int i = 0; i < m_nALCount; i++)
|
||||
{
|
||||
if( m_pOpenALSource[i]->m_bPlaying == true )
|
||||
{
|
||||
alGetSourcei(m_pOpenALSource[i]->m_nOpenALSouceID, AL_SOURCE_STATE, &nState );
|
||||
if ( nState == AL_STOPPED )
|
||||
{
|
||||
releaseOpenAL(m_pOpenALSource[i]);
|
||||
m_pOpenALSource[i]->m_bPlaying = false;
|
||||
if(m_pOpenALSource[i]->m_pAudio != NULL )
|
||||
{
|
||||
m_pOpenALSource[i]->m_pAudio->onPlayEnd();
|
||||
m_pOpenALSource[i]->m_pAudio = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
OpenALSourceInfo* JCAudioWavPlayer::playAudio( JCAudioInterface* p_pAudio,const std::string& p_sSrc, bool bIsOgg)
|
||||
{
|
||||
JCWaveInfo* pInfo = NULL;
|
||||
MapWaveInfoIter iter = m_vWaveInfos.find( p_sSrc );
|
||||
if( iter != m_vWaveInfos.end() )
|
||||
{
|
||||
pInfo = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
JCFileRes* pRes = m_pFileResManager->getRes(p_sSrc.c_str());
|
||||
JCBuffer kBuffer;
|
||||
if (pRes && pRes->loadFromCache(kBuffer, false))
|
||||
{
|
||||
pInfo = AddWaveInfo(p_sSrc, (unsigned char*)kBuffer.m_pPtr, kBuffer.m_nLen, NULL, p_pAudio, bIsOgg);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGE("JCAudioWavPlayer::playAudio load res error");
|
||||
}
|
||||
}
|
||||
if (pInfo != NULL)
|
||||
{
|
||||
pInfo->m_nTouchTime = tmGetCurms();
|
||||
WAVE_FORMAT* pFormat = &(pInfo->m_kFmtBlock.wavFormat);
|
||||
return playAudioFromBuffer(p_pAudio, (char*)(pInfo->m_pData), pInfo->m_nRealDataSize, pFormat->dwSamplesPerSec, pFormat->wBitsPerSample, pFormat->wChannels);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void JCAudioWavPlayer::delAudio(JCAudioInterface* p_pAudio)
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
for ( int i = 0; i < m_nALCount; i++){
|
||||
if( m_pOpenALSource[i]->m_pAudio==p_pAudio){
|
||||
m_pOpenALSource[i]->m_pAudio = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::releaseOpenAL( OpenALSourceInfo* pOpenALInfo )
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// some specific OpenAL implement defects existed on iOS platform
|
||||
// refer to: https://github.com/cocos2d/cocos2d-x/issues/18597
|
||||
ALint sourceState;
|
||||
ALint bufferProcessed = 0;
|
||||
alGetSourcei(pOpenALInfo->m_nOpenALSouceID, AL_SOURCE_STATE, &sourceState);
|
||||
if (sourceState == AL_PLAYING)
|
||||
{
|
||||
alGetSourcei(pOpenALInfo->m_nOpenALSouceID, AL_BUFFERS_PROCESSED, &bufferProcessed);
|
||||
while (bufferProcessed < 1/*QUEUEBUFFER_NUM*/)
|
||||
{
|
||||
LOGI("JCAudioWavPlayer::releaseOpenAL wait buffer");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
alGetSourcei(pOpenALInfo->m_nOpenALSouceID, AL_BUFFERS_PROCESSED, &bufferProcessed);
|
||||
}
|
||||
alSourceUnqueueBuffers(pOpenALInfo->m_nOpenALSouceID, /*QUEUEBUFFER_NUM*/1, &pOpenALInfo->m_nBufferID);
|
||||
}
|
||||
#else
|
||||
alSourceUnqueueBuffers( pOpenALInfo->m_nOpenALSouceID, 1, &(pOpenALInfo->m_nBufferID) );
|
||||
#endif
|
||||
|
||||
alSourcei(pOpenALInfo->m_nOpenALSouceID, AL_BUFFER, 0);
|
||||
if (pOpenALInfo->m_nBufferID != 0 && alIsBuffer(pOpenALInfo->m_nBufferID))
|
||||
{
|
||||
alDeleteBuffers(1, &pOpenALInfo->m_nBufferID);
|
||||
pOpenALInfo->m_nBufferID = 0;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
OpenALSourceInfo* JCAudioWavPlayer::playAudioFromBuffer( JCAudioInterface* p_pAudio,const char* p_pBuffer,unsigned int p_nBufferSize,
|
||||
int p_nRate,int nBitsPerSample, int nChannels)
|
||||
{
|
||||
OpenALSourceInfo* pOpenALInfo = getOpenALSource();
|
||||
alSourceStop( pOpenALInfo->m_nOpenALSouceID );
|
||||
releaseOpenAL( pOpenALInfo );
|
||||
alSourcef ( pOpenALInfo->m_nOpenALSouceID, AL_PITCH, 1.0 );
|
||||
alSourcef ( pOpenALInfo->m_nOpenALSouceID, AL_GAIN, 1.0 );
|
||||
alSourcei ( pOpenALInfo->m_nOpenALSouceID, AL_LOOPING, 0 );
|
||||
//ÏÈÆÁ±Î
|
||||
//alSourcefv( pOpenALInfo->m_nOpenALSouceID, AL_VELOCITY, pOpenALInfo->m_vSourceVel );
|
||||
//alSourcefv( pOpenALInfo->m_nOpenALSouceID, AL_POSITION, pOpenALInfo->m_vSourcePos );
|
||||
|
||||
//bind buffer
|
||||
ALuint nBufferID = 0;
|
||||
alGenBuffers( 1,&nBufferID );
|
||||
int nFormat = AL_FORMAT_MONO16;
|
||||
switch (nChannels)
|
||||
{
|
||||
case 1:
|
||||
switch (nBitsPerSample)
|
||||
{
|
||||
case 8:
|
||||
nFormat = AL_FORMAT_MONO8;
|
||||
break;
|
||||
case 16:
|
||||
nFormat = AL_FORMAT_MONO16;
|
||||
break;
|
||||
default:
|
||||
LOGE("JCAudioWavPlayer::playAudioFromBuffer sound bitsPerSample error,only support 8 or 16");
|
||||
nFormat = AL_FORMAT_MONO16;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (nBitsPerSample)
|
||||
{
|
||||
case 8:
|
||||
nFormat = AL_FORMAT_STEREO8;
|
||||
break;
|
||||
case 16:
|
||||
nFormat = AL_FORMAT_STEREO16;
|
||||
break;
|
||||
default:
|
||||
LOGE("JCAudioWavPlayer::playAudioFromBuffer sound bitsPerSample error,only support 8 or 16");
|
||||
nFormat = AL_FORMAT_STEREO16;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGE("JCAudioWavPlayer::playAudioFromBuffer sound channel error");
|
||||
switch (nBitsPerSample)
|
||||
{
|
||||
case 8:
|
||||
nFormat = AL_FORMAT_MONO8;
|
||||
break;
|
||||
case 16:
|
||||
nFormat = AL_FORMAT_MONO16;
|
||||
break;
|
||||
default:
|
||||
LOGE("JCAudioWavPlayer::playAudioFromBuffer sound bitsPerSample error,only support 8 or 16");
|
||||
nFormat = AL_FORMAT_MONO16;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
alBufferData(nBufferID, nFormat, p_pBuffer, p_nBufferSize, p_nRate);
|
||||
alSourceQueueBuffers( pOpenALInfo->m_nOpenALSouceID, 1, &nBufferID );
|
||||
pOpenALInfo->m_nBufferID = nBufferID;
|
||||
//play
|
||||
alSourcePlay( pOpenALInfo->m_nOpenALSouceID );
|
||||
//±£ÁôÐÅÏ¢
|
||||
pOpenALInfo->m_pAudio = p_pAudio;
|
||||
pOpenALInfo->m_bPlaying = true;
|
||||
return pOpenALInfo;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::stopAll()
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
for (int i = 0; i < m_nALCount; i++)
|
||||
{
|
||||
if( m_pOpenALSource[i]->m_bPlaying == true )
|
||||
{
|
||||
alSourceStop(m_pOpenALSource[i]->m_nOpenALSouceID );
|
||||
releaseOpenAL(m_pOpenALSource[i]);
|
||||
m_pOpenALSource[i]->m_bPlaying = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
void JCAudioWavPlayer::pause()
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
for (int i = 0; i < m_nALCount; i++)
|
||||
{
|
||||
alSourcePause(m_pOpenALSource[i]->m_nOpenALSouceID);
|
||||
}
|
||||
}
|
||||
void JCAudioWavPlayer::resume()
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
for (int i = 0; i < m_nALCount; i++)
|
||||
{
|
||||
alSourcePlay(m_pOpenALSource[i]->m_nOpenALSouceID);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::setAllVolume( float p_nVolume )
|
||||
{
|
||||
int m_nALCount = m_pOpenALSource.size();
|
||||
for ( int i = 0; i < m_nALCount; i++ )
|
||||
{
|
||||
alSourcef ( m_pOpenALSource[i]->m_nOpenALSouceID, AL_GAIN, p_nVolume);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::stop(OpenALSourceInfo* pOpenALInfo)
|
||||
{
|
||||
if (pOpenALInfo->m_bPlaying == true)
|
||||
{
|
||||
alSourceStop(pOpenALInfo->m_nOpenALSouceID);
|
||||
releaseOpenAL(pOpenALInfo);
|
||||
pOpenALInfo->m_bPlaying = false;
|
||||
pOpenALInfo->m_pAudio = NULL;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::setVolume(OpenALSourceInfo* pOpenALInfo,float p_nVolume)
|
||||
{
|
||||
alSourcef(pOpenALInfo->m_nOpenALSouceID, AL_GAIN, p_nVolume);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void JCAudioWavPlayer::Release()
|
||||
{
|
||||
for (int i = 0; i < m_pOpenALSource.size(); i++)
|
||||
{
|
||||
if (m_pOpenALSource[i]->m_nBufferID != 0 && alIsBuffer(m_pOpenALSource[i]->m_nBufferID))
|
||||
{
|
||||
alDeleteBuffers(1, &m_pOpenALSource[i]->m_nBufferID);
|
||||
m_pOpenALSource[i]->m_nBufferID = 0;
|
||||
}
|
||||
if (m_pOpenALSource[i]->m_nOpenALSouceID != 0 && alIsSource(m_pOpenALSource[i]->m_nOpenALSouceID))
|
||||
{
|
||||
alDeleteSources(1, &m_pOpenALSource[i]->m_nOpenALSouceID);
|
||||
m_pOpenALSource[i]->m_nOpenALSouceID = 0;
|
||||
}
|
||||
delete m_pOpenALSource[i];
|
||||
}
|
||||
if (m_pContext != NULL)
|
||||
{
|
||||
alcDestroyContext( m_pContext );
|
||||
m_pContext=NULL;
|
||||
}
|
||||
if ( m_pDevice !=NULL )
|
||||
{
|
||||
alcCloseDevice(m_pDevice);
|
||||
m_pDevice=NULL;
|
||||
}
|
||||
m_bStop=true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
JCWaveInfo* JCAudioWavPlayer::AddWaveInfo( const std::string& p_sUrl,unsigned char* p_pBuffer,int p_nSize,const char* p_sFilePath,void* p_pExternalMark,bool p_bIsOgg )
|
||||
{
|
||||
JCWaveInfo* pInfo = FindWaveInfo( p_sUrl );
|
||||
if( pInfo == NULL )
|
||||
{
|
||||
if( p_bIsOgg == false )
|
||||
{
|
||||
pInfo = JCWaveParser::GetInstance()->GetWaveInfoFromBuffer( p_pBuffer,p_nSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
pInfo = JCOggParser::GetInstance()->GetWaveInfo( p_sFilePath,p_pBuffer,p_nSize );
|
||||
}
|
||||
if( pInfo != NULL )
|
||||
{
|
||||
pInfo->m_sUrl = p_sUrl;
|
||||
pInfo->m_nTouchTime = tmGetCurms();
|
||||
pInfo->m_pExternalMark = p_pExternalMark;
|
||||
m_vWaveInfos[ p_sUrl ] = pInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGE( "JCAudioWavPlayer::AddWaveInfo wave paser err" );
|
||||
}
|
||||
}
|
||||
return pInfo;
|
||||
}
|
||||
void JCAudioWavPlayer::autoGarbageCollection()
|
||||
{
|
||||
if (m_vWaveInfos.size() <= 0)return;
|
||||
double nCurrentTime = tmGetCurms();
|
||||
for (MapWaveInfoIter iter = m_vWaveInfos.begin(); iter != m_vWaveInfos.end();)
|
||||
{
|
||||
JCWaveInfo* pInfo = iter->second;
|
||||
if (pInfo && (nCurrentTime - pInfo->m_nTouchTime > s_nGarbageCollectionTime ) )
|
||||
{
|
||||
delete pInfo;
|
||||
pInfo = NULL;
|
||||
iter = m_vWaveInfos.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
JCWaveInfo* JCAudioWavPlayer::FindWaveInfo( const std::string& p_sUrl )
|
||||
{
|
||||
MapWaveInfoIter iter = m_vWaveInfos.find( p_sUrl );
|
||||
if( iter != m_vWaveInfos.end() )
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool JCAudioWavPlayer::ClearAllWaveInfo( void )
|
||||
{
|
||||
for( MapWaveInfoIter iter = m_vWaveInfos.begin(); iter != m_vWaveInfos.end(); iter++ )
|
||||
{
|
||||
JCWaveInfo* pInfo = NULL;
|
||||
pInfo = iter->second;
|
||||
if( pInfo != NULL )
|
||||
{
|
||||
delete pInfo;
|
||||
pInfo = NULL;
|
||||
}
|
||||
}
|
||||
m_vWaveInfos.clear();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
//-----------------------------END FILE--------------------------------
|
||||
Reference in New Issue
Block a user