»спользование FMOD в звуковых играх

ƒата публикации:2005
ѕоделитьс€ в Twitter ѕоделитьс€ в F******k ѕоделитьс€ в VKontakte ѕоделитьс€ в Telegram

ƒостоинства и недостатки FMOD

–ечь пойдЄт о программной библиотеке дл€ работы со звуком, известной под названием FMOD. –азработчиком этого программного продукта €вл€етс€ компани€ Firelight Technologies Pty, Ltd. Ќа момент написани€ статьи последним релизом FMOD была верси€ 3.74. — текущим состо€нием дел и с новыми верси€ми, если они по€вились, вы можете ознакомитьс€ на сайте www.FMOD.org. Ќа том же сайте вы можете получить версии FMOD дл€ различных операционных систем. ѕр€мые ссылки на дистрибутив FMOD расположены здесь.

Ѕиблиотека функций FMOD представл€ет собой реализацию API верхнего уровн€, который включает широкий набор функций дл€ работы со звуковыми файлами различных форматов, обработки звуковых данных и воспроизведени€ звука через аудиосистему компьютера или игровых приставок. ƒл€ того чтобы рассказать обо всех возможност€х этого API потребуетс€ не один дес€ток web-страниц.  роме того, основной нашей тематикой названа разработка звуковых игр, дл€ которых главный интерес представл€ют функции дл€ работы с объЄмным (3D) звуком. «накомством с этими функци€ми мы и ограничимс€. —ледует иметь в виду, что данна€ публикаци€ не €вл€етс€ полным руководством по FMOD, поэтому, разбира€ приводимые ниже примеры, не следует пренебрегать официальной документацией. ¬се примеры в статье составлены на €зыке программировани€ C (—и).

ƒл€ создани€ источников 3D звука и расчета трЄхмерной звуковой картины FMOD (верси€ дл€ Windows) использует в качестве базы любую из следующих звуковых систем: WMM (Windows Multimedia), DirectSound3D (звукова€ подсистема Microsoft DirectX) и A3D. FMOD обеспечивает такое взаимодействие с этими звуковыми системами, что переход от одной из них к другой требует минимальных изменений в коде программы (а часто вообще не требует никаких изменений). ѕри работе с базовой звуковой системой DirectSound3D функции FMOD заметно облегчают управление объЄмными источниками звука, упрощают их инициализацию, воспроизведение и позиционирование. ѕростота программировани€ FMOD (в сравнении с программированием базовых звуковых систем) €вл€етс€ важным достоинством этого API (ќ программировании непосредственно DirectSound3D можно прочитать в статье ѕрограммирование объЄмного звука в DirectSound3D).

ƒругим достоинством FMOD €вл€етс€ лЄгкость установки - достаточно разместить в системной папке или в папке, из которой запускаетс€ приложение, dll библиотеку, чтобы функции FMOD стали доступны. ¬ версии 3.74, кроме обычной дл€ Windows 32-разр€дной dll, поставл€етс€ 64-разр€дна€ библиотека FMOD.

FMOD содержит подробную документацию и примеры (вместе с заголовочными и другими служебными файлами) дл€ VisualC, BorlandC, Watcom C, Borland Delphi и VisualBasic. ƒл€ некоммерческих приложений библиотека FMOD предоставл€етс€ бесплатно.

  недостаткам FMOD следует отнести отсутствие таких возможностей (которые реализованы в DirectSound3D), как создание направленных источников звука и создание зависимых источников звука (по крайней мере, в наборе функций FMOD не представлены функции, устанавливающие данные параметры пространственной обработки звука).

ћодель пространства в FMOD

ћодель пространства (система координат), используема€ дл€ размещени€ источников 3D звука, аналогична модели пространства в DirectSound3D. «десь используетс€ левосторонн€€ декартова система координат, состо€ща€ из трЄх ортогональных координатных осей. ќсь X (икс) направлена вправо; ось Y (игрек) направлена вверх; ось Z (зэт) направлена вперед (то есть в монитор, если сидеть лицом к нему). –ассто€ние измер€етс€ в метрах, но можно установить другую единицу измерени€ длин, задав соотношение между метром и новой единицей измерени€. Ћюба€ точка в пространстве задаетс€ своими координатами, которые записываютс€ в последовательности X, Y, Z.  оординаты могут принимать как положительные, так и отрицательные значени€.  оординатную триаду XYZ, характеризующую положение точки в пространстве, можно рассматривать как вектор, начало которого находитс€ в начале отсчета, то есть в точке с координатами (0, 0, 0), и конечной точкой с координатами (X, Y, Z).  роме векторов положени€, в FMOD используютс€ векторы скорости, необходимые дл€ вычислени€ доплеровского смещени€ в спектре звука движущихс€ источников. ¬ектор скорости задаетс€ трем€ координатами своей конечной точки (начальной точкой вектора скорости считаетс€ точка (0, 0, 0)). —ледует заметить, что FMOD (как и DirectSound3D) не занимаетс€ расчетом координат движущегос€ объекта. Ёту задачу должен решать программист, передава€ функци€м FMOD данные, необходимые дл€ моделировани€ исключительно звуковой картины в конкретной точке пространства и в конкретный момент. “о есть по сути FMOD (как и DirectSound3D) рассчитывает статическую звуковую картину, которую программист может сделать динамичной дл€ слушател€ (игрока), часто мен€€ положение источников звука.

¬ тех функци€х FMOD, дл€ которых в качестве параметра должен передаватьс€ вектор, используетс€ указатель на структуру, состо€щую из трЄх вещественных (float) чисел, или на массив, состо€щий из трЄх вещественных (float) чисел. “о есть две следующие конструкции будут одинаково восприн€ты функци€ми FMOD:

/* масив */
float pos[3] = {10.0f, 2.0f, 4.2f};
/* структура */
struct VECTOR
{
float X;
float Y;
float Z;
};
VECTOR pos = {10.0f, 2.0f, 4.2f};

ћодель пространства в FMOD включает еще некоторые параметры среды, вли€ющие на распространение звуковых волн. — помощью функций FMOD можно установить степень затухани€ звука и степень выраженности доплеровского эффекта.

ќбъекты звуковой картины в FMOD

¬ FMOD существуют два вида объектов трЄхмерного звукового пространства: источники звука и слушатели. ¬ отличие от DirectSound3D, FMOD поддерживает модель нескольких слушателей. ¬о всем остальном обе системы аналогичны.

»сточники звука в FMOD могут быть только точечными и ненаправленными, что означает отсутствие у источника собственных размеров в и всенаправленность распространени€ звука от этого источника. ѕоложение слушател€, напротив, €вл€етс€ ориентированным. ƒл€ этого задаютс направление двух ортогональных векторов единичного размера. ѕервый вектор ориентирует направление лица, то есть указывает, куда смотрит слушатель. ¬торой вектор всегда направлен из макушки вверх, то есть указывает направление вертикальной оси слушател€. ћодуль каждого из этих векторов равен единице измерени€ длины, поэтому они нос€т названи€ единичных (ћодуль вектора вычисл€етс€ как корень квадратный из суммы квадратов длин его проекций на оси координат).

‘ункции дл€ работы с 3D звуком

дл€ простоты изложени€ ниже привод€тс€ не только функции FMOD, отвечающие непосредственно за создание объЄмного звука, но и все те функции, которыми необходимо воспользоватьс€ программисту, чтобы работать с библиотекой FMOD. ѕричем в списке функции расположены в той ориентировочной последовательности, в которой их следует вызывать в программе, взаимодействующей с FMOD. ¬ документации, котора€ входит в комплект FMOD все приводимые ниже функции помещены в раздел "FSOUND API Reference".

  • FSOUND_GetVersion() - возвращает версию библиотеки FMOD, установленной на компьютере. ¬озвращаемое значение следует сравнить с константой FMOD_VERSION, котора€ хранит номер версии FMOD, дл€ которой была скомпилирована программа.
  • FSOUND_SetOutput () / FSOUND_GetOutput () - выбрать/получить базовую звуковую систему (Windows Multimedia, DirectSound, A3D и т.п.). ¬ыбор базовой системы должен производитс€ до вызова функции FSOUND_Init().
  • FSOUND_SetDriver () / FSOUND_GetDriver () - выбрать/получить номер устройства вывода (звуковой карты). ¬ыбор устройства должен производитс€ до вызова функции FSOUND_Init().
  • FSOUND_SetMixer () /FSOUND_GetMixer () - выбрать/получить тип цифрового микшера. ¬ыбор микшера должен производитс€ до вызова функции FSOUND_Init(). ќпределение типа микшера не €вл€етс€ об€зательным, так как FMOD самосто€тельно определит лучший из имеющихс€ вариантов.
  • FSOUND_Init() - инициализирует звуковую систему FMOD.
  • FSOUND_Sample_Load () - загружает в пам€ть и декодирует звуковой файл (поддерживаютс€ .wav, .mp2, .mp3, .ogg, .raw и др.).
  • FSOUND_3D_SetDistanceFactor () - позвол€ет установить единицы измерени€ длин, отличные от метров.
  • FSOUND_3D_SetDopplerFactor () - позвол€ет установить доплеровское смещение. Ѕазовое значение (1.0) соответствует скорости звука 340 м/с.
  • FSOUND_3D_SetRolloffFactor () - позвол€ет установить уровень потерь энергии звуковой волны (затухани€). Ѕазовое значение (1.0) соответствует нормальным услови€м.
  • FSOUND_PlaySoundEx () - проигрывает звуковой файл, загруженный в пам€ть, через звуковой канал.
  • FSOUND_3D_SetAttributes () / FSOUND_3D_GetAttributes () - установить/получить вектор положени€ и вектор скорости источника звука.
  • FSOUND_3D_SetMinMaxDistance () / FSOUND_3D_GetMinMaxDistance () установить / получить минимальное и максимальное рассто€ние слышимости источника звука. ћинимальным называетс€ такое рассто€ние от источника звука до слушател€, при уменьшении которого громкость звука больше не возрастает, а остаетс€ на том значении, которого она достигла на минимальном рассто€нии. ”станавлива€ разные минимальные рассто€ни€, например, дл€ самолета и шмел€, можно сделать их одинаково заметными на слух, несмотр€ на то, что гул мотора будет восприниматьс€ как более мощный звук. ћаксимальным называетс€ такое рассто€ние от источника звука до слушател€, начина€ с которого громкость звука больше не уменьшаетс€, а остаетс€ на уровне, который она достигла на максимальном рассто€нии. Ёто означает, что как бы далеко не находилс€ источник звука, он будет слышен.
  • FSOUND_SetPaused () - приостанавливает / возобновл€ет воспроизведение звука в канале.
  • FSOUND_3D_Listener_SetAttributes () / FSOUND_3D_Listener_GetAttributes () - установить/ получить вектор положени€, вектор скорости и векторы ориентации слушател€.
  • FSOUND_Update () -обновить состо€ние звукового микшера, то есть обновить состо€ние звуковой панорамы, после чего все изменени€ в положении слушател€ или источников звука вступают в силу.
  • FSOUND_Sample_Free () - освобождает пам€ть от звуковых данных, загруженных функцией FSOUND_Sample_Load().
  • FSOUND_Close () - выгружает звуковую систему FMOD.

ƒанный список €вл€етс€ минимально необходимым и не включает р€д функций, позвол€ющих получать дополнительную информацию о звуковой карте, поддерживаемых алгоритмах обработки звука и т.п., а также управл€ть некоторыми параметрами воспроизведени€ звука.

јлгоритм использовани€ FMOD в игровых программах

¬ центре нашего внимани€ будут игры, использующие объЄмный (3D) звук.  ак правило, в играх существует основной цикл игры, внутри которого происходит перемещение игровых объектов в пространстве. “акое перемещение может быть вызвано действи€ми игрока (например, в автосимул€торе это может быть поворот рулевого колеса вправо или влево) или изменением игровой ситуации (например, в "экшене" может приблизитс€ монстр). –ассчитав новые координаты объектов, следует изменить и положение источников звука так, чтобы они соответствовали новому положению объектов в игровом пространстве.

»гровому циклу, как правило, предшествует та часть программы, в которой происходит инициализаци€ переменных, загрузка необходимых библиотек и ресурсов. ѕри использовании FMOD, в этой части должны располагатьс€ функции: FSOUND_SetOutput, FSOUND_SetDriver и FSOUND_SetMixer. ¬ качестве параметра дл€ автоматического определени€ базовой звуковой системы в функцию FSOUND_SetOutput можно передать -1 (0FFFFFFFFh).

ѕосле успешной инициализации FMOD необходимо в соответствии со сценарием игры разместить в пам€ти звуковые данные. ‘ункци€ FSOUND_Sample_Load, отвечающа€ за этот процесс, поддерживает несколько звуковых форматов и загрузка, скажем, .mp3 файла с точки зрени€ программиста ничем не отличаетс€ от загрузки файла в формате wav. «десь полностью про€вл€ютс€ достоинства библиотеки FMOD, позвол€ющей упростить утомительную процедуру создани€ звуковых буферов и загрузки в них данных, характерную дл€ DirectSound. –езультатом работы FSOUND_Sample_Load будет указатель на образец звука, размещенный в пам€ти. ≈сли обратитьс€ к терминологии DirectSound, то это будет аналог вторичного звукового буфера. ”казанный образец звука может быть использован дл€ создани€ нескольких источников 3D звука, при этом нет необходимости создавать дополнительные копии этого образца.

“еперь, когда необходимые данные загружены, можно приступать к формированию трЄхмерной звуковой картины. Ќеобходимо помнить, что изменение вектора положени€ и вектора скорости, а также многих иных характеристик источника звука возможно только непосредственно во врем€ воспроизведени€ звука функци€ми FSOUND_PlaySound и FSOUND_PlaySoundEx, поэтому, прежде чем поместить источник звука в какую-либо точку пространства, вы должны начать воспроизведение этого звука. ќднако при вызове указанных функций звук будет воспроизводитьс€ в той точке, где находитс€ слушатель (Listener), что может нарушить сцену игры (например, монстр, который должен приближатьс€ из самого дальнего закоулка, вдруг зарычит под ухом у игрока). „тобы избежать подобного казуса, в функции FSOUND_PlaySoundEx() предусмотрен специальный параметр, который сразу же приостанавливает воспроизведение звука. ћолчащий источник можно, без риска нарушить сцену игры, поместить в нужное место и возобновить воспроизведение звука. ƒл€ того чтобы изменени€ в звуковой картине вступили в силу, необходимо вызвать функцию FSOUND_Update.

—ледует сказать, что в пон€ти€х FMOD воспроизведение звука происходит через канал (channel), поэтому все, что программист собираетс€ сделать с источником 3D звука, необходимо выполн€ть, пользу€сь функци€ми, которые работают с каналом. ѕервым параметром в таких функци€х выступает номер канала.

—интаксис вызова функции FSOUND_PlaySoundEx следующий:

int F_API FSOUND_PlaySoundEx(
int channel,
FSOUND_SAMPLE *sptr,
FSOUND_DSPUNIT *dspunit,
signed char startpaused
);

¬ качестве параметров эта функци€ получает номер канала (channel), через который будет воспроизводитс€ звук,; указатель (дескриптор sptr) на образец звука, размещенный в пам€ти; указатель (дескриптор dspunit) на блок каналов, к которому должен присоединитьс€ вновь создаваемый канал (этот параметр может иметь значение NULL); флаг приостановки воспроизведени€ (paused), который должен быть TRUE, чтобы воспроизведение звука сразу же было приостановлено.

≈сли необходимо создать новый канал, то в параметре channel передаетс€ константа FSOUND_FREE. ≈сли необходимо, чтобы звук воспроизводилс€ во всех существующих каналах, то в channel передаетс€ константа FSOUND_ALL.

‘ункци€ возвращает номер (дескриптор) канала, через который воспроизводитс€ звук. ≈сли возникла ошибка, то функци€ возвращает -1 (0FFFFFFFFH). Ќомер (дескриптор) канала необходим дл€ работы с функци€ми канального уровн€, например, FSOUND_3D_SetAttributes.

“аким образом, создание и позиционирование источника звука программно может быть реализовано так:

FSOUND_SAMPLE *samp1 = NULL;
int channel1 = -1;
/* провер€ем версию FMOD */
if (FSOUND_GetVersion() < FMOD_VERSION)
{
/* обработка ошибки */
return 1;
}
/* выбираем базовую звуковую систему DirectSound */
FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND);
/* выбираем звуковую карту по умолчанию */
FSOUND_SetDriver(0);
/* позвол€ем FMOD выбрать микшер */
FSOUND_SetMixer(FSOUND_MIXER_AUTODETECT);
/* инициализируем FMOD */
/* частота, к которой будут приводитс€ все звуки в микшере, - 22050 √ц */
/* максимальное число программных каналов - 32 */
if (!FSOUND_Init(22050, 32, 0))
{
/* обработка ошибки */
return 1;
}
/* загружаем в пам€ть звуковой фрагмент из файла myfile.wav */
/* константа FSOUND_HW3D указывает, что необходимо включить аппаратную поддержку 3D звука */
samp1 = FSOUND_Sample_Load(FSOUND_FREE, "myfile.wav", FSOUND_HW3D, 0, 0);
if (!samp1)
{
/* обработка ошибки */
return 1; 
}
/* устанавливаем циклическое воспроизведение, т.е. */
/* источник слышен всегда */
FSOUND_Sample_SetMode(samp1, FSOUND_LOOP_NORMAL);
/* указываем позицию и скорость источника */
float pos[3] = { -10.0f, -20.0f, 0.5f };
float vel[3] = { 0,0,0 };
/* создаем новый канал дл€ воспроизведени€ звука */
/* сразу же приостанавливаем воспроизведение */
channel1 = FSOUND_PlaySoundEx(FSOUND_FREE, samp1, NULL, TRUE);
if (channel1 == -1)
{
/* обработка ошибки */
return 1; 
}
/* помещаем источник звука в нужную точку */
FSOUND_3D_SetAttributes(channel1, pos, vel);
/* здесь может происходить изменение позиции слушател€ */
. . .
/* обновл€ем звуковую картину */
FSOUND_Update();
/* возобновл€ем воспроизведение */
FSOUND_SetPaused(channel1, FALSE);
. . .

—ледует помнить, что функции FSOUND_PlaySound и FSOUND_PlaySoundEx помещают источник звука в текущую позицию слушател€, поэтому , если в параметре channel этих функций указан номер (дескриптор) существующего канала, то, несмотр€ на то, что дл€ этого канала функцией FSOUND_3D_SetAttributes была установлена позици€, отлична€ от позиции слушател€, все равно источник звука переместитс€ в позицию слушател€. „тобы избежать искажени€ звуковой картины, необходимо перед вызовом FSOUND_PlaySoundEx сохранить позицию и скорость источника звука в специальных переменных, получив эти значени€ функцией FSOUND_3D_GetAttributes. ѕосле чего вызвать FSOUND_PlaySoundEx с приостановкой воспроизведени€; затем переместить источник в нужную точку, воспользовавшись сохраненными значени€ми, а уж потом продолжить воспроизведение. ”казанна€ последовательность действий, кроме всего прочего, напр€мую относитс€ к однократно проигрываемым звукам (то есть к таким источникам, которые не издают звук непрерывно, а звучат лишь при наступлении определенного событи€ в игре).

ƒл€ изменени€ позиции, скорости и ориентации слушател€ в пространстве следует использовать функцию FSOUND_3D_Listener_SetAttributes. ¬от ее синтаксис:

void F_API FSOUND_3D_Listener_SetAttributes(
const F_FLOAT_API *pos,
const F_FLOAT_API *vel,
F_FLOAT_API fx,
F_FLOAT_API fy,
F_FLOAT_API fz,
F_FLOAT_API tx,
F_FLOAT_API ty,
F_FLOAT_API tz
);

¬ качестве параметров эта функци€ получает указатель на триаду координат позиции (pos), указатель на вектор скорости (vel), X, Y и Z составл€ющие единичного вектора, определ€ющего фронтальную ориентацию головы слушател€ (fx, fy, fz); X, Y и Z составл€ющие единичного вектора, определ€ющего вертикальную ориентацию головы слушател€ (tx, ty, tz). Ќесмотр€ на тип void, функци€, согласно официальной документации, возвращает TRUE, если ее выполнение было успешным, и FALSE в случае ошибки.

¬ отличие от DirectSound3D, в FMOD может быть не один, а несколько слушателей. Ёто сделано дл€ игровых приставок, где одно игровое устройство могут использовать одновременно несколько игроков. ¬ыбор текущего слушател€ производитс€ при помощи функции FSOUND_3D_Listener_SetCurrent.

 огда игра завершена и в заключительном сегменте кода программы происходит освобождение ресурсов, зан€тых программой, необходимо использовать функции FSOUND_Sample_Free, которой в качестве параметра передаетс€ указатель (дескриптор) фрагмента звуковых данных в пам€ти, и FSOUND_Close, котора€ вызываетс€ без параметров и выгружает звуковую систему FMOD.

FSOUND_Sample_Free(samp1); 
FSOUND_Close();

ќбработка ошибок

Ѕольшинство функций FMOD, если иное не оговорено в документации, возвращают TRUE в случае успешного завершени€. ≈сли же в работе функции возникла ошибка, то возвращаетс€ FALSE. ƒл€ того чтобы получить дополнительную информацию об ошибке, следует воспользоватьс€ функци€ми FSOUND_GetError и FMOD_ErrorString. ѕоследн€€ функци€ €вл€етс€ макросом, поэтому необходимо включить заголовочный файл FMOD_errors.h.

‘ункци€ FSOUND_GetError не требует параметров и возвращает код ошибки, возникшей при выполнении функции FMOD. ћакрос FMOD_ErrorString получает этот код в качестве параметра и возвращает текстовое описание ошибки. ¬от пример вызова этих функций:

/* вывод сообщени€ об ошибке в консольном режиме */
printf("Error: %s\n", FMOD_ErrorString(FSOUND_GetError()));

”правление ресурсами и звуковые платы нижней ценовой категории

—егодн€ существуют различные по производительности и возможност€м звуковые карты. ќдни из них способны поддерживать до 100 аппаратных каналов дл€ воспроизведени€ 3D звука, другие - не более четырех. Ѕыло бы недальновидно при разработке игр ориентироватьс€ на "слабые" звуковые карты. ќднако ошибка, котора€ может возникнуть при нехватке аппаратных каналов в игре с большим количеством источников звука, может сделать игру совершенно неработоспособной на указанной группе звуковых карт. ¬ качестве выхода из данной ситуации FMOD предлагает использовать функцию FSOUND_SetMinHardwareChannels.

Ёта функци€ вызываетс€ один раз перед вызовом FSOUND_Init и устанавливает минимальнное количество аппаратных каналов, которое должно поддерживатьс€ звуковой картой. ѕосле этого либо все из указанного при вызове FSOUND_SetMinHardwareChannels числа каналов будут воспроизводитс€ с использованием аппаратных каналов, либо аппаратна€ поддержка использоватьс€ не будет и микширование каналов будет происходить программным путем. »ными словами, например, если у вас 16 звуков и карта имеет такое же или большее число аппаратных каналов, то воспроизведение будет идти через эти каналы. ≈сли окажетс€, что у карты всего 4 канала, то смешивание всех звуков будет выполн€тьс€ программно.

ѕоддержка приоритетов

¬ FMOD реализована система приоритетов. ≈сли множество источников звука должны воспроизводитьс€ на ограниченном числе каналов, то некоторые из них могут быть более важными, чем другие. ≈сли, например, главным действующим лицом в игре выступает стрелок, то воспроизведение звука выстрела было бы, веро€тно, самым важным. “ак что этому источнику звука (выстрел) следовало бы установить самый высокий приоритет посредством FSOUND_SetPriority. ћенее важные звуки не будут воспроизводитьс€, если уже зан€ты все доступные каналы.

«аключение

»зложенный выше материал €вл€етс€ необходимым дл€ того, чтобы познакомитьс€ с возможност€ми FMOD в области работы с объЄмным звуком и начать использовать эту библиотеку в своих программах. Ќо одной этой статьи недостаточно, чтобы узнать о всех возможност€х библиотеки FMOD. —ледующим шагом может стать изучение примеров, вход€щих в дистрибутивный пакет FMOD.



–аспространение материалов сайта означает, что распространитель прин€л услови€ лицензионного соглашени€.
»де€ и реализаци€: © ¬ладимир ƒовыденков и јнатолий  амынин,  2004-2022