Главная Статьи Ссылки Скачать Скриншоты Юмор Почитать Tools Проекты Обо мне Гостевая |
Библиотека OpenAL (Open Audio Library), разработанная и поддерживаемая компаниями Creative Labs и Loki Entertainment, представляет собой бесплатную, кроссплатформенную библиотеку для работы с 3D-звуком с открытым кодом. Существуют версии OpenAL для платформ Mac OS 8/9, Mac OS X, Linux, BSD, Solaris, IRIX и M$ Windows.
Эта библиотека была использована в ряде игр, таких как Unreal II, Unreal Tournament 2003/2004, версии Doom III для Linux.
Большими плюсами этой библиотеки (кроме поддержки такой компании как Creative Labs) является как ее простота, так и то, что по стилю она очень сильно напоминает библиотеку OpenGL. Поэтому для программистов, уже знакомых с OpenGL, освоение OpenAL становится очень простым и быстрым.
Для начала работы с OpenAL скачайте OpenAL SDK для используемой Вами платформы. Все примеры к данной статье компилировались как для Windows, так и для Linux.
Основными понятиями OpenAL являются аудиоустройство (audio device), аудиоконтекст (audio context), слушатель (listener), источники звука (sources) и буфера (buffers).
Понятие контекста в OpenAL очень близко к своему аналогу в OpenGL. Все производимые изменения параметров происходят в пределах определенного контекста, связанного с аудиоустройством. Возможно наличие нескольких аудиоконтекстов для одного аудиоустройства, между которыми можно переключаться.
Для простейших примеров всю работу с аудио устройствами и контекстами можно переложить на входящую в состав OpenAL SDK библиотеку alut.
Библиотека OpenAL позволяет задавать в трехмерном пространстве различные источники звука и слушателя. И для каждого источника звука и для слушателя можно задать ряд параметров (таких как, положение, скорость и т.п.), влияющих на получающийся в результате звук.
Библиотека OpenAL на основе этой информации осуществляет обработку звука (учитывая при этом как взаимное расположение слушателя и источников звука, так и их скорости). После обработки происходит смешение звука от различных источников для получение выходного сигнала для каждого из выходных каналов.
Кроме интуитивно понятных понятий слушателя и источников, в OpenAL важную роль играет понятие буфера. Именно посредством буферов осуществляется задание непосредственных звуковых данных (Raw PCM), которые должны выводится для каждого из источников.
Можно для источника задать сразу несколько буферов, организовав их в очередь. Тогда после того как все данные из одного буфера будут выведены, происходит автоматическое переключение на следующий буфер.
Рассмотрим сначала несколько простых примеров работы с OpenAL, основанных на использовании библиотеки alut, в конце статьи будут приведены несколько классов на С++, заметно облегчающих использование OpenAL.
В этом и ряде следующих примеров мы будем активно использовать библиотеку alut для упрощения работы с OpenAL.
Первым шагом при работе с OpenAL является инициализация - получение устройства и создание контекста. При использовании alut для этого можно использовать всего одну функцию - alutInit.
void alutInit ( int * argc, char * argv [] );
Входными параметрами этой функции являются указатель на аргумент argc и аргумент argv функции main (полностью аналогично функции glutInit).
Эта функция осуществляет создание устройства (под M$ Windows обычно используется DirectSound3D) и контекста для него.
Для проверки успешности вызова alutInit (как и практически любой функции OpenAL) служит функция alGetError. При отсутствии ошибок она возвращает значение AL_NO_ERROR.
int main ( int argc, char * argv [] ) { alutInit ( &argc, argv ); if ( alGetError () != AL_NO_ERROR ) { printf ( "Ошибка инициализации\n" ); exit ( 1 ); } . . . . . . . }
Для завершения работы с OpenAL можно использовать функция alutExit:
void alutExit ();
После инициализации OpenAL необходимо создать источник звука и буфер для него, а также задать их свойства.
Каждый источник звука (и буфер) задается беззнаковым целым числом (типа ALuint). Для создания источников и буферов служат следующие функции.
ALvoid alGenSources ( ALsizei n, ALuint * sources ); ALvoid alGenBuffers ( ALsizei n, ALuint * buffers );
Каждая из этих функций принимает два параметра - сколько соответствующих объектов (источников или буферов) надо создать (n) и указатель на массив, в который надо поместить идентификаторы созданных объектов (sourcesили buffers).
Как и ранее, для проверки успешности создания объектов следует использовать функцию alGetError.
ALuint buffer; ALuint source; alGenBuffers ( 1, &buffer ); if ( alGetError () != AL_NO_ERROR ) exit ( 1 ); alGenSources ( 1, &source ); if ( alGetError () != AL_NO_ERROR ) exit ( 1 );
Следующие функции служат для уничтожения созданных источников и буферов.
ALvoid alDeleteBuffers ( ALsizei n, ALuint * buffers ); ALvoid alDeleteSources ( ALsizei n, ALuint * sources );
Сама библиотека OpenAL не содержит в себе функций для работы со звуковыми файлами различных форматов (таких как wav, mp3, ogg и т.п.). Задачей пользователя является декодирование таких файлов (к счастью для этого хватает библиотек) и передача декодированных PCM-данных в OpenAL.
Однако для удобства в библиотеку alut входят функции, позволяющие загружать звуковые данные из популярного формата wav.
ALboolean alutLoadWAVFile ( const char * fileName, ALsizei * format, ALsizei * size, ALsizei * bits, ALsizei * freq, ALboolean *loop ); ALvoid alutUnloadWAV ( ALenum format, ALvoid * data, ALsizei size, ALsizei freq );
Входной параметр fileName задает имя файла, из которого следует загрузить звуковые данные. Параметр format является указателем на переменную, в которую будет записан формат звуковых данных (см. далее описание функции alBufferData). Параметр size является указателем на переменную, в которую будет записан объем декодированных данных в байтах.
Параметр bits является указателем на переменную, в которую будет записано количество бит, служащее для представления единицы данных (sample) - 8 или 16 бит. Параметр freq задает частоту воспроизведения данных. Последний параметр loop определяет надо ли зациклить данный звук (т.е. постоянно повторять).
Функция alutUnloadWAVFile служит для освобождения памяти, выделенной при декодировании wav-файла.
Используя эти функции, легко осуществлять загрузку звуковых данных в буфер. Для этого в OpenAL служит функция alBufferData.
ALvoid alBufferData ( ALuint buffer, ALenum format, ALvoid * data, ALsizei size, ALsizei freq );
Параметр buffer является идентификатором буфера, данные для которого задаются этой командой. Параметр format определяет формат звуковых данных и может принимать одно из следующих значений - AL_FORMAT_MONO8, AL_FORMAT_MONO16, AL_FORMAT_STEREO8 и AL_FORMAT_STEREO16.
Параметр data является указателем на буфер со звуковыми данными. Обратите внимание, что данная команда копирует данные, поэтому после данной команды память, на которую указывает данный параметр можно изменять или освободить.
Остальные параметры имеют тот же смысл, что и в команде alutLoadWAVFile.
Ниже приводится фрагмент кода, осуществляющий загрузку wav-файла в созданный буфер.
ALenum format; ALsizei size; ALvoid * data; ALsizei freq; ALboolean loop; alutLoadWAVFile ( fileName, &format, &data, &size, &freq, &loop ); alBufferData ( buffer, format, data, size, freq ); alutUnloadWAV ( format, data, size, freq );
После создания буфера и заполнения его звуковыми данными, следует задать параметры источника звука. Для этого служат следующие функции.
ALvoid alSourcef ( ALuint source, ALenum pname, ALfloat value ); ALvoid alSourcefv ( ALuint source, ALenum pname, ALfloat * values ); ALvoid alSource3f ( ALuint source, ALenum pname, ALfloat v1, ALfloat v2, ALfloat v3 ); ALvoid alSourcei ( ALuint source, ALenum pname, ALint value );
Параметр source задает для какого именно источника звука задается значение.
Параметр pname задает имя изменяемого свойства. В следующей таблице приводятся допустимые значения для данного параметра.
Таблица 1. Параметры источника.
Константа | Используется в функциях | Значение |
---|---|---|
AL_PITCH | alSourcef | Параметр pitch |
AL_GAIN | alSourcef | Параметр, используемый в модели учета расстояния |
AL_MAX_DISTANCE | alSourcef | Максимальное расстояние, далее него уже не будет происходить дальнейшего ослабления звука |
AL_ROLLOFF_FACTOR | alSourcef | Параметр rolloff, используемый в модели учета расстояния |
AL_REFERENCE_DISTANCE | alSourcef | Расстояние, на котором сила звука уменьшается вдвое (до воздействия параметра rolloff |
AL_MIN_GAIN | alSourcef | Минимальное значение параметра gain |
AL_MAX_GAIN | alSourcef | Максимальное значение параметра gain |
AL_CONE_OUTER_GAIN | alSourcef | Значение параметра gain вне конуса звука |
AL_CONE_INNER_ANGLE | alSourcei | Значение параметра gain внутри конуса звука |
AL_CONE_OUTER_ANGLE | alSourcei | Угол конуса для источника звука, по умолчанию 360 |
AL_POSITION | alSourcefv alSource3f | Положение источника звука |
AL_VELOCITY | alSourcefv alSource3f | Скорость источника звука |
AL_DIRECTION | alSourcefv alSource3f | Направление источника |
AL_SOURCE_RELATIVE | alSourcei | Определяет, задаются ли координаты источников относительно слушателя или нет |
AL_LOOPING | alSourcei | Включить ли режим повторения (looping)для источника |
AL_BUFFER | alSourcei | Идентификатор используемого источника звука |
AL_SOURCE_STATE | alSourcei | Текущее состояние источника (AL_PLAYING, AL_STOPPED,...) |
Следующий пример - задание основных параметров источника звука.
Vector3D sourcePos ( 0, 0, 2 ); // source position Vector3D sourceVel ( 0, 0, 0 ); // source velocity (used for doppler effect) alSourcei ( source, AL_BUFFER, buffer ); alSourcef ( source, AL_PITCH, 1.0f ); alSourcef ( source, AL_GAIN, 1.0f ); alSourcefv( source, AL_POSITION, sourcePos ); alSourcefv( source, AL_VELOCITY, sourceVel ); alSourcei ( source, AL_LOOPING, AL_TRUE );
В отличии от источников звука и буферов, слушатель существует всегда (и он всегда один). Он также обладает рядом свойств, которые можно устанавливать при помощи следующих команд:
ALvoid alListenerf ( ALenum pname, ALfloat value ); ALvoid alListener3f ( ALenum pname, ALfloat v1, ALfloat v2, ALfloat v3 ); ALvoid alListenerfv ( ALenum pname, ALfloat * values ); ALvoid alListeneri ( ALenum pname, ALint value );
Параметр pname задает имя изменяемого свойства. В следующей таблице приводятся допустимые значения для данного параметра.
Таблица 2. Параметры слушателя.
Константа | Используется в функциях | Значение |
---|---|---|
AL_POSITION | alListener3f alListenerfv | Координаты слушателя |
AL_VELOCITY | alListener3f alListenerfv | скорость слушателя |
AL_ORIENTATION | alListenerfv | Ориентация наблюдателя. Задается 6 числами |
AL_GAIN | alListenerf | Параметр master gain, используемый для учета расстояния |
OpenAL может использовать несколько моделей учета расстояния от слушателя до источника звука. Выбор модели осуществляется при помощи следующей функции:
ALvoid alDistanceModel ( ALenum value );
Параметр value задает используемую модель и может принимать одно из следующий значений - AL_NONE, AL_INVERSE_DISTANCE и AL_INVERSE_DISTANCE_CLAMPED.
Изменение громкости звука в зависимости от расстояния в модели AL_INVERSE_DISTANCE задается следующие формулы:
f = AL_GAIN – 20*lg (1 + AL_ROLLOFF_FACTOR*(distance–AL_REFERENCE_DISTANCE)/ AL_REFERENCE_DISTANCE)) f = min(f, AL_MAX_GAIN); f = max(f, AL_MIN_GAIN);
При использовании модели AL_INVERSE_DISTANCE_CLAMPED используются следующие формулы:
distance = max(distance, AL_REFERENCE_DISTANCE); distance = min(distance, AL_MAX_DISTANCE); f = AL_GAIN – 20*log(1 + AL_ROLLOFF_FACTOR*(distance-AL_REFERENCE_DISTANCE)/ AL_REFERENCE_DISTANCE)); f = min(G_dB, AL_MAX_GAIN); f = max(G_dB, AL_MIN_GAIN);
При использовании модели AL_NONE применяется следующая формула:
f = AL_GAIN;
Ориентация наблюдателя в OpenAL задается при помощи 6 вещественных чисел, определяющих два трехмерных вектора - at и up (см рис. 1).
Рис 1. Задание ориентации слушателя.
Следующие функции служат для управления воспроизведением звука.
ALvoid alSourcePlay ( ALuint source ); ALvoid alSourcePlayv ( ALsizei n, ALuint * sources ); ALvoid alSourcePause ( ALuint source ); ALvoid alSourcePausev ( ALsizei n, ALuint * sources ); ALvoid alSourceStop ( ALuint source ); ALvoid alSourceStopv ( ALsizei n, ALuint * sources ); ALvoid alSourceRewind ( ALuint source ); ALvoid alSourceRewindv ( ALsizei n, ALuint * sources );
Действия данных функций понятны из названия. Обратите внимание, на наличие функций, позволяющих применять выбранную операцию сразу к целому набору источников - параметр n задает количество источников звука в массиве sources.
Ниже приводится полный исходный код простейшего примера использования OpenAL.
#include <stdlib.h> #include <stdio.h> #include <time.h> #include <al.h> #include <alc.h> #include <alut.h> #include "Vector3D.h" #ifndef _WIN32 #include "kbhit.h" #else #include <conio.h> #define initKeyboard() #define closeKeyboard() #endif ALuint buffer; // buffer for sound data ALuint source; // source of sound Vector3D sourcePos ( 0, 0, 2 ); // source position Vector3D sourceVel ( 0, 0, 0 ); // source velocity (used for Doppler effect) Vector3D listenerPos ( 0, 0, 0 ); // listeners position Vector3D listenerVel ( 0, 0, 0 ); // listern's velocity // listeners orientation (forward, up) float listenerOri [] = { 0, 0, -1, 0, 1, 0 }; bool setupSource ( char * fileName ) { ALenum format; ALsizei size; ALvoid * data; ALsizei freq; ALboolean loop; alGenBuffers ( 1, &buffer ); // create buffer if ( alGetError () != AL_NO_ERROR ) return false; // load .wav data using alut alutLoadWAVFile ( (ALbyte *)fileName, &format, &data, &size, &freq, &loop ); alBufferData ( buffer, format, data, size, freq ); alutUnloadWAV ( format, data, size, freq ); alGenSources ( 1, &source ); // create source if ( alGetError () != AL_NO_ERROR ) return false; // setup source params alSourcei ( source, AL_BUFFER, buffer ); alSourcef ( source, AL_PITCH, 1.0f ); alSourcef ( source, AL_GAIN, 1.0f ); alSourcefv( source, AL_POSITION, sourcePos ); alSourcefv( source, AL_VELOCITY, sourceVel ); alSourcei ( source, AL_LOOPING, loop ); return true; } int main ( int argc, char * argv [] ) { initKeyboard (); // for Linux setup keyboard raw mode alutInit ( NULL, 0 ); // initialize OpenAL and clear the error bit. alGetError (); char * fileName = argv [1]; if ( argc < 2 ) fileName = "wavdata/Footsteps.wav"; if ( !setupSource ( fileName ) ) // load the wav data. { printf ( "Error loading data \"%s\"\n.", fileName ); return 0; } alListenerfv ( AL_POSITION, listenerPos ); alListenerfv ( AL_VELOCITY, listenerVel ); alListenerfv ( AL_ORIENTATION, listenerOri ); printf ( "Use p to play sound, s to stop sound, h to pause sound and q to quit\n" ); for ( char ch = '\0'; ch != 'q'; ) { ch = getche (); switch ( ch ) { case 'p': alSourcePlay ( source ); break; case 's': alSourceStop ( source ); break; case 'h': alSourcePause ( source ); break; } } alDeleteBuffers ( 1, &buffer ); alDeleteSources ( 1, &source ); alutExit (); closeKeyboard (); // for Linux setup keyboard raw mode return 0; }
Функции initKeyboard и closeKeyboard служат для приведения клавиатуры под Linux в небуферизованный режим, используемый реализациями функций kbhit и getche.
Библиотека OpenAL осуществляет учет как расстояния до источника звука, так и его скорости (а также и скорости самого слушателя).
Расстояние до источника звука влияет на громкость звука, а для учета скоростей используется эффект Допплера (т.е. изменение воспринимаемой слушателем частоты звука).
Также учитывается ориентация слушателя относительно источника звука.
Обратите внимание, что все эти действия относятся только к моно-источникам звука. В случае стерео-источников происходит просто их проигрывания без учета расстояний, скоростей и ориентации.
Для организации движения источника звука достаточно просто периодически изменять его положение в пространстве. Обратите внимание, что для источника звука (как и для слушателя) положение и скорость никак между собой не связаны - скорость используется только для эффекта Допплера, перемещать источники (и наблюдателя) должны Вы сами.
На следующем листинге приводится пример, в котором источник звука двигается по круговой орбите вокруг наблюдателя.
#include <stdlib.h> #include <stdio.h> #include <time.h> #include <al.h> #include <alc.h> #include <alut.h> #include "Vector3D.h" #ifndef _WIN32 #include "kbhit.h" #else #include <conio.h> #define initKeyboard() #define closeKeyboard() #endif ALuint buffer; // buffer for sound data ALuint source; // source of sound Vector3D sourcePos ( 0, 0, 2 ); // source position Vector3D sourceVel ( 0, 0, 0 ); // source velocity (used for doppler effect) Vector3D listenerPos ( 0, 0, 0 ); // listeners position Vector3D listenerVel ( 0, 0, 0 ); // listern's velocity // listeners orientation (forward, up) float listenerOri [] = { 0, 0, -1, 0, 1, 0 }; bool setupSource ( char * fileName ) { ALenum format; ALsizei size; ALvoid * data; ALsizei freq; ALboolean loop; alGenBuffers ( 1, &buffer ); // create buffer if ( alGetError () != AL_NO_ERROR ) return false; // load .wav data using alut alutLoadWAVFile ( (ALbyte *)fileName, &format, &data, &size, &freq, &loop ); alBufferData ( buffer, format, data, size, freq ); alutUnloadWAV ( format, data, size, freq ); alGenSources ( 1, &source ); // create source if ( alGetError () != AL_NO_ERROR ) return false; // setup source params alSourcei ( source, AL_BUFFER, buffer ); alSourcef ( source, AL_PITCH, 1.0f ); alSourcef ( source, AL_GAIN, 1.0f ); alSourcefv( source, AL_POSITION, sourcePos ); alSourcefv( source, AL_VELOCITY, sourceVel ); alSourcei ( source, AL_LOOPING, AL_TRUE ); return true; } int main ( int argc, char * argv [] ) { initKeyboard (); alutInit ( NULL, 0 ); // initialize OpenAL and clear the error bit. alGetError (); char * fileName = argv [1]; if ( argc < 2 ) fileName = "wavdata/Footsteps.wav"; if ( !setupSource ( fileName ) ) // load the wav data. { printf ( "Error loading data \"%s\"\n.", fileName ); return 0; } alListenerfv ( AL_POSITION, listenerPos ); alListenerfv ( AL_VELOCITY, listenerVel ); alListenerfv ( AL_ORIENTATION, listenerOri ); printf ( "Press q to quit\n" ); alSourcePlay ( source ); while ( !kbhit () ) { float secs = clock () / CLOCKS_PER_SEC; sourcePos.x = 5*sin(secs*0.3); sourcePos.z = 5*sin(secs*0.3); alSourcefv ( source, AL_POSITION, sourcePos ); } getche (); alDeleteBuffers ( 1, &buffer ); alDeleteSources ( 1, &source ); alutExit (); closeKeyboard (); return 0; }
С помощью OpenAL легко можно осуществлять смешение звуков от нескольких источников - для этого достаточно просто создать соответствующие источники и начать воспроизведение каждого из них.
Если мы хотим воспроизводить звуковые данные из mp3 или ogg файлов, то возникает ситуация, когда полностью распакованные данные из такого файла будут занимать десятки мегабайт при сравнительно небольшом объеме исходного файла.
Поэтому в таком случае желательно иметь возможность не полностью распаковывать весь сжатый файл, а делать это по частям, по мере проигрывания данных.
Именно такую возможность и предоставляет OpenAL через механизм выстраивания нескольких буферов для одного источника звука при помощи функций:
ALvoid alSourceQueueBuffers ( ALuint source, ALsizei n, ALuint * buffers ); ALvoid alSourceUnqueueBuffers ( ALuint source, ALsizei n, ALuint * buffers );
Первая из этих функций ставит в очередь к источнику source сразу n буферов, идентификаторы которых передаются в массиве buffers. По мере проигрывания данных будет происходить автоматическое переключение к следующему буферу из очереди.
Буфера, звуковые данные из которых уже были воспроизведены и больше не нужны, удаляются из очереди при помощи функции alSourceUnqueueBuffers.
Узнать сколько буферов для данного источника уже были обработаны (т.е. больше не нужны и могут быть удалены из очереди) можно при помощи следующего фрагмента кода.
ALuint processed; alGetSourceiv ( source, AL_BUFFERS_PROCESSED, &processed );
После этого вызова в переменной processed будет содержаться количество буферов, которые можно удалить из очереди и переиспользовать (т.е. загрузить новыми звуковыми данными и опять поставить в очередь).
Рекомендуется при использовании очереди для задания буферов всегда использовать команду alSourceQueueBuffers и использовать буфера с одинаковым форматом звуковых данных.
Для работы с OpenAL без использования alut необходимо открыть подходящее аудиоустройство и создать для него аудиоконтекст.
Для работы с аудиоустройствами в OpenAL используются следующие функции:
ALCdevice * alcOpenDevice ( const ALubyte * tokstr ); void alcCloseDevice ( ALCdevice * dev );
В качестве параметра tokstr выступает строка, описывающая устройство, например "DirectSound3D". Вместо строки можно передать значение NULL. В этом случае OpenAL сам подберет подходящее устройство (под M$ Windows это обычно DirectSound3D).
Следующим шагом после открытия аудиоустройства является создание для него аудиоконтекста и выбор его в качестве текущего.
Для работы с контекстами в OpenAL служат следующие функции:
void * alcCreateContext ( ALCdevice * dev, ALint * attrlist ); ALCenum alcDestroyContext ( ALvoid * alcHandle ); ALCenum alcMakeContextCurrent ( ALvoid * alcHandle ); void alcSuspendContext ( ALvoid * alcHandle ); void alcProcessContext ( ALvoid * alcHandle );
Функция alcCreateContext используется для создание нового аудиоконтекста. Ее первым параметром служит указатель на аудиоустройства, для которого создается аудиоконтекст. Второй параметр является указателем на список атрибутов. Обычно он используется, когда есть несколько аудиоконтекстов. В случае одиночного контекста проще всего в качестве второго параметра использовать значения NULL.
Функция alcDestroyContext служит для уничтожения созданного контекста, она возвращает код ошибки.
Функция alcMakeContextCurrent позволяет выбрать заданный аудиоконтекст в качестве текущего.
Функции alcSuspendContext и alcProcessContext позволяют приостановить обработку заданного аудиоконтекста и снова ее возобновить. В частности приостановление аудиоконтекста приводит к приостановке воспроизведения источников звука, связанных с данным контекстом.
Таким образом, для инициализации OpenAL можно использовать следующий фрагмент кода
ALCdevice * device = NULL; ALCcontext * context = NULL; device = alcOpenDevice ( NULL ); context = alcCreateContext ( device, NULL ); alcMakeCurrent ( context );
Для завершения работы с OpenAL служит следующий фрагмент кода:
alcMakeCurrent ( NULL ); alcDestroyContext ( context ); alcCloseDevice ( device );
Подобно библиотеке OpenGL в OpenAL также есть поддержка расширений. Для получения списка всех поддерживаемых расширением следует использовать функцию alcGetString:
const char * exts = (const char *) alcGetString ( device, ALC_EXTENSIONS );
Для проверки поддерживается ли данное расширение можно использовать следующую функцию.
ALboolean alcIsExtensionPresent ( ALCdevice * device, ALubyte * extName );
В случае поддержки расширения можно использовать функцию alcGetProcAddress для получения адресов вводимых расширением функций по их именам:
ALvoid * alcGetProcAddress ( ALCdevice * device, ALubyte * funcName );
Для облегчения работы будет очень удобно завернуть все основные используемые понятия в объекты. Явными кандидатами на такие объекты является аудиоконтекст (и аудиустройство, связанное с ним), источники данных и файлы со звуковыми данными, слушатель.
Отдельно заворачивать буфера в объекты не имеет смысла, так как они используются только в связи с источниками звука и файлами со звуковыми данными.
Используемые классы и их взаимоотношения изображены на следующем рисунке.
Рис 2. Диаграмма используемых классов.
Ниже приводится описание класса OpenAlContext, обеспечивающего как инициализацию/деинициализацию OpenAL, так и поддержку основных свойств слушателя.
class OpenAlContext { protected: ALCdevice * device; // device & context for working with OpenAL ALCcontext * context; Vector3D pos; // listener's position Vector3D velocity; // listeners velocity (for Doppler effect) Vector3D viewDir; // listener's orientation - view and up vectors Vector3D upDir; public: OpenAlContext (); ~OpenAlContext (); bool isOk () const { return device != NULL && context != NULL; } const Vector3D& getPos () const { return pos; } const Vector3D& getVelocity () const { return velocity; } const Vector3D& getViewDir () const { return viewDir; } const Vector3D& getUpDir () const { return upDir; } void moveTo ( const Vector3D& newPos ); void moveBy ( const Vector3D& delta ); void setVelocity ( const Vector3D& newVel ); void setOrientation ( const Vector3D& view, const Vector3D& up ); static SoundData * open ( const char * fileName ); static bool registerSound ( Sound * sound ); static bool unregisterSound ( Sound * sound ); static void updateSounds (); };
Для работы со источниками звука используется класс Sound.
class Sound { protected: SoundData * dataSource; bool looping; bool stream; ALuint format; ALuint source; ALuint buffer [2]; // id's of OpenAL buffers int currentBuffer; byte * buf; // buffer for sound data Vector3D pos; // sound source position Vector3D velocity; // sound source velocity float pitch; float gain; public: Sound ( SoundData * data, bool theLoop = false ); ~Sound (); const Vector3D& getPos () const { return pos; } const Vector3D& getVelocity () const { return velocity; } float getGain () const { return gain; } float getPitch () const { return pitch; } bool getLooping () const { return looping; } bool isPlaying () const; bool atEnd () const; void setPos ( const Vector3D& newPos ); void setVelocity ( const Vector3D& newVel ); void setPitch ( float newPitch ); void setGain ( float newGain ); void setLooping ( bool flag ); void play (); void pause (); void stop (); void rewind (); void update (); enum { BUFFER_SIZE = 65536 // buffer size for unpacked PCM data }; };
За счет использования данных классов работа с OpenAL предельно упрощается - ниже приводится листинг программы, использующей введенные классы для вывода звука (как из wav, так и из mp3 и ogg файлов).
#include <stdio.h> #include <stdlib.h> #ifndef _WIN32 #include "kbhit.h" #else #include <windows.h> #include <conio.h> #include <process.h> #define initKeyboard() #define closeKeyboard() #endif #include "OpenAlContext.h" #include "Sound.h" #include "SoundData.h" int main () { OpenAlContext context; SoundData * data = OpenAlContext :: open ( "wavdata/Chi Mai.mp3" ); if ( data == NULL ) return 1; initKeyboard (); Sound * sound = new Sound ( data, true ); sound -> play (); for ( ; ; ) { sound -> update (); if ( kbhit () ) break; int i, j; // small delay for ( i = j = 0; i < 1000; i++ ) j += i*j + 1; } closeKeyboard (); return 0; }
Полный исходный код к данной статье (включая реализации всех вводимых классов) можно скачать здесь.
Для компилирования и работы этих примеров кроме OpenAL SKD, Вам также понадобятся библиотека libmad (используемая для декодирования mp3-файлов) и библиотеки Ogg Vorbis и Ogg Bitstream, используемые для декодирования ogg файлов.
Также доступны для скачивания откомпилированные версии для M$ Windows, Linux и Mac OS X.