Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1529

[VB6] - 3D sound using DirectSound.

$
0
0
Hello everyone.
The example shows an implementation of 3D sound, every object in three-dimensional space "assigned" the sound. To work need a library dx8vb.dll. Shift / Ctrl - deceleration of 10 times, the left button to rotate the camera, right tilt left / right. Spheres - sound sources, each can be turned on / off. Commented only work with sound:
Code:

Option Explicit

Dim dx      As DirectX8                    ' Объект DirectX8
Dim dxs    As DirectSound8                ' Объект DirectSound
Dim dl      As DirectSound3DListener8      ' Слушатель
Dim dp      As DirectSoundPrimaryBuffer8    ' Первичный буфер
Dim ds()    As DirectSoundSecondaryBuffer8  ' Вторичные буфера
Dim db()    As DirectSound3DBuffer8        ' 3D буфера
Dim dev    As Direct3DDevice8              ' Для визуализации ...
Dim d3d    As Direct3D8                    ' ...
Dim d3msh  As D3DXMesh                    ' ...
Dim d3pln  As D3DXMesh                    ' ...

Private Const CountSources = 3      ' Количество источников звука

' // Отключение/включение звука
Private Sub chkSound_Click(Index As Integer)
    ' Если стоит галочка, то
    If chkSound(Index).Value = vbChecked Then
        ' Проигрываем звук с зацикливанием по кругу
        ds(Index).Play DSBPLAY_LOOPING
    Else
        ' Иначе останавливаем
        ds(Index).Stop
    End If
   
End Sub

' // Процедура обрабтки нажатий клавиш
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Dim curPos  As D3DVECTOR    ' Текущая позиция слушателя
    Dim curOrt  As D3DVECTOR    ' Текущий вектор ориентации
    Dim curTop  As D3DVECTOR    ' Текущий вектор "макушки" слушателя
    Dim curLft  As D3DVECTOR    ' Вектор влево относительно ориентации слушателя
   
    ' Получаем позицию слушателя
    dl.GetPosition curPos
    ' Получаем ориентацию и направление вверх
    dl.GetOrientation curOrt, curTop
    ' С помощью векторного произведения находим препендикуляр к этим двум векторам, т.е. вектор влево
    D3DXVec3Cross curLft, curOrt, curTop
   
    ' Если нажата Shift/Ctrl
    If Shift Then
        ' Уменьшаем размер в 10 раз
        D3DXVec3Scale curOrt, curOrt, 0.1  ' вектора ориентации
        D3DXVec3Scale curLft, curLft, 0.1  ' вектора влево
       
    End If
   
    ' Получение кода нажатой клавиши
    Select Case KeyCode
    Case vbKeyW, vbKeyUp
        ' Вперед. Прибавляем к текущим координатам вектор ориентации
        D3DXVec3Add curPos, curPos, curOrt
    Case vbKeyA, vbKeyLeft
        ' Влево. Прибавляем к текущим координатам вектор влево
        D3DXVec3Add curPos, curPos, curLft
    Case vbKeyD, vbKeyRight
        ' Вправо. Вычитаем из текущих координат вектор влево
        D3DXVec3Subtract curPos, curPos, curLft
    Case vbKeyS, vbKeyDown
        ' Назад. Вычитаем из текущих координат ориентацию
        D3DXVec3Subtract curPos, curPos, curOrt
    End Select
   
    ' Устанавливаем измененную позицию
    dl.SetPosition curPos.X, curPos.Y, curPos.z, DS3D_IMMEDIATE
    ' Визуализация
    Render
   
End Sub

' // Процедура загрузки формы
Private Sub Form_Load()
    ' Создаем объект DirectX8
    Set dx = New DirectX8
    ' Создаем объект DirectSound
    Set dxs = dx.DirectSoundCreate(vbNullString)
    ' Настраиваем совместный доступ
    dxs.SetCooperativeLevel Me.hWnd, DSSCL_NORMAL
    ' Описатель буфера
    Dim bd  As DSBUFFERDESC
    ' Это первичный буфер и возможность контролировать положение и ориентацию в пространстве
    bd.lFlags = DSBCAPS_PRIMARYBUFFER Or DSBCAPS_CTRL3D
    ' Создаем первичный буфер
    Set dp = dxs.CreatePrimarySoundBuffer(bd)
    ' Получаем объект слушателя
    Set dl = dp.GetDirectSound3DListener()
    ' Для других буферов возможность контролировать положение и ориентацию в пространстве
    bd.lFlags = DSBCAPS_CTRL3D
    ' Задаем ориентацию вперед
    dl.SetOrientation 0, 0, 1, 0, 1, 0, DS3D_DEFERRED
   
    Dim i  As Long    ' Временная переменная
    Dim fil As Boolean  ' В IDE - загрузка из файла, в EXE из ресурсов
   
    ReDim ds(CountSources - 1)  ' Массив вторичных буферов (источников)
    ReDim db(CountSources - 1)  ' Массив 3D буферов
   
    Randomize
   
    For i = 0 To CountSources - 1
       
        Debug.Assert InIDE(fil)
       
        ' Загружаем из файла или из ресурса в зависимости от режима работы
        If fil Then
            Set ds(i) = dxs.CreateSoundBufferFromFile(Choose(i + 1, "Sound.wav", "Moto.wav", "Police.wav"), bd)
        Else
            Set ds(i) = dxs.CreateSoundBufferFromResource(App.EXEName & ".exe", Choose(i + 1, "#101", "#102", "#103"), bd)
        End If
        ' Получаем объект 3D буфера
        Set db(i) = ds(i).GetDirectSound3DBuffer()
        ' Задаем рандомную позицию
        db(i).SetPosition Rnd * 50 - 25, Rnd * 50, Rnd * 50 - 25, DS3D_DEFERRED
        ' Включаем воспроизведение
        ds(i).Play DSBPLAY_LOOPING
       
    Next
    ' Запуск просчета изменений
    dl.CommitDeferredSettings
   
    ' Для визуализации (не комментирую)
    ' //----//----//----//----//----//
    Dim pp  As D3DPRESENT_PARAMETERS
    Dim dm  As D3DDISPLAYMODE
   
    Set d3d = dx.Direct3DCreate()
   
    d3d.GetAdapterDisplayMode D3DADAPTER_DEFAULT, dm
   
    pp.BackBufferFormat = dm.Format
    pp.Windowed = 1
    pp.SwapEffect = D3DSWAPEFFECT_DISCARD
    pp.EnableAutoDepthStencil = 1
    pp.AutoDepthStencilFormat = D3DFMT_D16
   
    Set dev = d3d.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, pic.hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, pp)
   
    Dim mtx As D3DMATRIX
   
    D3DXMatrixPerspectiveFovLH mtx, 3.14 / 180 * 80, pic.ScaleHeight / pic.ScaleWidth, 0.1, 200
    dev.SetTransform D3DTS_PROJECTION, mtx
   
    dev.SetRenderState D3DRS_ZENABLE, D3DZB_TRUE
    dev.SetRenderState D3DRS_LIGHTING, 1
   
    Dim d3      As D3DX8
    Dim dat()  As Byte
   
    Set d3 = New D3DX8
    Set d3msh = d3.CreateSphere(dev, 1, 16, 8, Nothing)
    Set d3pln = d3.CreatePolygon(dev, 100, 4, Nothing)
   
    Dim lth As D3DLIGHT8
    Dim mat As D3DMATERIAL8
   
    lth.Type = D3DLIGHT_POINT
    lth.diffuse = col(1, 1, 1)
    lth.Position = vec3(0, 100, -100)
    lth.Attenuation1 = 0.01
    lth.Range = 400
   
    dev.SetLight 0, lth
    dev.LightEnable 0, 1
   
    mat.diffuse = col(1, 1, 1)
    dev.SetMaterial mat
    ' //----//----//----//----//----//
   
End Sub

' // Визуализация
Private Sub Render()
    Dim idx As Long
    Dim v1  As D3DVECTOR
    Dim v2  As D3DVECTOR
    Dim v3  As D3DVECTOR
    Dim mtx As D3DMATRIX
   
    dev.Clear 0, ByVal 0, D3DCLEAR_ZBUFFER Or D3DCLEAR_TARGET, &HAFFFFF, 1, 0

    dev.BeginScene

    dev.SetVertexShader d3msh.GetFVF
   
    dl.GetPosition v1:      dl.GetOrientation v2, v3
    D3DXVec3Add v2, v1, v2
    D3DXMatrixLookAtLH mtx, v1, v2, v3
    dev.SetTransform D3DTS_VIEW, mtx
   
    D3DXMatrixTranslation mtx, 0, -3, 0
    dev.SetTransform D3DTS_WORLD, mtx
    D3DXMatrixRotationX mtx, -3.14 / 2
    dev.MultiplyTransform D3DTS_WORLD, mtx
   
    d3pln.DrawSubset 0
   
    For idx = 0 To CountSources - 1
       
        db(idx).GetPosition v1
        D3DXMatrixTranslation mtx, v1.X, v1.Y, v1.z
        dev.SetTransform D3DTS_WORLD, mtx
        d3msh.DrawSubset 0
       
    Next
   
    dev.EndScene
   
    dev.Present ByVal 0, ByVal 0, 0, ByVal 0
   
End Sub

' // Функция сздания векторов
Private Function vec3(ByVal X As Single, ByVal Y As Single, ByVal z As Single) As D3DVECTOR
    vec3.X = X: vec3.Y = Y: vec3.z = z
End Function

' // Функция создания цветов
Private Function col(r As Single, g As Single, b As Single) As D3DCOLORVALUE
    col.r = r
    col.g = g
    col.b = b
    col.a = 1
End Function

' // Процедура выгрузки формы
Private Sub Form_Unload(Cancel As Integer)
    Dim i  As Long
    ' Проход по всем буферам
    For i = 0 To CountSources - 1
        ' Остановка
        ds(i).Stop
        ' Удаление и очистка
        Set ds(i) = Nothing
        Set db(i) = Nothing
       
    Next
   
    Set dl = Nothing
    Set dp = Nothing
   
    Set dxs = Nothing
    Set dx = Nothing
   
End Sub

' // Процедура обработки мыши
Private Sub pic_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    Static ox  As Single, oy As Single
    Dim mtx As D3DMATRIX
    Dim qt1 As D3DQUATERNION
    Dim qt2 As D3DQUATERNION
    Dim v1  As D3DVECTOR
    Dim v2  As D3DVECTOR
    Dim v3  As D3DVECTOR

    ' При движении с зажатой левой кнопкой изменяем ориентацию
    If Button = vbLeftButton Then
           
        dl.GetOrientation v1, v2
        D3DXVec3Cross v3, v1, v2
       
        D3DXQuaternionRotationAxis qt1, v2, (X - ox) / 50
        D3DXQuaternionRotationAxis qt2, v3, -(Y - oy) / 50
        D3DXQuaternionMultiply qt1, qt1, qt2
        D3DXMatrixRotationQuaternion mtx, qt1
       
        D3DXVec3TransformCoord v1, v1, mtx
        D3DXVec3TransformCoord v2, v2, mtx
        dl.SetOrientation v1.X, v1.Y, v1.z, v2.X, v2.Y, v2.z, DS3D_IMMEDIATE
       
        Render
    ' При правой кнопке - наклон (направление вверх)
    ElseIf Button = vbRightButton Then
   
        dl.GetOrientation v1, v2
       
        D3DXQuaternionRotationAxis qt1, v1, (X - ox) / 50
        D3DXMatrixRotationQuaternion mtx, qt1
       
        D3DXVec3TransformCoord v1, v1, mtx
        D3DXVec3TransformCoord v2, v2, mtx
        dl.SetOrientation v1.X, v1.Y, v1.z, v2.X, v2.Y, v2.z, DS3D_IMMEDIATE
       
        Render
       
    End If
   
    ox = X: oy = Y
   
End Sub

Private Sub pic_Paint()
    Render
End Sub

Private Function InIDE(z As Boolean) As Boolean
    z = True: InIDE = z
End Function

Download source code.

Viewing all articles
Browse latest Browse all 1529

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>