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

0
100

Programming 3D Sound With OpenAL

С увеличаването на възможностите на звуковите карти и на звуковите API (Application Program 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 има настроен обект за слушател, така че всичко което трябва да направите е да модифицирате свойствата му както са ви необходими. Най-важните свойства на слушателя са позицията и ориентацията му в пространстовоr. Тези свойства обикновено се обновяват при всеки кадър от играта. Позицията определя къде се намира в момента слушателя, докато ориентацията определя на къде той е обърнат. например ако слушателя е обърнат на запад и звука идва от север, звука ще изглежда че звука идва от дясно. Обаче ако ориентацията на играча се промени и той се обърне на север, звука вече ще изглежда да идва право отпред.

Модифицирането на свойствата на слушателя е подобно на промяната на свойствата на източника. Използва се функцията 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 но тази статиа беше написана просто за да поясни някои от основните. Програмния (source) код, който можете да намерите малко по-нататък, демонстрира използването на всичко това в OpenGL демо. В демото контролирате слушателя и позицията му се асоциира с вашата текуща позиция в игралния свят при всеки кадър. Ако имате някакви въпроси или коментари, пишете на ricart3@tcnj.edu

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

Автор: Dan Ricart
Превод: DarkLight
Материала е взет от DevMaster и е публикуван с разрешрението на автора
E-mail на автора: Athletics2@comcast.net

ДОБАВИ КОМЕНТАР

Коментирай това преди всички други

Извести ме за
avatar