游戏开发论坛

 找回密码
 立即注册
搜索
查看: 13232|回复: 28

用DirectSound播放OGG格式的音乐

[复制链接]

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
发表于 2006-4-14 19:37:00 | 显示全部楼层 |阅读模式
应shenqiren朋友的要求,我贴一段我自己播放OGG音乐的代码。
我的代码没经过仔细的设计,写的也很随意,希望大家帮我修正一下。
(写的时候参考了粘土游戏库的代码)。

头文件:



  1. #include <dsound.h>

  2. #include <assert.h>
  3. #include <math.h>

  4. #include <ogg/ogg.h>
  5. #include <vorbis/codec.h>
  6. #include <vorbis/vorbisfile.h>

  7. #include <mmsystem.h>

  8. #pragma comment(lib,"dsound.lib")
  9. #pragma comment(lib,"dxguid.lib")
  10. #pragma comment(lib,"winmm.lib")



  11. class ljmMusicBuffer_DSound : public ljmMusicBuffer
  12. {
  13. public:
  14.         ljmMusicBuffer_DSound(IDirectSound8* pDS);
  15.         ~ljmMusicBuffer_DSound();

  16.         bool LoadOggFile(const char* szFileName);

  17.         void Play(bool bLoop);
  18.         void Stop(void);

  19.         void Pause(void);
  20.         void Reset(void);

  21.         void SetVolume(float vol);
  22.         bool IsPlaying(void);

  23. protected:
  24.         LPDIRECTSOUND8               m_pDS;
  25.         LPDIRECTSOUNDBUFFER    m_pBuffer;

  26.         LONG                   m_lVolume;

  27.         WAVEFORMATEX           m_wfx;
  28.         DWORD                  m_dwWritePos;

  29.         OggVorbis_File* m_pVorbisFile;
  30.         string m_strCurFile;
  31.         bool m_bMono ;
  32.         long m_lRate;

  33.         int  current_section;

  34.         bool m_bLoop;
  35.         bool m_bFinished;

  36. //        static const int BUFFERSIZE = 8192;

  37.         UINT m_TimerID;

  38.         void Clear(void);
  39.         void FillBuffer(void);
  40.         static void CALLBACK OnTimerCB(UINT uID, UINT uMsg,DWORD_PTR pUserData, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
  41. };


复制代码

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
 楼主| 发表于 2006-4-14 19:41:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐

函数体




  1. ljmMusicBuffer_DSound::ljmMusicBuffer_DSound(IDirectSound8* pDS)
  2. :m_pDS(pDS)
  3. ,m_pBuffer(NULL)
  4. ,m_TimerID(0)
  5. ,m_pVorbisFile(NULL)
  6. ,m_bLoop(false)
  7. ,m_bFinished(false)
  8. {
  9. }

  10. ljmMusicBuffer_DSound::~ljmMusicBuffer_DSound()
  11. {
  12.         Stop();
  13.         Clear();

  14. }


  15. void ljmMusicBuffer_DSound::Play(bool bLoop)
  16. {
  17.         if(!m_pBuffer)
  18.                 return;
  19.         m_bLoop = bLoop;
  20.         if(IsPlaying())
  21.                 Stop();


  22.         m_dwWritePos = 0;
  23.         FillBuffer();
  24.         FillBuffer();


  25.         m_pBuffer->Play(0,0,DSBPLAY_LOOPING);
  26.         m_bFinished = false;
  27.         m_TimerID = timeSetEvent(500,0,OnTimerCB,(DWORD_PTR)this,TIME_PERIODIC);
  28. }

  29. void ljmMusicBuffer_DSound::Stop(void)
  30. {
  31.         timeKillEvent(m_TimerID);
  32.         Reset();
  33.         m_bFinished = true;

  34. }

  35. void ljmMusicBuffer_DSound::Pause(void)
  36. {
  37.         m_pBuffer->Stop();
  38. }

  39. void ljmMusicBuffer_DSound::Reset(void)
  40. {
  41.         if(!m_pBuffer)
  42.                 return;
  43.         m_pBuffer->Stop();
  44.         m_pBuffer->SetCurrentPosition(0);
  45.         m_dwWritePos = 0;
  46.         if(m_pVorbisFile)
  47.                 ov_pcm_seek(m_pVorbisFile,0);
  48. }

  49. void ljmMusicBuffer_DSound::SetVolume(float vol)
  50. {
  51.         //vol 为 0.0f~1.0f , DSound的单位是分贝
  52.         if (vol > 0)
  53.         {
  54.                 m_lVolume = (LONG)(log10(vol) * 2000.0f);
  55.         }
  56.         else
  57.         {
  58.                 m_lVolume = -10000;
  59.         }


  60.         if(!m_pBuffer)
  61.                 return;

  62.         m_pBuffer->SetVolume((LONG)vol);
  63. }

  64. bool ljmMusicBuffer_DSound::IsPlaying(void)
  65. {
  66.         DWORD dwStatus;
  67.         if(!m_pBuffer)
  68.                 return false;

  69.         m_pBuffer->GetStatus(&dwStatus);
  70.         return (dwStatus & DSBSTATUS_PLAYING);

  71. }


  72. void ljmMusicBuffer_DSound::Clear(void)
  73. {
  74.         SAFE_RELEASE(m_pBuffer);
  75.         if(m_pVorbisFile)
  76.         {
  77.                 ov_clear(m_pVorbisFile);
  78.                 delete m_pVorbisFile;
  79.                 m_pVorbisFile = NULL;
  80.         }
  81. }


复制代码

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
 楼主| 发表于 2006-4-14 19:44:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐




  1. bool ljmMusicBuffer_DSound::LoadOggFile(const char* szFileName)
  2. {
  3.         Stop();
  4.         Clear();
  5.         if(m_strCurFile == szFileName)
  6.                 return true;

  7.         FILE* pFile = fopen(szFileName,"rb");
  8.         if(!pFile)
  9.                 return false;

  10.         if(m_pVorbisFile)
  11.         {
  12.                 ov_clear(m_pVorbisFile);
  13.                 delete m_pVorbisFile;
  14.         }
  15.         m_pVorbisFile = new OggVorbis_File;
  16.         memset(m_pVorbisFile,0,sizeof(OggVorbis_File));
  17.         ov_clear(m_pVorbisFile);

  18.         if( 0!=ov_open(pFile,m_pVorbisFile,NULL,0) )
  19.         {
  20.                 ov_clear(m_pVorbisFile);
  21.                 delete m_pVorbisFile;
  22.                 return false;
  23.         }


  24.         if(m_pVorbisFile->vi->channels == 1)
  25.         {
  26.                 m_bMono = true;
  27.         }
  28.         else
  29.         {
  30.                 m_bMono = false;
  31.         }

  32.         m_lRate = m_pVorbisFile->vi->rate;




  33. //        WAVEFORMATEX wfx;

  34.         m_wfx.wFormatTag     = WAVE_FORMAT_PCM;
  35.         m_wfx.nSamplesPerSec = (DWORD)m_lRate;
  36.         m_wfx.wBitsPerSample = 16;
  37.         m_wfx.cbSize                 = sizeof(WAVEFORMATEX);
  38.        
  39.         if(m_bMono)
  40.         {
  41.                 m_wfx.nChannels = 1;
  42.         }
  43.         else
  44.         {
  45.                 m_wfx.nChannels = 2;
  46.         }

  47.         m_wfx.nBlockAlign                = m_wfx.nChannels * m_wfx.wBitsPerSample / 8;
  48.         m_wfx.nAvgBytesPerSec        = m_wfx.nSamplesPerSec * m_wfx.nBlockAlign;




  49.         DSBUFFERDESC dsbd;
  50.         ZeroMemory(&dsbd,sizeof(DSBUFFERDESC));
  51.         dsbd.dwSize          = sizeof(dsbd);
  52.         dsbd.dwFlags         = 0;//DSBCAPS_CTRLVOLUME;
  53.         dsbd.dwBufferBytes   = m_wfx.nAvgBytesPerSec * 2;        dsbd.guid3DAlgorithm = GUID_NULL;
  54.         dsbd.lpwfxFormat     = &m_wfx;

  55.         HRESULT hr;
  56.         if(FAILED( hr = m_pDS->CreateSoundBuffer(&dsbd,&m_pBuffer,NULL)))
  57.         {
  58.                 ov_clear(m_pVorbisFile);
  59.                 delete m_pVorbisFile;
  60.                 return false;
  61.         }


  62.         return true;
  63. }


复制代码

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
 楼主| 发表于 2006-4-14 19:49:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐



  1. void ljmMusicBuffer_DSound::FillBuffer(void)
  2. {

  3.         HRESULT hr;
  4.         VOID*   pDSLockedBuffer      = NULL; // Pointer to locked buffer memory
  5.         DWORD   dwDSLockedBufferSize = 0;    // Size of the locked DirectSound buffer
  6.         DWORD   dwWavDataRead        = 0;    // Amount of data read from the wav file

  7.         LPDIRECTSOUNDBUFFER pDSB = m_pBuffer;
  8.         BOOL bRepeatWavIfBufferLarger = FALSE;
  9.        

  10.         if( pDSB == NULL )
  11.                 return ;

  12.         // Make sure we have focus, and we didn't just switch in from
  13.         // an app which had a DirectSound device
  14.         //if( FAILED( hr = RestoreBuffer( pDSB, NULL ) ) )
  15.         //        return hr;


  16. //        int  buffer_size;
  17.         long bytes_read;
  18.        

  19.         size_t length = m_wfx.nAvgBytesPerSec / 2;

  20.         char* buffer = new char[length];
  21.        
  22.         long leave = (long)length;
  23.         long cur_pos = 0;



  24.         do
  25.         {
  26.                 bytes_read = ov_read(m_pVorbisFile,
  27.                                                         buffer+cur_pos,
  28.                                                         (int)leave,0/*endian*/,
  29.                                                         2/*16-bit*/,1/*signed*/,
  30.                                                         &current_section);
  31.                 leave   -= bytes_read;
  32.                 cur_pos += bytes_read;
  33.                 if(bytes_read<=0)
  34.                         break;
  35.         }while(leave>0);

  36.         bytes_read = cur_pos;
  37.        
  38.         DWORD dwOffset = (DWORD)length * m_dwWritePos;


  39.         // Lock the buffer down
  40.         if( FAILED( hr = pDSB->Lock( dwOffset , (DWORD)length,
  41.                 &pDSLockedBuffer, &dwDSLockedBufferSize,
  42.                 NULL, NULL, 0L ) ) )
  43.         {
  44.                 delete buffer;
  45.                 return ;
  46.         }

  47.         memcpy(pDSLockedBuffer,buffer,(size_t)bytes_read);
  48.         if((size_t)bytes_read<length)
  49.         {
  50.                 memset((char*)pDSLockedBuffer + bytes_read,0,
  51.                                                                length-(size_t)bytes_read);
  52.                 if(m_bLoop)
  53.                 {
  54.                         ov_pcm_seek(m_pVorbisFile,0);
  55.                 }
  56.                 else
  57.                 {
  58.                         m_bFinished = true;
  59.                 }
  60.         }


  61.         m_dwWritePos++;
  62.         m_dwWritePos %= 4;


  63.         // Unlock the buffer, we don't need it anymore.
  64.         pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 );


  65.         delete buffer;

  66. }

复制代码

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
 楼主| 发表于 2006-4-14 19:53:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐



  1. void CALLBACK ljmMusicBuffer_DSound::OnTimerCB(
  2.                                 UINT uID, UINT uMsg,
  3.                                 DWORD_PTR pUserData,
  4.                         DWORD_PTR dwParam1,
  5.                                 DWORD_PTR dwParam2)
  6. {
  7.         ljmMusicBuffer_DSound* pObj = (ljmMusicBuffer_DSound*)pUserData;
  8.         if(pObj)
  9.         {
  10.                 if(pObj->m_bFinished)
  11.                 {
  12.                         pObj->Stop();
  13.                 }
  14.                 else
  15.                 {
  16.                         pObj->FillBuffer();
  17.                 }
  18.         }
  19. }

复制代码

28

主题

433

帖子

433

积分

中级会员

Rank: 3Rank: 3

积分
433
发表于 2006-4-15 08:40:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐

要工程 文件 和 原代码 ~~~

60

主题

1319

帖子

1319

积分

金牌会员

Rank: 6Rank: 6

积分
1319
 楼主| 发表于 2006-4-15 15:16:00 | 显示全部楼层

Re: 用DirectSound播放OGG格式的音乐

500K限制还挺麻烦的

sf_2006415151621.rar

300.82 KB, 下载次数:

16

主题

404

帖子

404

积分

中级会员

Rank: 3Rank: 3

积分
404
发表于 2006-4-15 20:38:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐

呵呵,感谢楼主!

12

主题

26

帖子

26

积分

注册会员

Rank: 2

积分
26
发表于 2006-4-16 09:24:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐

感谢感谢感感谢谢!!!

找了几天的ogg播放代码始终没找到,搜索ogg播放 全是关于播放器的  搜索ogg代码 全是关于ogg 开源的东西,    今天无意一搜发现了这篇
“用DirectSound播放OGG格式的音乐 - GameRes游戏开发..”
进来一看,原来楼主是写给我的,实在是高兴啊!

10

主题

149

帖子

149

积分

注册会员

Rank: 2

积分
149
QQ
发表于 2006-4-16 12:39:00 | 显示全部楼层

Re:用DirectSound播放OGG格式的音乐

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

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 14:04

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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