|
DirectSound Tutorial
Автор: Jack Hackslay
Теория- Нормальный режим
DS довольно прост для обучения, возможно, это самая легкая часть
DirectX. Если вы не планируете создание трехмерной игры, DirectSound3D не
должен вас волновать. Для полного восприятия режима 3D пользователю будет
необходима 3D звуковая система (обычно система из четырех динамиков).
Прим. перев.: Для тех, кто занимается созданием трехмерных игрушек,
раздел "3D режим" выйдет чуть позже и в отдельном учебнике, т.к. в
оригинале он почти не освещен.
Нормальный режим - Обзор
DirectSound, как можно понять из названия,
проигрывает звуки. Обычно он используется для создания звуковых эффектов в
играх, благодаря своей способности проигрывать больше, чем один звук в
одно и то же время ("Микширование"). Также, вы можете более точно
контролировать звучание в динамиках пользователя используя эффекты
громкости и баланса звука(panning). Также, есть возможность задания
координат x, y и z для источника звука, но в полной мере эта опция,
называемая DirectSound3D работает на компьютерах, оснащенных звуковой
системой из 4-х динамиков. Лучше всего 3D звук используется в шутерах от
первого лица, где игрок может слышать звуки изо всех направлений.
DirectSound очень важен для игр.
Многие обозреватели трехмерных игр забывают о звуке. Попробуйте играть в
игру с выключенным звуком и вы поймете разницу.
К сожалению, многие компоненты DirectX, ограничены в Visual
Basic. И поэтому имеется очень маленькая поддержка действительно 3D
позиционированного звука. Причина этого в самом языке, ведь Visual Basic в
основе своей инструмент для баз данных (поэтому в нем так много
инструментов для управления данными), и язык никогда не планировался для
разработки игр. Профессиональные компании используют C++ для создания игр,
поэтому DirectX имеет больше поддержки в C++, чем в Visual Basic.
Обзор- Теория
Этот учебник покажет вам как
создать простое приложение, которое проигрывает несколько звуков в одно и
то же время. У него будут опции для баланса звука (Право <-> Лево) и
громкости (ну это вы знаете!). Код из этого приложения затем может быть
добавлен в любую вашу игру, где будут использоваться звуковые эффекты.
Сначала, несколько понятий: Буфер -
место, в котором содержатся звуковые данные Wav файл -
тип файлов, которые использует DSound: *.wav
Щелкните в списке, чтобы перейти к нужной секции:
Этот проект использует DirectX 7,
поэтому добавьте соответствующую библиотеку к вашему проекту.
Также, вам потребуется несколько звуковых файлов для
проигрывания. Найдите пару wav файлов (попробуйте через пункт "Поик" из
меню "пуск". Скпируйте два РАЗНЫХ файла в папку с вашим проектом,
переименовав их в Tester1.wav и Tester2.wav
Сохраните проект и переходите к следующей секции...
Объявление переменных
В этом проекте будет довольно
мало переменных, но все же надо по ним пробежаться. Добавьте эти строки в
секцию Declarations для Form1:
Option
Explicit 'Очень
полезное требование, когда работаете с DirectX Dim m_dx As New DirectX7 'Это главный объект DirectX. DirectSound
создается из этого объекта Dim m_ds As
DirectSound 'Это объект
DirectSound. Позже, мы "Создадим" его из главного объекта DirectX
Dim m_dsBuffer(1) As
DirectSoundBuffer 'Это массив буферов,
использовать который не обязательно, но это сделает программирование
намного легче. m_dsBuffer(0) будет содержать tester1.wav, а
m_dsBuffer(1)
tester2.wav |
Позже, каждый буфер будет вызываться, чтобы проигрывать/остановить его
содержимое.
Создание
интерфейса
Интерфейс, как вы можете видеть, довольно мудреный. Интерфейс содержит
набор элементов, управляющих каждым буфером и набор общих элементов
управления. Вот таблица свойств элементов:
(1) Сначала, создайте два фрейма с
любыми именами. Свойство Caption одного должно быть "Громкость", а
другого "Баланс" (2) Затем, внутри первого фрейма поместите два
скролл бара scrlTester1_Vol .Max=0 .Min=-5000 .LargeChange=20
.SmallChange=255 scrlTester2_Vol .Max=0 .Min=-5000 .LargeChange=20
.SmallChange=255 Можете, если хотите,
добавить метки. (3) Затем, поместите еще два скролл бара во
второй фрейм scrlTester1_Pan .Max=10000 .Min=-10000 .LargeChange=1000
.SmallChange=500 scrlTester2_Pan .Max=10000 .Min=-10000 .LargeChange=1000
.SmallChange=500 (4) Используйте
рисунок, как подмогу, создавая главную "Контрольную панель"
cmdTester1_Play .Caption="Play
Tester1.Wav" cmdTester2_Play .Caption="Play Tester2.Wav"
cmdBoth_Play .Caption="Play Both"
cmdTester1_Stop .Caption="Stop Tester1.Wav"
cmdTester2_Stop .Caption="Stop Tester2.Wav"
cmdBoth_Stop .Caption="Stop Both" cmdTester1_Pause .Caption="Pause Tester1.Wav"
cmdTester2_Pause .Caption="Pause Tester2.Wav"
cmdBoth_Pause .Caption="Pause Both" (5) Затем финальная часть (уфф!) - флажки
chTester1_Loop .Caption="Tester1.Wav Loop"
chTester2_Loop .Caption="Tester2.Wav Loop"
chBoth_Loop .Caption="Loop Both
Sounds" |
Теперь, у вас должен быть интерфейс.
Затем, нам надо создать код, который будет все это связывать
воедино. Это короткие отрезки кода для каждого элемента управления,
которые будут задавать работу этих элементов управления. Помните, не
запускайте проект после того как напишете эти строки, вы получите кучу
сообщений об ошибках (Мы ведь не написали еще весь код!). Код для скролл
баров будет показан позже, так как для него требуется более тщательный
разбор...
Если вы присваивали элементам управления такие же имена, как
у меня, можете просто копировать эти строки в вашу программу.
Private Sub Form_Load()
Me.Show On Local Error
Resume Next
'Сначала нам надо создать объект DSound. Это должно быть сделано
прежде, чем использовать любые его возможности 'Это также должно быть сделано
перед созданием.
Set m_ds = m_dx.DirectSoundCreate("") 'Эти строки проверяют наличие
ошибок, если ошибок нет, то у пользователя установлен DirectX7 и
работающая звуковая карта If Err.Number <> 0 Then
MsgBox "Unable to
start DirectSound. Check to see that your sound card is properly
installed" End
End If 'ЭТО ДОЛЖНО БЫТЬ УСТАНОВЛЕНО ПЕРЕД
СОЗДАНИЕМ БУФЕРОВ
'DSSCL_PRIORITY=нет совместной работы. Эксклюзивный доступ к
звуковой карте ' Нужно для
игр
'DSSCL_NORMAL=совместная работа с другими приложениями
'GПолезен для мультимедийных приложений Windows
m_ds.SetCooperativeLevel
Me.hwnd, DSSCL_PRIORITY LoadWave 'Эта процедура будет создана позже. Потерпите...
End Sub
')))))))))))))))))))))(КОД ЦИКЛА
ПРОИГРЫВАНИЯ)(((((((((((((((((((((((((((((((((((((((((((((
'Я сгруппировал все эти части вместе, так
как они почти идентичны 'Во всех 3 случаях проверяется состояние
флажков. Если он не установлен, 'тогда смотрим, есть ли
что-нибудь в буферах? (Звк уже загружен?) 'В конце, проигрывание
останавливается и "перематывается" в начало
'Проверка буфера - это ловушка для
ошибки. Вы не можете изменять состояние буфера, когда 'он пуст.
Если вмы бы попытались вызвать метод Stop для пустого буфера,
получили бы ошибку
Private Sub
chBoth_Loop_Click() If
chBoth_Loop.Value = 0 Then If
m_dsBuffer(0) Is Nothing And m_dsBuffer(1) Is Nothing Then Exit
Sub m_dsBuffer(0).Stop
m_dsBuffer(0).SetCurrentPosition 0
m_dsBuffer(1).Stop m_dsBuffer(1).SetCurrentPosition 0 End If End Sub
Private Sub
chTester1_Loop_Click() If
chTester1_Loop.Value = 0 Then If
m_dsBuffer(0) Is Nothing Then Exit Sub m_dsBuffer(0).Stop m_dsBuffer(0).SetCurrentPosition 0 End If End Sub
Private Sub
chTester2_Loop_Click() If
chTester2_Loop.Value = 0 Then If
m_dsBuffer(1) Is Nothing Then Exit Sub m_dsBuffer(1).Stop m_dsBuffer(1).SetCurrentPosition 0 End If End Sub
'))))))))))))))))))))))))))(КОНЕЦ
ЦИКЛА ПРОИГРЫВАНИЯ)((((((((((((((((((((((((((((
')))))))))))))))))))))))))))))))(КОД
ПАУЗЫ)((((((((((((((((((((((((( 'И
снова я сгруппировал их вместе, потому что они почти
одинаковы 'Метод buffer.Stop вызывает паузу в проигрывании
содержимого буфера. 'Чтобы исполнить команду "Стоп", т. е. с
перемоткой назад, вам надо указать еще вернуться 'назад (это
позже). Если вы прикажете выполнить паузу, то следующий вызов
команды 'Play продолжит проигрывание с прерванного
места
Private Sub
cmdBoth_Pause_Click() If
m_dsBuffer(0) Is Nothing And m_dsBuffer(1) Is Nothing Then Exit
Sub m_dsBuffer(0).Stop
m_dsBuffer(1).Stop End Sub
Private Sub
cmdTester1_Pause_Click() If
m_dsBuffer(0) Is Nothing Then Exit Sub m_dsBuffer(0).Stop End
Sub
Private Sub
cmdTester2_Pause_Click() If
m_dsBuffer(1) Is Nothing Then Exit Sub m_dsBuffer(1).Stop End
Sub ')))))))))))))))))))))))))(КОНЕЦ
КОДА ПАУЗЫ)((((((((((((((((((((((((((((((((
')))))))))))))))))))))))))))))))(КОД
ОСТАНОВКИ)(((((((((((((((((((((( ' И
опять все вместе
'Эти процедуры останавливают звук
и "перематывают" его на начало.
Private Sub
cmdBoth_Stop_Click() If m_dsBuffer(0)
Is Nothing And m_dsBuffer(1) Is Nothing Then Exit Sub
m_dsBuffer(0).Stop m_dsBuffer(0).SetCurrentPosition 0 m_dsBuffer(1).Stop m_dsBuffer(1).SetCurrentPosition 0 End Sub
Private Sub
cmdTester1_Stop_Click() If
m_dsBuffer(0) Is Nothing Then Exit Sub m_dsBuffer(0).Stop m_dsBuffer(0).SetCurrentPosition 0 End Sub
Private Sub
cmdTester2_Stop_Click() If
m_dsBuffer(1) Is Nothing Then Exit Sub m_dsBuffer(1).Stop m_dsBuffer(1).SetCurrentPosition 0 End Sub
'))))))))))))))))))))))))))))))))))))))))))))))))))(КОНЕЦ
КОДА
ОСТАНОВКИ)(((((((((((((((((((((((((((((( |
Это первая ступень в создании кода. Помните, что пока нельзя
запускать проект, вы получите сообщение об ошибке
Создание
загрузочной процедуры
Слудующей ступенью создания программы будет написание
процедуры, загружающей звук в буфер. Назовем ее "LoadWave". Помните, мы ее
еще упоминали в процедуре Form_Load? Вот код:
Sub LoadWave()
Dim bufferDesc
As DSBUFFERDESC 'этот новый объект
передается DS, чтобы описать, какой буфер создается 'Очень
похоже на описание поверхности DirectDraw Dim waveFormat As
WAVEFORMATEX 'Эти утановки выполняются почти для
каждого приложения bufferDesc.lFlags =
DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLPAN Or DSBCAPS_CTRLVOLUME Or
DSBCAPS_STATIC
waveFormat.nFormatTag = WAVE_FORMAT_PCM waveFormat.nChannels =
2 'Два канала waveFormat.lSamplesPerSec = 22050
'22 kHz можете конечно менять, если
разбираетесь....... waveFormat.nBitsPerSample =
16 '16 бит лучше чем 8 (лучше
качество)
waveFormat.nBlockAlign = waveFormat.nBitsPerSample / 8 *
waveFormat.nChannels waveFormat.lAvgBytesPerSec =
waveFormat.lSamplesPerSec * waveFormat.nBlockAlign
'Следующие строки создают буфер с указанным файлом, загруженным в
него '"BufferDesc" и "WaveFormat" описывают
свойства буфера. Их можно менять только при создании
буфера... Dim sFile As String sFile = App.Path &
"\tester1.wav" 'Этот файл должен быть в
папке проекта...... Set m_dsBuffer(0) =
m_ds.CreateSoundBufferFromFile(sFile, bufferDesc, waveFormat)
sFile = App.Path &
"\tester2.wav" Set
m_dsBuffer(1) = m_ds.CreateSoundBufferFromFile(sFile, bufferDesc,
waveFormat)
'Проверяет на ошибки If Err.Number <> 0
Then ' Просто выдает сообщение об ошибке
(0 = все нормально) MsgBox
"unable to find " + sFile End
End If
'Проверяет "свойства" паннинга и
громкости
scrlTester1_Pan_Change 'Вместо того,
чтобы писать код снова, просто scrlTester1_Vol_Change 'вызывается процедура, в которой он
находится.........
scrlTester2_Pan_Change scrlTester2_Vol_Change
End
Sub |
Примечание: если вы получите сообщение об ошибке, но вы
знаете, что файлы находятся на своих местах, возможно то, что они записаны
в неправильном формате. Вы не можете заметить разницу, пока не загрузите
их, но некоторые wav файлы записаны в формате PCM (то, что требует
DirectSound), а некоторые нет. Если это произойдет, выберите другие
файлы.
Пусть
она заиграет!
Наконец-то мы получим полезные свойства от нашей
программы... Следующий код можете скопировать в поцедуры cmdBoth_Play cmdTester1_Play
cmdTester2_Play
Private Sub
cmdBoth_Play_Click() Dim flag As
Long flag = 0 'Значение будет меняться при изменении
флажка If chBoth_Loop.Value <> 0
Then flag = 1 'Решим, зацикливать ли
проигрывание m_dsBuffer(0).Play
flag m_dsBuffer(1).Play flag
'Когда вы применяете метод
"m_dsbuffer(*).play", вы можете указать режим
"DSBPLAY_NORMAL" 'и
"DSBPLAY_LOOPING", переменная flag выполняет то же, 0 = нормально,
1=зацикленно. End Sub
'Следующие две процедуры почти
идентичны Private Sub
cmdTester1_Play_Click() Dim flag As
Long flag = 0 If chTester1_Loop.Value <> 0 Then flag =
1 m_dsBuffer(0).Play flag
End Sub
Private Sub
cmdTester2_Play_Click() Dim flag As
Long flag = 0 If chTester2_Loop.Value <> 0 Then flag =
1 m_dsBuffer(1).Play
flag End
Sub |
OK, теперь у нас есть хоть что-то полезное. Следующий раздел будет еще
интересней.
Добавление эффектов громкости и
паннинга
Использование громкости очень просто, а паннинг вам обязательно
пригодится. Если вы делаете "приставочную" игру, вы можете использовать
эту функцию, чтобы звук исходил справа или слева от игрока, добавляя новое
измерение в окружение. Это также очень просто.
Вы уже должны были нарисовать ScrollBar'ы и установить их свойства, так
что просто скопируйте этот код в ваш проект.
Private Sub
scrlTester1_Pan_Change() If
m_dsBuffer(0) Is Nothing Then Exit Sub
'Если буфер пуст, то с ним нельзя что-либо делать m_dsBuffer(0).SetPan scrlTester1_Pan.Value
End Sub
Private Sub
scrlTester1_Vol_Change() If
m_dsBuffer(0) Is Nothing Then Exit Sub m_dsBuffer(0).SetVolume scrlTester1_Vol.Value
End Sub
Private Sub
scrlTester2_Pan_Change() If
m_dsBuffer(1) Is Nothing Then Exit Sub m_dsBuffer(1).SetPan scrlTester2_Pan.Value
End Sub
Private Sub
scrlTester2_Vol_Change() If
m_dsBuffer(1) Is Nothing Then Exit Sub m_dsBuffer(1).SetVolume scrlTester2_Vol.Value
End Sub |
Все ужасно просто. Но вы наверное хотите узнать
максимальные/минимальные установки громкости и паннинга:
Громкость колеблется от -5000 (тишина) до 0 (самая громкая). Это всего
лишь "проценты " от громкости, установленной в Панели Управления Windows.
Если громкость там установлена очень тихой, то любые изощрения не приведут
к более громкому результату.
Паннинг принимает значения от -10 000 (Левое ухо) до 0 (Все ухи :-) и
до 10 000 (Правое ухо)
Ну вот и все!
Обзор сделанного
OK, чего это мы тут натворили? Мы сделали программу, которая
помещает Wav файлы в память и проигрывает их с установленными значениями
громкости и баланса звука (паннинг).
На что надо обратить внимание:
Хранение звуков занимает RAM, так что разумные пределы 5-6 маленьких
звуков. Если вы занрузите 10 или больше больших звуков в память,
быстродействие оставит желать лучшего. В моих планах размещение учебника,
в котором показано как проигрывать файл по мере загружения (streaming)
вместо хранения его в памяти (как только так сразу - переведем! :) Прим.
перев.)
А самые любопытные могут загрузить
готовую программу прямо сейчас. Размер 100кб.
Have fun.
Перевод на русский язык (c)2000 Antiloop Публикуется с разрешения
автора. Полное или частичное цитирование перевода только с
разрешения переводчика. Пишите!
|