open source

This commit is contained in:
lvfulong
2020-11-11 16:17:13 +08:00
parent 4d989f3ecb
commit bc4ca748de
2441 changed files with 623057 additions and 2 deletions
@@ -0,0 +1,31 @@
/**
@file JCAudioInterface.h
@brief
@author James
@version 1.0
@date 2014_11_26
*/
#ifndef __JCAudioInterface_H__
#define __JCAudioInterface_H__
#include <stdio.h>
/**
* @brief JCAudioInterface
* 纯接口类
*/
namespace laya
{
class JCAudioInterface
{
public:
virtual void onPlayEnd() = 0;
};
}
#endif //__JCAudioInterface_H__
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,143 @@
/**
@file JCAudioWavPlayer.h
@brief
@author James
@version 1.0
@date 2014_4_22
*/
#ifndef __JCAudioWavPlayer_H__
#define __JCAudioWavPlayer_H__
//包含头文件
#ifdef WIN32
#include <xaudio2.h>
#include <al.h>
#include <alc.h>
#elif __APPLE__
#include <OpenAL/al.h>
#include <OpenAl/alc.h>
#elif ANDROID
#include <AL/al.h>
#include <AL/alc.h>
#endif
#include <stdio.h>
#include <thread>
#include "../../util/JCCommonMethod.h"
#include "JCWaveInfo.h"
#include "JCAudioInterface.h"
#include<unordered_map>
#include <vector>
namespace laya
{
class JCFileResManager;
#define OPENAL_SOURCE_NUM 10
struct OpenALSourceInfo
{
ALuint m_nOpenALSouceID; //OpenAl的ID
ALuint m_nBufferID; //bufferID
ALfloat m_vSourcePos[3]; //源声音的位置
ALfloat m_vSourceVel[3]; //源声音的速度
bool m_bPlaying; //是否为播放状态
JCAudioInterface* m_pAudio; //Audio 为了回调使用
void operator=(const OpenALSourceInfo& other)
{
m_nOpenALSouceID = other.m_nOpenALSouceID;
m_nBufferID = other.m_nBufferID;
m_bPlaying = other.m_bPlaying;
m_pAudio = other.m_pAudio;
for (int i = 0; i < 3; i++)
{
m_vSourcePos[i] = other.m_vSourcePos[i];
m_vSourceVel[i] = other.m_vSourceVel[i];
}
}
};
class JCAudioWavPlayer
{
public:
typedef std::unordered_map<std::string,JCWaveInfo*> MapWaveInfo;
typedef MapWaveInfo::iterator MapWaveInfoIter;
public:
JCAudioWavPlayer(JCFileResManager* pFileResManager);
~JCAudioWavPlayer();
void Release();
public:
OpenALSourceInfo* playAudio( JCAudioInterface* p_pAudio,const std::string& p_sSrc,bool bIsOgg );
void delAudio(JCAudioInterface* p_pAudio);
OpenALSourceInfo* playAudioFromBuffer( JCAudioInterface* p_pAudio,const char* p_pBuffer,unsigned int p_nBufferSize,int p_nRate, int p_nBitsPerSample, int nChannels);
void setVolume(OpenALSourceInfo* pOpenALInfo,float p_nVolume );
void stop(OpenALSourceInfo* pOpenALInfo);
void setAllVolume(float p_nVolume);
void stopAll();
void checkWavePlayEnd();
void pause();
void resume();
public:
/** @brief 添加资源
* @return
*/
JCWaveInfo* AddWaveInfo( const std::string& p_sUrl,unsigned char* p_pBuffer,int p_nSize,const char* p_sFilePath,void* p_pExternalMark,bool p_bIsOgg );
/** @brief 查找资源根据 ulid
* @param[in] ulID
* @return
*/
JCWaveInfo* FindWaveInfo( const std::string& p_sUrl );
/** @brief 清空所有
*/
bool ClearAllWaveInfo( void );
void autoGarbageCollection();
private:
void releaseOpenAL( OpenALSourceInfo* pOpenALInfo );
void createOpenALSource();
OpenALSourceInfo* getOpenALSource();
public:
static int s_nGarbageCollectionTime;
MapWaveInfo m_vWaveInfos; //wave的信息
public:
JCFileResManager* m_pFileResManager;
ALCdevice* m_pDevice; // 打开默认音频设备
ALCcontext* m_pContext; // context
std::vector<OpenALSourceInfo*> m_pOpenALSource; // 播放声音用的
int m_nCurrentIndex; // 记录上次的位置
bool m_bStop;
};
}
#endif //__JCAudioWavPlayer_H__
//-----------------------------END FILE--------------------------------
@@ -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--------------------------------
@@ -0,0 +1,50 @@
/**
@file JCMp3Interface.h
@brief
@author James
@version 1.0
@date 2014_11_26
*/
#ifndef __JCMp3Interface_H__
#define __JCMp3Interface_H__
#include "JCAudioInterface.h"
#include <stdio.h>
/**
* @brief JCMp3Interface
* 纯接口类
*/
namespace laya
{
class JCMp3Interface
{
public:
virtual void play( const char* p_sUrl,int p_nTimes,float nCurrentTime,JCAudioInterface* p_pJSAudio )=0;
virtual void delAudio( JCAudioInterface* p_pJSAudio )=0;
virtual void pause()=0;
virtual void stop()=0;
virtual void resume()=0;
virtual void setVolume( float p_nVolume )=0;
virtual void setMute(bool p_bMute)=0;
virtual void onPlayEnd()=0;
virtual void setCurrentTime(double nCurrentTime) = 0;
virtual double getCurrentTime() = 0;
virtual double getDuration() = 0;
};
}
#endif //__JCMp3Interface_H__
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,144 @@
/**
@file JCOggParser.cpp
@brief
@author James
@version 1.0
@date 2014_11_26
*/
//包含头文件
#include "JCOggParser.h"
#include "../../util/Log.h"
#include <vorbis/vorbisfile.h>
#include <ogg/ogg.h>
#include <vector>
#pragma warning (disable: 4996)
namespace laya
{
#define READ_OGG_BUFFER_TEMP_SIZE 44100 //读取ogg的时候,临时缓冲区大小
//------------------------------------------------------------------------------
JCOggParser* JCOggParser::ms_pOggParser = NULL;
//------------------------------------------------------------------------------
JCOggParser::JCOggParser()
{
m_nBufferSize = READ_OGG_BUFFER_TEMP_SIZE;
m_nCurBufferPos = 0;
m_pBuffer = new char[m_nBufferSize];
}
//------------------------------------------------------------------------------
JCOggParser::~JCOggParser()
{
if( m_pBuffer != NULL )
{
delete[] m_pBuffer;
m_pBuffer = NULL;
}
}
//------------------------------------------------------------------------------
JCOggParser* JCOggParser::GetInstance( void )
{
if( ms_pOggParser == NULL )
{
ms_pOggParser = new JCOggParser();
}
return ms_pOggParser;
}
//-----------------------------------------------------------------------------
void JCOggParser::DelInstance( void )
{
}
//-----------------------------------------------------------------------------
bool JCOggParser::copyBuffer( char* p_pBuffer,int p_nSize )
{
if( p_pBuffer == NULL || p_nSize <=0 ) return false;
if( m_nCurBufferPos + p_nSize > m_nBufferSize )
{
int nElargeSize = (p_nSize<=READ_OGG_BUFFER_TEMP_SIZE) ? READ_OGG_BUFFER_TEMP_SIZE : p_nSize;
char* pNewBuffer = new char[m_nBufferSize + nElargeSize];
memcpy( pNewBuffer,m_pBuffer,m_nBufferSize );
m_nBufferSize += nElargeSize;
delete m_pBuffer;
m_pBuffer = pNewBuffer;
}
memcpy( m_pBuffer+m_nCurBufferPos,p_pBuffer,p_nSize );
m_nCurBufferPos += p_nSize;
return true;
}
//------------------------------------------------------------------------------
JCWaveInfo* JCOggParser::GetWaveInfo( const char* p_sFileName,unsigned char* p_sBuffer, int p_nBufferSize )
{
m_nCurBufferPos = 0;
OggVorbis_File pOggStream;
vorbis_info* pVorbisInfo = NULL;
int nResult = -1;
if( p_sBuffer != NULL && p_nBufferSize > 0 )
{
nResult = ov_open_callbacks( NULL, &pOggStream, (const char*)p_sBuffer, p_nBufferSize, OV_CALLBACKS_DEFAULT );
}
else if( p_sFileName != NULL )
{
FILE* fp = NULL;
fp = fopen( p_sFileName, "rb" );
if( fp )
{
nResult = ov_open_callbacks( (void*)fp, &pOggStream, NULL, 0, OV_CALLBACKS_DEFAULT );
}
fclose( fp );
}
if( nResult >= 0 )
{
pVorbisInfo = ov_info( &pOggStream, -1 );
char pBufferData[ READ_OGG_BUFFER_TEMP_SIZE ];//解码时候的缓冲区
int nSize = 0;
int nPortion = 0;
int nResult1 = 0;
while( true )
{
nResult1 = ov_read( &pOggStream, pBufferData, sizeof(pBufferData), 0, 2, 1, &nPortion );
if( nResult1 > 0 )
{
nSize += nResult1;
copyBuffer( pBufferData,nResult1 );
}
else if( nResult1 == 0 )
{
break;
}
else
{
LOGE("JCOggParser::GetWaveInfo error 1");
return NULL;
}
}
if( nSize == 0)
{
LOGE("JCOggParser::GetWaveInfo error 2");
return NULL;
}
JCWaveInfo* pWaveInfo = new JCWaveInfo();
pWaveInfo->m_nRealDataSize = nSize;
pWaveInfo->m_pData = new unsigned char[nSize];
if( nSize == m_nCurBufferPos )
{
memcpy( pWaveInfo->m_pData,m_pBuffer,nSize*sizeof(char));
}
else
{
LOGE("JCOggParser::GetWaveInfo error 3");
return NULL;
}
pWaveInfo->m_kFmtBlock.wavFormat.dwSamplesPerSec = pVorbisInfo->rate;
pWaveInfo->m_kFmtBlock.wavFormat.wChannels = pVorbisInfo->channels;
//TODO 没有找到ogg的这个参数,似乎目前只支持16bit
pWaveInfo->m_kFmtBlock.wavFormat.wBitsPerSample = 16;
ov_clear(&pOggStream);
return pWaveInfo;
}
LOGE("JCOggParser::GetWaveInfo error 0");
return NULL;
}
//------------------------------------------------------------------------------
}
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,67 @@
/**
@file JCOggParser.h
@brief
@author James
@version 1.0
@date 2014_11_26
*/
#ifndef __JCOggParser_H__
#define __JCOggParser_H__
#include "JCWaveInfo.h"
/**
* @brief 读取wav文件 目前只支持
* 单声道
* 16位
* 采样级别 8000
* 音频格式 PCM
*/
namespace laya
{
class JCOggParser
{
public:
/** @brief构造函数
*/
JCOggParser( void );
/** @brief析构函数
*/
~JCOggParser( void );
/*
* getInstace()
*/
static JCOggParser* GetInstance( void );
static void DelInstance( void );
/*
* 从文件中读取wave数据
*/
JCWaveInfo* GetWaveInfo( const char* p_sFileName,unsigned char* p_sBuffer, int p_nBufferSize );
//拷贝buffer
bool copyBuffer( char* p_sBuffer,int p_nSize );
protected:
static JCOggParser* ms_pOggParser; //静态的this指针
char* m_pBuffer; //临时的buffer
int m_nBufferSize; //buffer大小
int m_nCurBufferPos; //当前buffer的位置
};
}
#endif //__JCOggParser_H__
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,208 @@
/**
@file JCWaveInfo.cpp
@brief
@author James
@version 1.0
@date 2012_11_17
*/
#include "JCWaveInfo.h"
#include "../../util/Log.h"
#pragma warning (disable: 4996)
namespace laya
{
//------------------------------------------------------------------------------
JCWaveInfo::JCWaveInfo( void )
{
m_nTouchTime = 0;
m_pExternalMark = NULL;
m_pData = NULL;
m_nCurPos = 0;
}
//------------------------------------------------------------------------------
JCWaveInfo::~JCWaveInfo( void )
{
//赋值为NULL,就可以了,不需要删除
if( m_pExternalMark != NULL )
{
m_pExternalMark = NULL;
}
if( m_pData != NULL )
{
delete[] m_pData;
m_pData = NULL;
}
}
//------------------------------------------------------------------------------
bool JCWaveInfo::LoadData( const char* p_sFileName )
{
FILE *fp = fopen( p_sFileName,"rb" );
if( fp == NULL )
{
LOGE("JCWaveInfo::LoadData Can't open file %s",p_sFileName );
return false;
}
fseek( fp,0,SEEK_END );
int nSize=ftell(fp);
fseek(fp,0L,SEEK_SET);
unsigned char* sBuffer = new unsigned char[nSize];
fread( sBuffer,1,nSize,fp );
fclose(fp);
m_nCurPos = 0;
LoadData( sBuffer,nSize );
if (sBuffer)
{
delete[] sBuffer;
sBuffer = NULL;
}
return true;
}
//------------------------------------------------------------------------------
bool JCWaveInfo::LoadData( unsigned char* p_sBuffer,int p_nBufferSize )
{
if( p_sBuffer == NULL )
{
LOGE("JCWaveInfo::LoadData buffer == null" );
return false;
}
//读取 RIFF 头
{
read( &m_kRiff, sizeof(RIFF_HEADER), p_sBuffer );
if( memcmp( m_kRiff.szRiffID, "RIFF", 4 ) != 0 || memcmp( m_kRiff.szRiffFormat, "WAVE", 4 ) != 0 )
{
LOGE("JCWaveInfo::LoadData No a vaild wave file!\n");
return false;
}
m_nCurPos += sizeof(RIFF_HEADER);
}
//读取格式
{
read( &m_kFmtBlock.szFmtID, 4, p_sBuffer );
m_nCurPos += 4;
read( &m_kFmtBlock.dwFmtSize, 4, p_sBuffer );
m_nCurPos += 4;
if( memcmp(m_kFmtBlock.szFmtID, "fmt ", 4) !=0 )
{
LOGE("JCWaveInfo::LoadData we only support follow format" );
return false;
}
if( m_kFmtBlock.dwFmtSize != 18 && m_kFmtBlock.dwFmtSize != 16 )
{
LOGE("JCWaveInfo::LoadData we only support Format: linear PCM size = %d",m_kFmtBlock.dwFmtSize );
return false;
}
if( m_kFmtBlock.dwFmtSize == 16 )
{
read(&m_kFmtBlock.wavFormat, 16, p_sBuffer );
m_nCurPos += 16;
}
else if( m_kFmtBlock.dwFmtSize == 18 )
{
read(&m_kFmtBlock.wavFormat, 18, p_sBuffer );
m_nCurPos += 18;
}
/*
if( m_kFmtBlock.wavFormat.dwSamplesPerSec != 22050 )
{
LOGE("we only support Samples Rate: 22050 KHz" );
return false;
}
if( m_kFmtBlock.wavFormat.wChannels != 0x1 )
{
LOGE("we only support one channel" );
return false;
}
if( m_kFmtBlock.wavFormat.wBitsPerSample != 16 )
{
LOGE("we only support BitsPerSample: 16" );
return false;
}
if( m_kFmtBlock.wavFormat.wFormatTag != 0x1 )
{
LOGE("we only support wFormatTag != 0x1" );
return false;
}
*/
}
/*
//读取无用信息 改到下面循环查找了
{
//试图读取fact
read(&m_kFact, sizeof(FACT_BLOCK), p_sBuffer);
if (memcmp(m_kFact.szFactID, "fact", 4) == 0)
{
m_nCurPos += sizeof(FACT_BLOCK);
read(&m_vFackBlockBuffer, m_kFact.dwFactSize, p_sBuffer);
m_nCurPos += m_kFact.dwFactSize;
}
//试图读取JUNK
read(&m_kJunkBlock, sizeof(_JUNK_BLOCK), p_sBuffer);
if (memcmp(m_kJunkBlock.szJUNK, "JUNK", 4) == 0)
{
m_nCurPos += sizeof(_JUNK_BLOCK) + m_kJunkBlock.dwJunkSize;
}
//试图读取FLLR
read(&m_kJunkBlock, sizeof(_JUNK_BLOCK), p_sBuffer);
if (memcmp(m_kJunkBlock.szJUNK, "FLLR", 4) == 0)
{
m_nCurPos += sizeof(_JUNK_BLOCK) + m_kJunkBlock.dwJunkSize;
}
}
*/
bool bResult = false;
int nSize = p_nBufferSize - sizeof(DATA_BLOCK);
while( m_nCurPos < nSize )
{
read( &m_kDataBlock, sizeof(DATA_BLOCK), p_sBuffer );
if ( memcmp( m_kDataBlock.szDataID, "data", 4 ) == 0 )
{
m_kDataBlock.dwDataSize /= 2;
m_nCurPos += sizeof(DATA_BLOCK);
bResult = true;
break;
}
else
{
m_nCurPos += sizeof(DATA_BLOCK) + m_kDataBlock.dwDataSize;
}
}
if (bResult == false)
{
LOGE("JCWaveInfo::LoadData parse wav error");
return false;
}
//拿出data数据
m_nRealDataSize = m_kDataBlock.dwDataSize * 2;
m_pData = new U8[m_nRealDataSize];
for( unsigned int i =0; i< m_kDataBlock.dwDataSize; i++ )
{
U8 n1 = (U8) getC( p_sBuffer );
m_nCurPos ++;
U8 n2 = (U8) getC( p_sBuffer );
m_nCurPos ++;
m_pData[i*2+0] = n1;
m_pData[i*2+1] = n2;
}
return true;
}
//------------------------------------------------------------------------------
void JCWaveInfo::read( void* pRet, int p_nSize,unsigned char* p_sBuffer )
{
unsigned char* p = p_sBuffer + m_nCurPos;
memcpy( pRet,(void*)(p),p_nSize );
}
//------------------------------------------------------------------------------
unsigned char JCWaveInfo::getC( unsigned char* p_sBuffer )
{
return p_sBuffer[m_nCurPos];
}
//------------------------------------------------------------------------------
}
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,136 @@
/**
@file JCWaveInfo.h
@brief
@author James
@version 1.0
@date 2014_11_26
*/
#ifndef __JCWaveInfo_H__
#define __JCWaveInfo_H__
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <string>
namespace laya
{
typedef unsigned char U8;
typedef unsigned short U16;
typedef unsigned int U32;
typedef unsigned long U64;
#pragma pack(push,1)
typedef struct _RIFF_HEADER
{
U8 szRiffID[4]; // 'R','I','F','F'
U32 dwRiffSize;
U8 szRiffFormat[4]; // 'W','A','V','E'
}RIFF_HEADER;
typedef struct _WAVE_FORMAT
{
U16 wFormatTag;
U16 wChannels;
U32 dwSamplesPerSec;
U32 dwAvgBytesPerSec;
U16 wBlockAlign;
U16 wBitsPerSample;
U16 pack; //附加信息
}WAVE_FORMAT;
typedef struct _FMT_BLOCK
{
U8 szFmtID[4]; // 'f','m','t',' '
U32 dwFmtSize;
WAVE_FORMAT wavFormat;
}FMT_BLOCK;
typedef struct _FACT_BLOCK
{
U8 szFactID[4]; // 'f','a','c','t'
U32 dwFactSize;
}FACT_BLOCK;
typedef struct _JUNK_BLOCK
{
U8 szJUNK[4];
U32 dwJunkSize;
}JUNK_BLOCK;
typedef struct _DATA_BLOCK
{
U8 szDataID[4]; // 'd','a','t','a'
U32 dwDataSize;
}DATA_BLOCK;
#pragma pack(pop)
/**
* @brief
*/
class JCWaveInfo
{
public:
/** @brief构造函数
*/
JCWaveInfo( void );
/** @brief析构函数
*/
~JCWaveInfo( void );
/** @brief 加载数据
* @param[in] 文件名
* @return true 代表读取成功 false代表失败
*/
bool LoadData( const char* p_sFileName );
/** @brief 加载数据
* @param[in] buffer数据
* @param[in] 长度
* @return true 代表读取成功 false代表失败
*/
bool LoadData( unsigned char* p_sBuffer,int p_nBufferSize );
private:
unsigned char getC( unsigned char* p_sBuffer );
void read( void* pRet, int p_nSize, unsigned char* p_sBuffer );
public:
char m_vFackBlockBuffer[20]; //FackBlockBuffer
RIFF_HEADER m_kRiff; //数据头
FMT_BLOCK m_kFmtBlock; //fmt
DATA_BLOCK m_kDataBlock; //数据
U32 m_nRealDataSize; //数据长度
U8* m_pData; //数据
int m_nCurPos; //当前位置
void* m_pExternalMark; //外部标记,现在目的是为了存储JSAudio的指针,为了能够回调JS,或者想存储你想存储的数据
std::string m_sUrl; //url
double m_nTouchTime; //时间戳
//FACT_BLOCK m_kFact; //fact
//JUNK_BLOCK m_kJunkBlock; //JunkBlock
};
}
#endif //__JCWaveInfo_H__
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,90 @@
/**
@file JCWaveParser.cpp
@brief
@author James
@version 1.0
@date 2014_11_26
*/
#include "JCWaveParser.h"
#pragma warning (disable: 4996)
namespace laya
{
//------------------------------------------------------------------------------
JCWaveParser* JCWaveParser::m_sWaveParser = NULL;
//------------------------------------------------------------------------------
JCWaveParser::JCWaveParser()
{
}
//------------------------------------------------------------------------------
JCWaveParser::~JCWaveParser()
{
}
//------------------------------------------------------------------------------
JCWaveParser* JCWaveParser::GetInstance( void )
{
if( m_sWaveParser == NULL )
{
m_sWaveParser = new JCWaveParser();
}
return m_sWaveParser;
}
//-----------------------------------------------------------------------------
void JCWaveParser::DelInstance( void )
{
}
//------------------------------------------------------------------------------
JCWaveInfo* JCWaveParser::GetWaveInfoFromFile( const char* p_sFileName )
{
JCWaveInfo* pWaveInfo = new JCWaveInfo();
bool bRet = pWaveInfo->LoadData( p_sFileName );
if( bRet )
{
return pWaveInfo;
}
return NULL;
}
//------------------------------------------------------------------------------
JCWaveInfo* JCWaveParser::GetWaveInfoFromBuffer( unsigned char* p_sBuffer, int p_nBufferSize )
{
JCWaveInfo* pWaveInfo = new JCWaveInfo();
bool bRet = pWaveInfo->LoadData( p_sBuffer,p_nBufferSize );
if( bRet )
{
return pWaveInfo;
}
return NULL;
}
//------------------------------------------------------------------------------
void JCWaveParser::TestWave( const char* p_sFileName,const char* p_sOutFileName )
{
JCWaveInfo* pInfo = GetWaveInfoFromFile( p_sFileName );
if( pInfo )
{
FILE* fp = fopen( p_sOutFileName,"a+" );
char sBuf[128];
fputs( "{", fp );
for( unsigned int i = 0 ; i < pInfo->m_nRealDataSize; i++ )
{
memset( sBuf,0,128 );
if( i == pInfo->m_nRealDataSize -1 )
{
sprintf( sBuf,"%d", pInfo->m_pData[i] );
}
else
{
sprintf( sBuf,"%d,", pInfo->m_pData[i] );
}
fputs( sBuf,fp );
}
fputs( "};", fp );
fclose( fp );
}
}
}
//-----------------------------END FILE--------------------------------
@@ -0,0 +1,68 @@
/**
@file JCWaveParser.h
@brief
@author James
@version 1.0
@date 2014_11_26
*/
#ifndef __JCWaveParser_H__
#define __JCWaveParser_H__
#include "JCWaveInfo.h"
/**
* @brief 读取wav文件 目前只支持
* 单声道
* 16位
* 采样级别 8000
* 音频格式 PCM
*/
namespace laya
{
class JCWaveParser
{
public:
/** @brief构造函数
*/
JCWaveParser( void );
/** @brief析构函数
*/
~JCWaveParser( void );
/*
* getInstace()
*/
static JCWaveParser* GetInstance( void );
static void DelInstance( void );
/*
* 从文件中读取wave数据
*/
JCWaveInfo* GetWaveInfoFromFile( const char* p_sFileName );
/*
* 从数据中读取wave
*/
JCWaveInfo* GetWaveInfoFromBuffer( unsigned char* p_sBuffer, int p_nBufferSize );
/**
* @brief 测试用的
*/
void TestWave( const char* p_sFileName,const char* p_sOutFileName );
protected:
static JCWaveParser* m_sWaveParser; //静态的this指针
};
}
#endif //__JCWaveParser_H__
//-----------------------------END FILE--------------------------------