經多日努力終於可以在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感知效果要素如下:
- 響度:當聲源逐漸遠離聽者,聲源會逐漸衰減
- 兩耳聲響差:若聲源位於聽者右側,則右耳聽到聲響比左耳響.
- 兩耳時間差:若聲源位於聽者右側,則右耳比左耳早聽到一毫秒.
- 兩耳朝向:若聲源在前邊則比後邊響
- 聲音最大距離:大於此距離聲音不再衰減.默認為DS3D_DEFAULTMAXDISTANCE(109 m)
- 聲音最小距離:大於此距離聲音不再遞增.默認為DS3D_DEFAULTMINDISTANCE(1m)
- 默認模式: DS3DMODE_NORMAL使用3D座標設定音源位置
- 頭部模式: DS3DMODE_HEADRELATIVE.可以設定音源位置,但監聽位置總為(0,0,0)
- 禁用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(¶m, 0, sizeof(DS3DBUFFER));
param.dwSize = sizeof(DS3DBUFFER);
sound3D->buffer3D->GetAllParameters(¶m);
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(¶m, DS3D_IMMEDIATE);// 立即設定
15.正確設置音源因子與3D聽者位置,關鍵部分是不要設置DS3DMODE_HEADRELATIVE(頭部模式)
DS3DLISTENER param;
memset(¶m, 0, sizeof(DS3DLISTENER));
param.dwSize = sizeof(DS3DLISTENER);
DirectSound3D_Listener->GetAllParameters(¶m);
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(¶m, 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();// 釋放聲卡