应shenqiren朋友的要求,我贴一段我自己播放OGG音乐的代码。 我的代码没经过仔细的设计,写的也很随意,希望大家帮我修正一下。 (写的时候参考了粘土游戏库的代码)。
头文件:
#include <dsound.h> #include <assert.h> #include <math.h> #include <ogg/ogg.h> #include <vorbis/codec.h> #include <vorbis/vorbisfile.h> #include <mmsystem.h> #pragma comment(lib,"dsound.lib") #pragma comment(lib,"dxguid.lib") #pragma comment(lib,"winmm.lib") class ljmMusicBuffer_DSound : public ljmMusicBuffer { public: ljmMusicBuffer_DSound(IDirectSound8* pDS); ~ljmMusicBuffer_DSound(); bool LoadOggFile(const char* szFileName); void Play(bool bLoop); void Stop(void); void Pause(void); void Reset(void); void SetVolume(float vol); bool IsPlaying(void); protected: LPDIRECTSOUND8 m_pDS; LPDIRECTSOUNDBUFFER m_pBuffer; LONG m_lVolume; WAVEFORMATEX m_wfx; DWORD m_dwWritePos; OggVorbis_File* m_pVorbisFile; string m_strCurFile; bool m_bMono ; long m_lRate; int current_section; bool m_bLoop; bool m_bFinished; // static const int BUFFERSIZE = 8192; UINT m_TimerID; void Clear(void); void FillBuffer(void); static void CALLBACK OnTimerCB(UINT uID, UINT uMsg,DWORD_PTR pUserData, DWORD_PTR dwParam1, DWORD_PTR dwParam2); };
| 函数体
ljmMusicBuffer_DSound::ljmMusicBuffer_DSound(IDirectSound8* pDS) :m_pDS(pDS) ,m_pBuffer(NULL) ,m_TimerID(0) ,m_pVorbisFile(NULL) ,m_bLoop(false) ,m_bFinished(false) { }
ljmMusicBuffer_DSound::~ljmMusicBuffer_DSound() { Stop(); Clear(); } void ljmMusicBuffer_DSound:lay(bool bLoop) { if(!m_pBuffer) return; m_bLoop = bLoop; if(IsPlaying()) Stop();
m_dwWritePos = 0; FillBuffer(); FillBuffer();
m_pBuffer->lay(0,0,DSBPLAY_LOOPING); m_bFinished = false; m_TimerID = timeSetEvent(500,0,OnTimerCB,(DWORD_PTR)this,TIME_PERIODIC); }
void ljmMusicBuffer_DSound::Stop(void) { timeKillEvent(m_TimerID); Reset(); m_bFinished = true; } void ljmMusicBuffer_DSound:ause(void) { m_pBuffer->Stop(); } void ljmMusicBuffer_DSound::Reset(void) { if(!m_pBuffer) return; m_pBuffer->Stop(); m_pBuffer->SetCurrentPosition(0); m_dwWritePos = 0; if(m_pVorbisFile) ov_pcm_seek(m_pVorbisFile,0); } void ljmMusicBuffer_DSound::SetVolume(float vol) { //vol 为 0.0f~1.0f , DSound的单位是分贝 if (vol > 0) { m_lVolume = (LONG)(log10(vol) * 2000.0f); } else { m_lVolume = -10000; } if(!m_pBuffer) return;
m_pBuffer->SetVolume((LONG)vol); } bool ljmMusicBuffer_DSound::IsPlaying(void) { DWORD dwStatus; if(!m_pBuffer) return false; m_pBuffer->GetStatus(&dwStatus); return (dwStatus & DSBSTATUS_PLAYING); } void ljmMusicBuffer_DSound::Clear(void) { SAFE_RELEASE(m_pBuffer); if(m_pVorbisFile) { ov_clear(m_pVorbisFile); delete m_pVorbisFile; m_pVorbisFile = NULL; } }
|
bool ljmMusicBuffer_DSound:oadOggFile(const char* szFileName) { Stop(); Clear(); if(m_strCurFile == szFileName) return true; FILE* pFile = fopen(szFileName,"rb"); if(!pFile) return false; if(m_pVorbisFile) { ov_clear(m_pVorbisFile); delete m_pVorbisFile; } m_pVorbisFile = new OggVorbis_File; memset(m_pVorbisFile,0,sizeof(OggVorbis_File)); ov_clear(m_pVorbisFile); if( 0!=ov_open(pFile,m_pVorbisFile,NULL,0) ) { ov_clear(m_pVorbisFile); delete m_pVorbisFile; return false; } if(m_pVorbisFile->vi->channels == 1) { m_bMono = true; } else { m_bMono = false; }
m_lRate = m_pVorbisFile->vi->rate; // WAVEFORMATEX wfx;
m_wfx.wFormatTag = WAVE_FORMAT_PCM; m_wfx.nSamplesPerSec = (DWORD)m_lRate; m_wfx.wBitsPerSample = 16; m_wfx.cbSize = sizeof(WAVEFORMATEX); if(m_bMono) { m_wfx.nChannels = 1; } else { m_wfx.nChannels = 2; } m_wfx.nBlockAlign = m_wfx.nChannels * m_wfx.wBitsPerSample / 8; m_wfx.nAvgBytesPerSec = m_wfx.nSamplesPerSec * m_wfx.nBlockAlign; DSBUFFERDESC dsbd; ZeroMemory(&dsbd,sizeof(DSBUFFERDESC)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = 0;//DSBCAPS_CTRLVOLUME; dsbd.dwBufferBytes = m_wfx.nAvgBytesPerSec * 2; dsbd.guid3DAlgorithm = GUID_NULL; dsbd.lpwfxFormat = &m_wfx;
HRESULT hr; if(FAILED( hr = m_pDS->CreateSoundBuffer(&dsbd,&m_pBuffer,NULL))) { ov_clear(m_pVorbisFile); delete m_pVorbisFile; return false; } return true; }
void ljmMusicBuffer_DSound::FillBuffer(void) { HRESULT hr; VOID* pDSLockedBuffer = NULL; // Pointer to locked buffer memory DWORD dwDSLockedBufferSize = 0; // Size of the locked DirectSound buffer DWORD dwWavDataRead = 0; // Amount of data read from the wav file LPDIRECTSOUNDBUFFER pDSB = m_pBuffer; BOOL bRepeatWavIfBufferLarger = FALSE;
if( pDSB == NULL ) return ; // Make sure we have focus, and we didn't just switch in from // an app which had a DirectSound device //if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) ) // return hr; // int buffer_size; long bytes_read;
size_t length = m_wfx.nAvgBytesPerSec / 2; char* buffer = new char[length];
long leave = (long)length; long cur_pos = 0; do { bytes_read = ov_read(m_pVorbisFile, buffer+cur_pos, (int)leave,0/*endian*/, 2/*16-bit*/,1/*signed*/, ¤t_section); leave -= bytes_read; cur_pos += bytes_read; if(bytes_read<=0) break; }while(leave>0); bytes_read = cur_pos;
DWORD dwOffset = (DWORD)length * m_dwWritePos; // Lock the buffer down if( FAILED( hr = pDSB->Lock( dwOffset , (DWORD)length, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ) ) ) { delete buffer; return ; }
memcpy(pDSLockedBuffer,buffer,(size_t)bytes_read); if((size_t)bytes_read<length) { memset((char*)pDSLockedBuffer + bytes_read,0, length-(size_t)bytes_read); if(m_bLoop) { ov_pcm_seek(m_pVorbisFile,0); } else { m_bFinished = true; } } m_dwWritePos++; m_dwWritePos %= 4;
// Unlock the buffer, we don't need it anymore. pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );
delete buffer;
} void CALLBACK ljmMusicBuffer_DSound::OnTimerCB( UINT uID, UINT uMsg, DWORD_PTR pUserData, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { ljmMusicBuffer_DSound* pObj = (ljmMusicBuffer_DSound*)pUserData; if(pObj) { if(pObj->m_bFinished) { pObj->Stop(); } else { pObj->FillBuffer(); } } }
| 本主题包含附件: sf_2006415151621.rar (308040bytes)
|