DirectSound之3D狼嚎

DirectSound之3D狼嚎

經多日努力終於可以在3D空間中添加中添加3D效果,所帶來極強真實感效果有時比3D渲染更好.而且x86和x64均正確運行.在演示程式中.『狼嚎』放置於山地中心.隨著按方向鍵移動相機聲音產生變化.單這點很多書本例程均不正確. 3D狼嚎程式:下載

而DirectSound如何模擬3D效果.3D即有xyz三軸笛卡爾座標,以此定義聲源和聽者位置、速度、方向.要注意Z軸是指向屏幕內部.所以3D效果需單聲道.

typdef struct{

IDirectSoundBuffer       * buffer;  // 輔助緩存

IDirectSound3DBuffer8    * buffer3D;// 3D緩存

float x,y,z;// 音源3D位置

PBYTE data;// 音頻數據

int size;// 所占空間

}SOUND3D;

SOUND3D sound3D;

而一般我地有左右兩個音箱,最多四角四個音箱.要模擬3D感知效果要素如下:

  1. 響度:當聲源逐漸遠離聽者,聲源會逐漸衰減
  2. 兩耳聲響差:若聲源位於聽者右側,則右耳聽到聲響比左耳響.
  3. 兩耳時間差:若聲源位於聽者右側,則右耳比左耳早聽到一毫秒.
  4. 兩耳朝向:若聲源在前邊則比後邊響
  5. 聲音最大距離:大於此距離聲音不再衰減.默認為DS3D_DEFAULTMAXDISTANCE(109 m)
  6. 聲音最小距離:大於此距離聲音不再遞增.默認為DS3D_DEFAULTMINDISTANCE(1m)
  7. 默認模式: DS3DMODE_NORMAL使用3D座標設定音源位置
  8. 頭部模式: DS3DMODE_HEADRELATIVE.可以設定音源位置,但監聽位置總為(0,0,0)
  9. 禁用3D模式:DS3DMODE_DISABLE 禁用3D聲音

WAV數據載入』後交與DirectSound代碼如下:

1.創建聲卡接口,NULL為與默認聲卡鏈接

IDirectSound8 * direct_sound3D = NULL;// 默認聲卡接口

DirectSoundCreate8(NULL,&direct_sound3D,NULL);

2.設置為優先等級,允許設定主緩存音頻數據格式並獲取IDirectSound3DListener8接口

direct_sound3D->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);// 優先級別

3.初始化Directsound主緩存,主緩存代表聲卡,並設置格式

DSBUFFERDESC buffer;// 緩存格式描述

ZeroMemory(&buffer, sizeof(DSBUFFERDESC));// 清零

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

buffer.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;//3D緩存並使用聲卡緩存

4.創建默認聲卡緩存接口

IDirectSoundBuffer * DirectSound3D_Buffer = NULL;

direct_sound3D->CreateSoundBuffer(&buffer, &DirectSound3D_Buffer, NULL);

5.獲取3D空間『聽者』

IDirectSound3DListener8  * DirectSound3D_Listener;// 3D聽者

DirectSound3D_Buffer->QueryInterface(IID_IDirectSound3DListener, (VOID**)&DirectSound3D_Listener);

6.設置緩存數據格式

WAVEFORMATEX format;//緩存格式描敘

memset(&format, 0, sizeof(WAVEFORMATEX));

format.cbSize = 0;//總是0.

format.wFormatTag = WAVE_FORMAT_PCM;  //脈衝編碼格式

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

format.nSamplesPerSec = 11025;//(每秒的樣本)總是這個速度

format.wBitsPerSample = 8;//聲音為8Bit

format.nBlockAlign = 1;//字節對齊,單聲道8bit占1byte.雙聲道16bit占4yte.

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

DirectSound3D_Buffer->SetFormat(&format); //設置主緩存音頻格式

7.現在建立輔助聲音緩存

DSBUFFERDESC desc;// 緩存格式描敘

memset(&desc,0,sizeof(DSBUFFERDESC));

desc.dwSize = sizeof(DSBUFFERDESC);//dsbd的大小

desc.dwFlags = DSBCAPS_CTRL3D |// 請求3D BUFFER

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

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

DSBCAPS_GLOBALFOCUS |

DSBCAPS_CTRLPOSITIONNOTIFY |  // 3D位置

DSBCAPS_GETCURRENTPOSITION2; // 播放位置

desc.dwBufferBytes = sound3D->size;//聲音數據的大小.

desc.guid3DAlgorithm = DS3DALG_DEFAULT;// 主緩沖區在 DSBCAPS_CTRL3D 模式下可以啟用這個選項

desc.lpwfxFormat = &format;// 緩存數據格式

8.創建輔助聲音緩衝器

direct_sound3D->CreateSoundBuffer(&desc, &sound3D->buffer, NULL);

9.獲取3D空間緩存

sound3D->buffer->QueryInterface(IID_IDirectSound3DBuffer, (VOID**)&sound3D->buffer3D);

10.把數據寫入聲音輔助緩存,輔助(二級)聲音緩存是自循環

UCHAR  audio_ptr_1 = NULL,audio_ptr_2 = NULL; //指向緩存第一與第二部分

DWORD   audio_len_1 = 0, audio_len_2 = 0;  //第一與第二緩存長度

11.鎖住空間

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

sound3D->size,//要鎖定空間大小.

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

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

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

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

DSBLOCK_FROMWRITECURS );

11.複製數據到聲音緩沖存儲器,拷貝到圓形緩沖存儲器的第一段中

memcpy(audio_ptr_1, sound3D->data, audio_len_1);

12.拷貝到圓形緩沖存儲器的第二段中

memcpy(audio_ptr_2, (sound3D->data + audio_len_1), audio_len_2);

13.解鎖

sound3D->buffer->Unlock(audio_ptr_1, audio_len_1,audio_ptr_2, audio_len_2);

14.設置音源3D位置與距離

DS3DBUFFER  param;

memset(&param, 0, sizeof(DS3DBUFFER));

param.dwSize = sizeof(DS3DBUFFER);

sound3D->buffer3D->GetAllParameters(&param);

param.flMaxDistance = sound3D->max;// 聲音最大距離 DS3D_DEFAULTMAXDISTANCE

param.flMinDistance = sound3D->min;// 聲音最小距離 DS3D_DEFAULTMINDISTANCE

param.vPosition.x = x; //音源3D位置

param.vPosition.y = y;

param.vPosition.z = -z;// Z軸反轉

param.dwMode = DS3DMODE_NORMAL;// 默認,使用3D座標設定音源位置和

sound3D->buffer3D->SetAllParameters(&param, DS3D_IMMEDIATE);// 立即設定

15.正確設置音源因子與3D聽者位置,關鍵部分是不要設置DS3DMODE_HEADRELATIVE(頭部模式)

DS3DLISTENER  param;

memset(&param, 0, sizeof(DS3DLISTENER));

param.dwSize = sizeof(DS3DLISTENER);

DirectSound3D_Listener->GetAllParameters(&param);

param.flDopplerFactor = 0; //多譜勒頻移,一般設為0

param.flRolloffFactor = 0.1f; // 衰減率,此直越大衰減越快.一般設為0.1f~0.5f

param.vPosition.x = x; //聽者3D位置

param.vPosition.y = y;

param.vPosition.z = -z;

DirectSound3D_Listener->SetAllParameters(&param, DS3D_IMMEDIATE);

16.循環播放音頻數據

sound3D->buffer->Play(0,0,DSBPLAY_LOOPING);

17.單次播放

sound3D->buffer->Play(0, 0, 0);

18.停止音頻播放

sound3D->buffer->Stop();

19.釋放DirectSound3D

sound3D->buffer3D->Release();// 釋放3D緩存

sound3D->buffer->Release();// 釋放輔助緩存

DirectSound3D_Buffer->Release(); // 釋放聲卡主緩存

direct_sound3D->Release();// 釋放聲卡

 

評論