kenlistian

厚积薄发. 勤为桨,思为帆

   :: 首页 :: 新随笔 ::  :: 聚合  :: 管理 ::
  73 随笔 :: 4 文章 :: 22 评论 :: 0 Trackbacks

1、配置DirectDound的开发环境
包含以下
#include <mmsystem.h>
#include <dsound.h>
添加Dsound.lib库
comctl32.lib dxerr9.lib winmm.lib dsound.lib dxguid.lib odbc32.lib odbccp32.lib,

2 DiectDound几个对象
 
  创建一个设备对象,后通过设备对象创建缓冲区对象。
  辅助缓冲区由应用程序创建和管理,DirectSound会自动地创建和管理主缓冲区,


3 播放音频文件开发的基本流程

 a 创建一个设备对象,设置设备对象的协作度。

    调用DirectSoundCreat8创建一个支持IDirectSound8接口的对象,
      这个对象通常代表缺省的播放设备。
   
       如果没有声音输出设备,这个函数就返回error,或者,在VXD驱动程序下,
      如果声音输出设备正被某个应用程序通过waveform格式的api函数所控制,
      该函数也返回error。 

LPDIRECTSOUND8 lpDirectSound; 
HRESULT hr 
= DirectSoundCreate8(NULL,&lpDirectSound, NULL));

      当创建完设备对象后,调用IDirectSound8::SetCooperativeLevel来设置
      协作度,否则听不到声音.

  b.创建一个辅助Buffer,也叫后备缓冲区
      (IDirectSound8::CreateSoundBuffer)
      创建的buffer称作辅助缓冲区,Direcsound通过把几个后备缓冲区的声音
      混合到主缓冲区中,然后输出到声音输出设备上,达到混音的效果。

  c. 获取PCM类型的数据
   
  将WAV文件或者其他资源的数据读取到缓冲区中。

  d. 将数据读取到缓冲区
       其中用到以下来锁缓冲区。
          IDirectSoundBuffer8::Lock
          IDirectSoundBuffer8::Unlock.

  e. 播放缓冲区中的数据
       IDirectSoundBuffer8::Play  播放缓冲区中的音频数据,
       IDirectSoundBuffer8::Stop 暂停播放数据,
       
       获取或者设置正在播放的音频的音量的大小
   IDirectSoundBuffer8::GetVolume
         IDirectSoundBuffer8::SetVolume

      获取设置音频播放的频率
    IDirectSoundBuffer8::GetFrequency
         IDirectSoundBuffer8::SetFrequency   
              主缓冲区的频率不允许改动,

      设置音频在左右声道播放的位置
          IDirectSoundBuffer8::GetPan
          IDirectSoundBuffer8::SetPan

  包含全部音频数据的缓冲区我们称为静态的缓冲区,
        尽管不同的声音可能会反复使用同一个内存buffer,但静态缓冲区的数据只写入一次。

        静态缓冲区只填充一次数据,然后就可以play,
 
  给静态缓冲区加载数据分下面几个步骤
  1、用IDirectSoundBuffer8::Lock函数来锁定所有的内存,
            指定你锁定内存中你开始写入数据的偏移位置,并且取回该偏移位置的地址。
  2、采用标准的数据copy方法,将音频数据复制到返回的地址。
  3、调用IDirectSoundBuffer8::Unlock.,解锁该地址。


用static buffer 播放wav方法

  

 

LPDIRECTSOUNDBUFFER8    g_pDSBuffer8 = NULL; //buffer
LPDIRECTSOUND8                   g_pDsd = NULL; //dsound
CWaveFile                                   *g_pWaveFile= NULL;

//初始化DirectSound工作
HRESULT hr;
if(FAILED(hr = DirectSoundCreate8(NULL,&g_pDsd,NULL)))
 
return FALSE;

//设置设备的协作度
if(FAILED(hr = g_pDsd->SetCooperativeLevel(m_hWnd,DSSCL_PRIORITY)))
 
return FALSE;

g_pWaveFile 
= new CWaveFile;
g_pWaveFile
->Open(_T("c:\\test.wav"), NULL, WAVEFILE_READ);

DSBUFFERDESC dsbd;
ZeroMemory( 
&dsbd, sizeof(DSBUFFERDESC) );
dsbd.dwSize 
= sizeof(DSBUFFERDESC);
dsbd.dwFlags 
= DSBCAPS_GLOBALFOCUS               //设置主播
                                | DSBCAPS_CTRLFX
                                
| DSBCAPS_CTRLPOSITIONNOTIFY 
                                
| DSBCAPS_GETCURRENTPOSITION2;

dsbd.dwBufferBytes 
= g_pWaveFile->GetSize();    
dsbd.lpwfxFormat 
= g_pWaveFile->m_pwfx;

LPDIRECTSOUNDBUFFER lPBuffer;

//创建辅助缓冲区对象
if(FAILED(hr = g_pDsd->CreateSoundBuffer(&dsbd,&lpbuffer,NULL)))
 
return ;
if( FAILED(hr = lpbuffer->QueryInterface( IID_IDirectSoundBuffer8, (LPVOID*&g_pDSBuffer8) ) )
 
return ; 
lpbuffer
->Release();

//播放
LPVOID lplockbuf;
DWORD len;
DWORD dwWrite;

g_pDSBuffer8
->Lock(0,0&lplockbuf,  &len,  NULL,  NULL, DSBLOCK_ENTIREBUFFER);

//g_pWaveFile 声音写入到lplockbuf所指地址
g_pWaveFile->Read((BYTE*)lplockbuf, len, &dwWrite);

g_pDSBuffer8
->Unlock(lplockbuf,len,NULL,0);

g_pDSBuffer8
->SetCurrentPosition(0);

g_pDSBuffer8
->Play(0,0,DSBPLAY_LOOPING);




   f  流缓冲区播放超大型的wave文件

   流缓冲区就是播放那些比较长的音频文件,边播放,边填充DirectSound缓冲区。

   DirectSound的通知机制
      因为Stream buffer 大小只够容纳一部分数据,在播放完缓冲区中的数据后,
      DirectSound就会通知应用程序,将新的数据填充到DirectSound的缓冲区中。

 

 

#define MAX_AUDIO_BUF 4                        //设置4个buffer
#define BUFFERNOTIFYSIZE 1920               //每个buffer尺寸为1920

BOOL g_bPlaying     
= FALSE;                                            //是否正在播放
LPDIRECTSOUNDNOTIFY8 g_pDSNotify = NULL; 
DSBPOSITIONNOTIFY        g_aPosNotify[MAX_AUDIO_BUF];     
//设置通知标志的数组

HANDLE g_event[MAX_AUDIO_BUF];
for(int i =0; i< MAX_AUDIO_BUF;i++)
{
 g_aPosNotify[i].dwOffset 
= i* BUFFERNOTIFYSIZE ;   
    g_aPosNotify[i].hEventNotify 
= g_event[i];
}

if(FAILED(hr = g_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID *&g_pDSNotify )))
 
return ;

g_pDSNotify
->SetNotificationPositions(MAX_AUDIO_BUF,g_aPosNotify);

g_pDSNotify
->Release();


     当DirectSound播放到buffer的1920,3840,5760,7680等位置时,
Directsound就会通知应用程序,将g_event,设置为通知态;
  应用程序就通过WaitForMultipleObjects 函数等待DirectSound的通知,
将数据填充到DirectSoun的辅助缓冲区。

 


 

posted on 2008-12-27 18:30 kenlistian 阅读(2872) 评论(1)  编辑 收藏 引用 所属分类: directx

评论

# re: directsound的一些基本札记 2009-02-25 12:17 Ian
请问主人“用static buffer 播放wav方法” 那一段代码编译过没有?代码好像有问题,没有声音。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理