【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2754|回复: 0

[转帖]用DirectSound播放OGG格式的音乐

[复制链接]
发表于 2006-9-27 15:36:57 | 显示全部楼层 |阅读模式
应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*/,
                                                        &current_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)

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 04:01

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表