Програмиране на 3D звук с OpenAL

Преводни и оригинални статии в областта на разработката на игри.
gemicha
Site Admin
Site Admin
Мнения: 2930
Регистриран: 20 ное 2003 22:20
Местоположение: USA

Програмиране на 3D звук с OpenAL

Мнение от gemicha » 15 мар 2004 11:27

Програмиране на 3D звук с OpenAL
Автор: Dan Ricart
Материалът е взет от DevMaster и е публикуван с разрешението на автора
E-mail на автора: Athletics2@comcast.net
Превод от английски: Максим Крижановски (DarkLight)
e-mail: darklight@mail.bg

С увеличаването на възможностите на звуковите карти и на звуковите API (Application Programming Interface) през годините, 3D звукът започва да играе все по-важна роля в игрите. Създаването на впечатляващо преживяване за геймъра минава отвъд добре изглеждащата графика. Ако се направи добре, заобикалящите звуци и музика могат да пренесат играта на едно съвсем ново ниво. За да се постигне този ефект са създадени различни библиотеки за управление на звука, като DirectSound и DirectSound3D на Мicrosofтt, A3D на Aureal и EAX на Creative Labs. По-късно Loki Entertainment и Creative Labs създадоха OpenAL. Направиха я с цел да създадат по-стандартна, платформено независима библиотека, която да позволи на разработчиците да добавят звук към всяко приложение. Тази статия разяснява основите на OpenAL и показва как да започнете да използвате 3D звук към вашите проекти.

OpenAL в основата си е аудио библиотека, която съдържа функции за възпроизвеждане на звук и музика в компютърна игра. Тя позволява на програмиста да зареди каквито пожелае звуци и да контролира определени характеристики като позицията, скоростта, посоката и ъгъла на конусите, определящи как звукът се пренася в пространството. Всички звуци се позиционират относително спрямо текущата позиция на геймъра в игралния свят. Колкото повече героят се приближава, толкова по-силен става звукът. Освен това OpenAL може да се използва за възпроизвеждането на музика. OpenAL позволява използването на поточна, непрекъсната фонова музика. OpenAL поддържа използването на DirectSound3D и EAX - тя предоставя функции, които позволяват използването на тези две библиотеки без необходимостта от допълнителен код.

Основното предимство на OpenAL пред DirectSound и EAX е, че OpenAL е проектирана да бъде платформено-независима библиока. Възможно е да свалите Windows, Mac и Linux версии на библиотеката, така че тя може да се използва на множество различни операционни ситеми. DirectSound и DirectSound3D са предназначени единствено за Windows, а EAX в основата си е разширение на на DirectSound3D. За онези, които искат да пишат приложения за множество операционни системи, OpenAL може да е подходящото средство. Това ръководство има за цел да ви покаже как да се възползвате от основната функционалност на OpenAL под Windows. Кодът, показан тук е от демо-приложението, което можете да си свалите за да видите цялостен пример. За изображението в демото е използван OpenGL, което показва някои от приликите между OpenGL и OpenAL.

Откъде да започнем

Първото нещо, което трябва да направите, е да се сдобиете с OpenAL SDK. Това можете да направите от сайта за разработчици на Creative Labs на адрес http://developer.creative.com След като веднъж OpenAL SDK е инсталиран, можете да започнете да използвате неговите функции. Първо трябва да инициализирате библиотеката - обикновено това се прави при стартирането на вашата игра или приложение. За моето приложение избрах да използвам DirectSound3D, но е възможно използването и на EAX. Инициализационният код изглежда така:

Код: Избери всички

 
ALCcontext *Context; 
ALCdevice *Device; 
Device = alcOpenDevice((ALubyte*)"DirectSound3D"); 
if (Device == NULL) 
exit(-1); 

//Създаване на контекст 
Context=alcCreateContext(Device, NULL); 
//Настройване на активния контекст 
alcMakeContextCurrent(Context); 
// Изтриване на кода за грешка 
alGetError(); 


Зареждане на звуци

След като веднъж сте инициализирали OpenAL, можете да започнете да запълвате буферите със звуци. Първата стъпка е да запълните буфера със звук използвайки функцията аlutLoadWAVFile. След като сте запълнили буфера, трябва да го прикачите към източник на звук. Този източник може да се използва за възпроизвеждане на звука. Кодът за зареждане на звук изглежда така:

Код: Избери всички

 
char* alBuffer; //данни в буфера 
ALenum alFormatBuffer; //Формат на буфера 
ALsizei alFreqBuffer; //Честота на буфера 
long alBufferLen; //Битова дълбочина 
ALboolean alLoop; //дали е затворен цикъл 
unsigned int alSource; //идентификатор на източник 
unsigned int alSampleSet; //идентификатор на буфер 

//Зареждане на WAVE файл 
alutLoadWAVFile("test.wav",&alFormatBuffer, (void**) &alBuffer,(unsigned int *)&alBufferLen, &alFreqBuffer, &loop); 

//Създаване на 1 източник 
alGenSources(1, &alSource); 

//Създаване на 1 буфер 
alGenBuffers(1, &alSampleSet); 

//Запълване на буфера с данните от alBuffer 
alBufferData(alSampleSet, alFormatBuffer, alBuffer, alBufferLen, alFreqBuffer); 

//Асоцииране на буфера към източника 
alSourcei(alSource, AL_BUFFER, alSampleSet); 

//Освобождаване на данните 
alutUnloadWAV(alFormatBuffer, alBuffer, alBufferLen, alFreqBuffer); 


Първата стъпка тук беше зареждането на файла "test.wav". Данните се прочитат и съхраняват в lBuffer. След това се създават източник и буфер. Тогава буфера се запълва с данните от alBuffer. След това буфера е асоцииран към източника и информацията за WAVE файла е освободена.

Настройване на свойствата на източника

След като имате източник, ще трябва да настроите някои от неговите свойства. За да го направите, трябва да използвате функцията alSource. Тази функция работи подобно на функциите в OpenGL където съществуват различни версии на функцията, като например alSourcei, alSourcef, alSource3f и т.н. Свойствата които настройвате определят коя от версиите да използвате. Настройването на нещо като височината на тона например, има нужда само от един параметър от тип с плаваща запетая, така че се използва alSourcef. Първият параметър, предаден на функцията, е източникът, чиито свойства настройвате. Вторият параметър отговаря на променяното свойство. Останалите параметри са действителните настройки за това свойство. По-нататък съм дал пример за настройването на позицията и скороста на източника на звука:

Код: Избери всички

 
//определяне на позицията на звука 
alSource3f(alSource,AL_POSITION, xposition, yposition, zposition); 

//определяне на скоростта на разпространение на звука 
alSource3f(alSource,AL_VELOCITY, xvelocity, yvelocity, zvelocity); 


Тук alSource е нашият източник на звук, а AL_POSITION и AL_VELOCITY показват, че искаме да променим позицията и скоростта на разпространение на звука на този източник. Останалите параметри са числа с плаваща запетая, които съдържат конкретните стойности за позицията и скоростта съответно по X-, Y- и Z-координатите.

Използване на слушател:

Използването на слушател в 3D звука е важно за да имате относителна точка, в която се чува звукът. Колкото по-близо е слушателят до позицията на източника на звука, толкова по силен ще бъде звукът ако няма препятствия помежду им. OpenAL има настроен обект за слушател, така че всичко което трябва да направите е да модифицирате свойствата му както са ви необходими. Най-важните свойства на слушателя са позицията и ориентацията му в пространството. Тези свойства обикновено се обновяват при всеки кадър от играта. Позицията определя къде се намира в момента слушателят, докато ориентацията определя накъде е обърнат. Например ако слушателят е обърнат на запад и звукът идва от север, ще изглежда че звукът идва отдясно. Обаче ако ориентацията на играча се промени и той се обърне на север, звукът вече ще изглежда да идва право отпред.

Модифицирането на свойствата на слушателя е подобно на промяната на свойствата на източника. Използва се функцията alListener , която има различни версии в зависимост от свойството, което модифицирате. Например за да определите позицията на слушателя, можете да извикате alListener3f и да зададете 3 отделни числа с плаваща запетая или можете да извикатеl alListenerfv и да подадете масив от числа с плаваща запетая. Параметрите за позицията са просто X-, Y- и Z- координатите на слушателя в игралния свят. Ориентацията обаче изисква 6 параметъра. Първите три са за вектора, който отговаря на посоката, в която слушателят гледа. Следващите три са за вектора, сочещ право нагоре от слушателя (по този начин се определя къде е горе, т.е. накъде е наклонен слушателят - б.пр). Ето и пример за определянето на позицията и ориентацията на слушателя:

Код: Избери всички

 
float listenerx, listenery, listenerz; 
float vec[6]; 

listenerx=10.0f; 
listenery=0.0f; 
listenerz=5.0f; 

vec[0] = fvecx; //x-координата на вектора, сочещ напред 
vec[1] = fvecy; //y-координата на вектора, сочещ напред 
vec[2] = fvecz; //z-координата на вектора, сочещ напред 
vec[3] = uvecx; //x-координата на вектора, сочещ нагоре 
vec[4] = uvecy; //y-координата на вектора, сочещ нагоре 
vec[5] = uvecz; //z-координата на вектора, сочещ нагоре 

//Определяне на текущата позиция на слушателя 
alListener3f(AL_POSITION, listenerx, listenery, listenerz); 

//Определяне на ориентацията на слушателя 
alListenerfv(AL_ORIENTATION, vec); 


При извикването на първата функция, 3 отделни стойности с плаваща запетая са подадени съответно за X-, Y- и Z-координати на слушателя. При второто извикване е подаден масив с име vec. Този масив се състои от 6 стойности за двата вектора, определящи ориентацията на слушателя.

Възпроизвеждане на звук

След като сте заредили звуците и сте определили свойствата на слушателя, можете да възпроизведете звуците. За тази цел трябва да извикате функцията alSourcePlay. Тази функция приема единствен параметър източника, чийто звук искате да възпроизведете. За да спрете звука, трябва да извикате функцията alSourceStop, която също приема името на източника, който искате да спрете. Ако искате вашия звуков ефект да се повтаря, както например ако имате звук на течаща вода, можете да настроите свойството за повтаряемост на звука на true преди да го възпроизведете. Ето и примерен код:

Код: Избери всички

 
//Нека звукът се възпроизвежда постоянно 
alSourcei(alSource,AL_LOOPING,AL_TRUE); 

//Възпроизвеждане на звука 
alSourcePlay(alSource); 


За да спрете звука:

Код: Избери всички

alSourceStop(alSource); 


Освобождаване на ресурсите

След като програмата ви е приключила, трябва да освободите всички източници и буфери и да спрете OpenAL. Функциите, които се ползват за тази цел са относително прости. Ето как да унищожите вашите източници и буфери:

Код: Избери всички

 
//Унищожаване на източника 
alDeleteSources(1,&alSource); 
//Унищожаване на буфера 
alDeleteBuffers(1,&alSampleSet); 


Първият параметър тук е броят на буферите или източниците, които трябва да бъдат унищожени, а вторият е идентификаторът на буфера или източника, използван при създаването им. Последната стъпка е ликвидирането на самата OpenAL. Това се прави по следния начин:

Код: Избери всички

 
//Намиране на активния контекст 
Context=alcGetCurrentContext(); 
//Намиране на устройството на активния контекст 
Device=alcGetContextsDevice(Context); 
//Изключване на контекста 
alcMakeContextCurrent(NULL); 
//Освобождаване на контекста 
alcDestroyContext(Context); 
//Затваряне на устройството 
alcCloseDevice(Device); 


Това е най-важното за възпроизвеждането на звук в OpenAL. Основните тъпки са първо да инициализирате OpenAL, после да заредите звуците, които са ви необходими, да настроите свойствата на източниците и на слушателя и да възпроизведете звуците. Има още много неща, които можете да направите с OpenAL но тази статия беше написана просто за да поясни някои от основните. Изходният код, който можете да намерите малко по-нататък, демонстрира използването на всичко това в OpenGL демо. В демото контролирате слушателя и позицията му се асоциира с вашата текуща позиция в игралния свят при всеки кадър. Ако имате някакви въпроси или коментари, пишете на ricart3@tcnj.edu

Свалете примерното приложение

Отговори