DirectSound---3D環境

DirectSound對於單聲道的Wav文件(或者說對於單聲道的PCM音頻數據)提供了內置3D音效的模擬,你可以控制每個聲源和收聽者的立體位置,對移動的物體應用多普勒效果等等。在單個應用程序中,能夠有多個聲源,可是隻能有一個收聽者。git

1. 3D音效概念簡介

  1. 3D座標: 座標採用左手笛卡爾座標系,x軸向右延伸,y軸向上延伸,z軸向前延伸。
  2. 3D處理模式: DirectSound由三種3D環境處理模式:普通模式禁用模式頭部相關模式。普通模式就是完整的3D模式,禁用模式不言而喻,頭部相關模式是部分3D模式(由於該模式下全部的聲源參數都是參考聽者位置的,而不是參考原點)。
  3. 延遲生效: 所以每次應用3D配置,DirectSound都要進行大量的計算,可能會家中cpu的負擔。所以,聲源和聽者都支持一種叫作延遲設置的方式,多個以延遲設置設置的參數須要調用提交函數才能應用到音頻數據上,這樣能夠避免屢次重複計算。

coordinate-pic

1.1 聲源(Source)相關概念

  • 最小距離: 在最小距離範圍內,聽到的聲源音量大小保持不變;在最小距離範圍外,聽到的音量開始成比例衰減(例如最小距離是10米,則聽者站在距離聲源20米處聽到的聲音是原始聲音的1/2)。
  • 最大距離: 在最大距離外的聽者,無論再怎麼朝外移動,聽到的音量都不會再減少。
  • 朝向: 朝向用來指定聲源投射的方向,具體見下一點。
  • 音量投射角度: 3D環境下的音量有一個錐形的投射角度(當設置朝向時),份內角和外角:內角的聲音是正常的音量,外角的音量一般是衰減的音量,在內角邊界向外角邊界過渡時音量逐級衰減。

cone-pic

  • 移動速度: 移動速度在整個3D環境裏主要是用來計算多普勒效應(Doppler Effect)的。

1.2 聽者(Listener)相關概念

  • 朝向: 聽者的朝向角度由兩個3維向量構成,實際上這個朝向是一個平面。兩個三維向量都以聽者頭部中心爲原點,一個向頂部延伸,一個向前延伸。

orientation-pic

  • 距離因子: 距離因子(Distance Factor)表示三維空間中的單位,與成正比(例如距離因子爲2,則一個三維點(1,0,0)表示現實中距離原點x軸2米)。
  • 多普勒因子: 表示產生的多普勒效應是真實效應的幾倍。
  • 滾降因子: 表示音量隨距離的衰減程度。0表示不衰減,1表示衰減成程度與現實環境相同,等等。

2. 3D示例程序

2.1 獲取和設置聲源最大最小距離

IDirectSound3DBuffer8::GetMaxDistance(D3DVALUE * pflMaxDistance);
IDirectSound3DBuffer8::GetMinDistance(D3DVALUE * pflMinDistance);
IDirectSound3DBuffer8::SetMaxDistance(D3DVALUE flMaxDistance, DWORD dwApply);
IDirectSound3DBuffer8::SetMinDistance(D3DVALUE flMinDistance, DWORD dwApply);github

dwApply參數用來指定是當即生效仍是延遲生效(須要調用CommitDeferredSettings函數)。windows

2.2 獲取和設置聲源音量投射角度

由於投射角度中外角確定要比內角大,爲了保證這一點咱們須要作些額外的判斷處理:ide

void MainWindow::on_coneAnglesInside_valueChanged(int value)
{
    DWORD insideAngle, outsideAngle;
    if (m_wavPlayer.get3DSource()->GetConeAngles(&insideAngle, &outsideAngle) != DS_OK)
        throw std::exception("GetConeAngles error");

    if (static_cast<unsigned>(value) > outsideAngle)
        ui->coneAnglesOutside->setValue(value),
        outsideAngle = value;
    if (m_wavPlayer.get3DSource()->SetConeAngles(value, outsideAngle, DS3D_IMMEDIATE) != DS_OK)
        throw std::exception("SetConeAngles error");

    ui->coneAnglesInsideLabel->setText(QString("coneAnglesInside(%1)").arg(value));
}

2.3 獲取和設置聲源朝向

這裏也有一個特殊狀況要處理:朝向的3個維度不能都爲0,不然就是一個無效的方向:函數

#define SET_ONE_VECTOR_WITH_ZERO_CHECK_OF_SOURCE(getFunc, setFunc, sliderName, valueX, valueY, valueZ)  \
    D3DVECTOR vector;                                                                                   \
    if (m_wavPlayer.get3DSource()->getFunc(&vector) != DS_OK)                                           \
        throw std::exception(#getFunc " error");                                                        \
                                                                                                        \
    if (!(valueX == 0.0 && valueY == 0.0 && valueZ == 0.0))                                             \
        if (m_wavPlayer.get3DSource()->setFunc(valueX, valueY, valueZ, DS3D_IMMEDIATE) != DS_OK)        \
            throw std::exception(#setFunc " error");                                                    \
                                                                                                        \
    ui->sliderName##Label->setText(QString(#sliderName "(%1)").arg(value));

void MainWindow::on_coneOrientationX_valueChanged(int value)
{
    SET_ONE_VECTOR_WITH_ZERO_CHECK_OF_SOURCE(GetConeOrientation, SetConeOrientation, coneOrientationX,
                                            value, vector.y, vector.z);
}

其餘相關設置這裏就不給出代碼了,都比較簡單,有須要的能夠看官方文檔ui

3. 運行結果示意圖

界面太大,我就分紅3張圖展現了:code

reuslt-pic1 reuslt-pic2 reuslt-pic3

完整代碼見連接blog

相關文章
相關標籤/搜索