DirectSound之播放聲音

DirectSound之播放聲音

DirectSound顧明思義可以讓你控制聲卡播放聲音和音樂. DirectSound由許多模塊和接口組成,編譯時需要庫文檔DSOUND.LIB和頭文檔DSOUND.H

WAV音檔播放演示程式,按+/-鍵控制聲音音量.按Open載入WAV音檔:下載

1.啟動DirectSound

IDirectSound接口:DirectSound的主COM對象.它代表聲卡硬件.若你裝有多個聲卡,則每個DirectSound對象代表一個聲卡.創建主聲卡對象,輸入NULL與默認聲卡鏈接

LPDIRECTSOUND       direct_sound;

DirectSoundCreate(NULL,&direct_sound,NULL);

if (direct_sound == NULL)

return false;

2.設置默認協作等級

設定遊戲控制聲卡的等級.一般設定為DSSCL_NORMAL即可.當程式具有焦點時,即可播放聲音.但並不妨礙其它程式. DirectSound自動創建22kHz,立體聲,8bit主緩存(默認).hWnd為當前窗口句柄

direct_sound->SetCooperativeLevel(hWnd,DSSCL_NORMAL);

參數 簡介
DSSCL_NORMAL 默認等級
DSSCL_PRIORITY 優先等級.允許設定主緩存數據格式
DSSCL_EXCLUSIVE 當窗口在前臺時擁有優先等級
DSSCL_WRITEPRIMARY 完全控制主緩存

3.輔助(二級)音頻緩存

『輔助緩存』即代表你想播放的音頻.但聲卡上SRAM卻容量有限,而且我印象中只在ISA版CREATIVE(創新)聲卡有出現.『輔助緩存』分為『靜態緩存』與『動態緩存』.『靜態緩存』用於存儲經常播放短聲音.『動態緩存』用於存儲較長聲音.DirectSound不斷播放不斷把音頻數據寫入『輔助緩存』.使用稱為Circular Buffering(環形緩存)結構,一個指針寫入音頻數據,另一個指針讀取音頻數據.創建輔助聲音緩衝器

HRESULT IDirectSound::CreateSoundBuffer(

LPCDSBUFFERDESC lpcDSBufferDesc,

LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer,

IUnknown FAR* pUnkOuter

);

4.設置緩存格式描敘,單聲道11kHz,8bit

AVEFORMATEX format;

format.cbSize = 0;//高級,總是0.

format.wFormatTag = WAVE_FORMAT_PCM;//PCM編碼

format.nChannels = 1;//(聲道數目)1為單聲道播放

format.nSamplesPerSec = 11025;// 樣本速度11kHz

//設置字節對齊.

//單聲道乘以1字節(8Bit), 它將是1字節字節對齊.

//立體聲它將是雙聲道8Bit, 它將是2字節字節對齊.

//如果它是立體聲系統和16Bit它將是4字節對齊.

format.nBlockAlign     = 1;

format.wBitsPerSample = 8;//聲言位數為8BIT

format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;// 每秒字節

3.設定聲音緩沖存儲器描敘表

DSBUFFERDESC buffer;// 描述結構

memset(&buffer,0,sizeof(DSBUFFERDESC));// 清零

buffer.dwSize = sizeof(DSBUFFERDESC);// 結構所占空間

//設置DirectSoundBuffer的描述結構的標誌

buffer.dwFlags = DSBCAPS_CTRLPAN | // 緩存擁有總控制功能

DSBCAPS_CTRLVOLUME | // 緩存擁有音量控制功能

DSBCAPS_CTRLFREQUENCY; // 緩存擁有頻率控制功能

buffer.dwBufferBytes = sound_size;//聲音數據大小.

buffer.lpwfxFormat  = &format;//”WAV文件格式描述結構”

4.創建輔助(二級)音頻緩存

LPDIRECTSOUNDBUFFER sound_buffer;

direct_sound->CreateSoundBuffer(&buffer, &sound_buffer, NULL);

if (sound_buffer == NULL)

return false;

5.鎖住緩存

UCHAR *audio_ptr_1 = NULL, //指向緩存第一部分

UCHAR *audio_ptr_2 = NULL; //指向緩存第二部分

DWORD  audio_len_1 = 0,  //第一緩存長度

DWORD  audio_len_2 = 0;  //第二緩存長度

sound_buffer->Lock(0,//寫入指針指向位置

sound_size,//要鎖定大小,音頻數據長度.

(void **)&audio_ptr_1,//第一個部分開始地址.

&audio_len_1,//第一個部分長度

(void **)&audio_ptr_2,//第二個部分開始地址.

&audio_len_2,//第二個部分長度

DSBLOCK_FROMWRITECURSOR);// 緩存當前寫入點將被鎖住.

6.拷貝到環形緩存第一部分, sound_size為音頻數據

memcpy(audio_ptr_1, sound_data, audio_len_1);

7.拷貝到環形緩存第二段中

memcpy(audio_ptr_2, (sound_data + audio_len_1), audio_len_2);

8.解鎖

sound_buffer->Unlock(audio_ptr_1,audio_len_1,audio_ptr_2,audio_len_2);

9.循環播放聲音

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

10.若單次播放聲音

sound_buffer->Play(0, 0, 0);

11.當退出遊戲時需要釋放緩存和聲卡

sound_buffer->Release();

direct_sound->Release();

發佈留言