(一)DirectSound接口播放WAVE音频文件

来源:互联网 发布:汪小菲为什么选大s知乎 编辑:程序博客网 时间:2024/05/27 09:45

首先要声明三个接口,用于声音的播放

LPDIRECTSOUND8 g_pDirectSound=NULL;         //directSound接口

LPDIRECTSOUNDBUFFER     g_pPrimaryBuffer    =NULL;//主缓冲区接口

LPDIRECTSOUNDBUFFER8    g_pSecondaryBuffer  = NULL;//辅助缓冲区接口

 

建立一个结构体,标识wav文件的相关信息。

struct WAVEHEADER

{

    char    riff_sig[4];           // 'RIFF'

    long    waveform_chunk_size;   // 8

    char    wave_sig[4];           // 'WAVE'

   char   format_sig[4];         // 'fmt ' (notice space after)

    long    format_chunk_size;     // 16;

    short   format_tag;            //WAVE_FORMAT_PCM

    short   channels;              // #of channels

    long    sample_rate;           // samplingrate

    long    bytes_per_sec;         // bytesper second

    short   block_align;           // sampleblock alignment

    short   bits_per_sample;       // bits persecond

    char    data_sig[4];           // 'data'

    long    data_size;              // sizeof waveform data

};

附录:wav文件的格式http://wenku.baidu.com/view/801b1537f111f18583d05aa7.html

 

然后在初始化函数中,

//创建directsound接口

     if(FAILED(DirectSoundCreate8(NULL,&g_pDirectSound,NULL)))

         ::MessageBox(NULL,"Create DirectSound failed","DirectSoundCreate",0);

//设置 directsound协作级别

     if(FAILED(g_pDirectSound->SetCooperativeLevel(hWnd,DSSCL_NORMAL)))

         ::MessageBox(NULL,"Set cooperative level failed!","SetCooperativeLevel",0);

    //读取WAV音频信息

     WAVEHEADER wave_header;

     ::ZeroMemory(&wave_header, sizeof(WAVEHEADER));

     FILE* fp = fopen("example.wav","rb");

   fread((void*)&wave_header, 1, sizeof(WAVEHEADER), fp);

  //根据wav文件,赋值结构体

  WAVEFORMATEX  wave_format;

    ZeroMemory(&wave_format, sizeof(WAVEFORMATEX));

     wave_format.wFormatTag=WAVE_FORMAT_PCM;

     wave_format.nChannels=wave_header.channels;               //2声道

     wave_format.nSamplesPerSec=wave_header.sample_rate;     //44100Hz回放频率

     wave_format.wBitsPerSample=wave_header.bits_per_sample;       //16位采样

     wave_format.nBlockAlign=wave_format.wBitsPerSample/8*wave_format.nChannels;

     wave_format.nAvgBytesPerSec=wave_format.nSamplesPerSec*wave_format.nBlockAlign;


       DSBUFFERDESC  ds_buf_desc;

      ZeroMemory(&ds_buf_desc, sizeof(DSBUFFERDESC));

     ds_buf_desc.dwSize= sizeof(DSBUFFERDESC);

     ds_buf_desc.dwFlags=DSBCAPS_CTRLVOLUME;

     ds_buf_desc.dwBufferBytes=wave_header.data_size;         //缓冲区

    ds_buf_desc.lpwfxFormat=&wave_format;

 

   //创建主音频缓存和辅助音频缓存

   g_pDirectSound->CreateSoundBuffer(&ds_buf_desc,&g_pPrimaryBuffer, NULL);

   g_pPrimaryBuffer->QueryInterface(IID_IDirectSoundBuffer8, (void**)&g_pSecondaryBuffer);

 

     // 加载WAV音频数据到辅助缓冲区

    char  *ptr1, *ptr2;

    DWORD size1, size2;

 

    fseek(fp, sizeof(WAVEHEADER), SEEK_SET);

    g_pSecondaryBuffer->Lock(0,wave_header.data_size, (void**)&ptr1,&size1, (void**)&ptr2, &size2, 0);

 

    if(ptr1) fread(ptr1, 1, size1, fp);

    if(ptr2) fread(ptr2, 1, size2, fp);

 

   g_pSecondaryBuffer->Unlock(ptr1, size1, ptr2, size2);

     fclose(fp);

// 初始化时,音频数据放到了辅助缓冲区,辅助缓冲区与主缓冲区关联,主缓冲区与directsound接口关联

 

接着在渲染函数中播放声音

        static longlPan = 0, lVolume = DSBVOLUME_MAX;

         if(::GetAsyncKeyState(VK_LEFT) & 0x8000f)

              lPan -= 500,g_pSecondaryBuffer->SetPan(lPan); //声道控制

         if(::GetAsyncKeyState(VK_RIGHT) & 0x8000f)

              lPan += 500,g_pSecondaryBuffer->SetPan(lPan);

 

         if(::GetAsyncKeyState(VK_UP) & 0x8000f)

              lVolume += 500,g_pSecondaryBuffer->SetVolume(lVolume); //音量控制

         if(::GetAsyncKeyState(VK_DOWN) & 0x8000f)

              lVolume -= 500,g_pSecondaryBuffer->SetVolume(lVolume);

 

         if(::GetAsyncKeyState(VK_SPACE) & 0x8000f)

              g_pSecondaryBuffer->Play(0,0, DSBPLAY_LOOPING); //循环播放

         if(::GetAsyncKeyState('S') & 0x8000f)

              g_pSecondaryBuffer->Stop();               // 停止播放

 

最后释放掉directSound接口

If(g_pDirectSound!=NULL)

{

     g_pDirectSound->Release();

     g_pDirectSound=NULL;

}