Arama Motoru

OpenAL Ders 3: Çoklu Ses

OpenAL Ders 3: Çoklu Source’ler

Jesse Maurais

14/06/2003

mumin16

25/04/2010

 


Selam. Son dersimden bu yana bayağı oldu. Ama hiç olmamaktansa varsın geç olsun diye düşünüyorum. Son dersimi okumaya sabırsızlandığınıza eminim, hemen bakalım.  Bir ses dosyasını birden fazla kereler çalmayı başardık sanıyorum. Ciddi oyunlar aynı anda farklı ses kliplerini birlikte çalmakta. Uygulaması zor değil. Çoklu ses sadece bir tane için yapılanla aynıdır. 

#include <conio.h>
#include <time.h>
#include <stdlib.h>
#include <al/al.h>
#include <al/alc.h>
#include <al/alu.h>
#include <al/alut.c>
 
// ihtiyacımız olacak toplam data bufferları.
#define NUM_BUFFERS 3
 
// ihtiyacımız olacak toplam yayınlananlar.
#define NUM_SOURCES 3
 
// Bunlar bufferlar ve sourceler indeksi.
#define BATTLE      0
#define GUN1        1
#define GUN2        2
 
// Bufferlar ses datasını tutar.
ALuint Buffers[NUM_BUFFERS];
 
// Sourceler sesin yayılma noktalarıdır.
ALuint Sources[NUM_SOURCES];
 
// source’nin pozisyonu.
ALfloat SourcesPos[NUM_SOURCES][3];
 
// source’nin hızı.
ALfloat SourcesVel[NUM_SOURCES][3];
 
 
// listener’nın pozisyonu.
ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 };
 
// listener’nın hızı.
ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 };
 
// listener’ın yönü. (ilk 3 eleman "-de,-da", ikinci 3lü "üs")
ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };

 

Sanıyorum, kaynak kodlarının bu bölümü ilk iki dersi okuyan çoğunuza aşina gelmiştir. Tek farklılık şimdi OpenAL ses sistemine yükleyeceğimiz 3 tane farklı ses efektine sahip olmamızdır.

 

 

ALboolean LoadALData()
{
    // alutLoadWavFile çağrı sonrası otomatik dolacak değişkenler.
 
    ALenum format;
    ALsizei size;
    ALvoid* data;
    ALsizei freq;
    ALboolean loop;
 
    // bufferlara wav datasını yükle.
 
    alGenBuffers(NUM_BUFFERS, Buffers);
 
    if (alGetError() != AL_NO_ERROR)
        return AL_FALSE;
 
    alutLoadWAVFile("wavdata/Battle.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[BATTLE], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);
 
    alutLoadWAVFile("wavdata/Gun1.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[GUN1], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);
 
    alutLoadWAVFile("wavdata/Gun2.wav", &format, &data, &size, &freq, &loop);
    alBufferData(Buffers[GUN2], format, data, size, freq);
    alutUnloadWAV(format, data, size, freq);
 
    // Source ile buffer’ı bağla.
 
    alGenSources(NUM_SOURCES, Sources);
 
    if (alGetError() != AL_NO_ERROR)
        return AL_FALSE;
 
    alSourcei (Sources[BATTLE], AL_BUFFER,   Buffers[BATTLE]  );
    alSourcef (Sources[BATTLE], AL_PITCH,    1.0              );
    alSourcef (Sources[BATTLE], AL_GAIN,     1.0              );
    alSourcefv(Sources[BATTLE], AL_POSITION, SourcePos[BATTLE]);
    alSourcefv(Sources[BATTLE], AL_VELOCITY, SourceVel[BATTLE]);
    alSourcei (Sources[BATTLE], AL_LOOPING,  AL_TRUE          );
 
    alSourcei (Sources[GUN1], AL_BUFFER,   Buffers[GUN1]  );
    alSourcef (Sources[GUN1], AL_PITCH,    1.0            );
    alSourcef (Sources[GUN1], AL_GAIN,     1.0            );
    alSourcefv(Sources[GUN1], AL_POSITION, SourcePos[GUN1]);
    alSourcefv(Sources[GUN1], AL_VELOCITY, SourceVel[GUN1]);
    alSourcei (Sources[GUN1], AL_LOOPING,  AL_FALSE       );
 
    alSourcei (Sources[GUN2], AL_BUFFER,   Buffers[GUN2]  );
    alSourcef (Sources[GUN2], AL_PITCH,    1.0            );
    alSourcef (Sources[GUN2], AL_GAIN,     1.0            );
    alSourcefv(Sources[GUN2], AL_POSITION, SourcePos[GUN2]);
    alSourcefv(Sources[GUN2], AL_VELOCITY, SourceVel[GUN2]);
    alSourcei (Sources[GUN2], AL_LOOPING,  AL_FALSE       );
 
    // Hata kontrolü yap ve dön.
 
    if( alGetError() != AL_NO_ERROR)
        return AL_FALSE;
 
    return AL_TRUE;
}

 

Üsteki kodlar başta epey farklı görünebilir, ama gerçekte değil. Sadece, 3 bufferımıza dosya verilerini yükleyip sonra ilgili 3 source ile 3 buffer’ı bağlarız. Diğer tek farklılık diğerlerinden farklı olarak "Battle.wav" (Source indeksinde 0) döngületilmesidir .

 

void SetListenerValues()
{
    alListenerfv(AL_POSITION,    ListenerPos);
    alListenerfv(AL_VELOCITY,    ListenerVel);
    alListenerfv(AL_ORIENTATION, ListenerOri);
}
 
void KillALData()
{
    alDeleteBuffers(NUM_BUFFERS, &Buffers[0]);
    alDeleteSources(NUM_SOURCES, &Sources[0]);
    alutExit();
}

 

Üsteki kodlarda herhangi bir şey değiştireceğimizi sanmıyorum.

 

int main(int argc, char *argv[])
{
    // OpenAL’ı ilkle ve hata bitini resetle.
    alutInit(NULL, 0);
    alGetError();
 
    // wav datasını yükle.
    if (LoadALData() == AL_FALSE)
        return 0;
 
    SetListenerValues();
 
    // bir çıkış prosedürü kur.
    atexit(KillALData);
 
    // battle.wav dosyasını çalmayı başla.
    alSourcePlay(Sources[BATTLE]);
 
    // tüm sourcelere göz atıp çalındıklarını kontrol et.
    // ilk source atlanır çünkü o zaten döngülenir (daima çalınacak).
    ALint play;
 
    while (!kbhit())
    {
        for (int i = 1; i < NUM_SOURCES; i++)
        {
                alGetSourcei(Sources[i], AL_SOURCE_STATE, &play);
 
                if (play != AL_PLAYING)
                {
                    // source’i çaldırmak için listener etrafında rast gele pozisyonlandır.
 
                double theta = (double) (rand() % 360) * 3.14 / 180.0;
 
                SourcePos[i][0] = -float(cos(theta));
                SourcePos[i][1] = -float(rand()%2);
                SourcePos[i][2] = -float(sin(theta));
 
                alSourcefv(Sources[i], AL_POSITION, SourcePos[i] );
 
                alSourcePlay(Sourcev[i]);
            }
        }
    }
 
    return 0;
}

 

Bu dersin ilginç kısmı bu üsttekilerdir. Çalındıklarından emin olmak için her bir source’ü gözden geçiririz. Çalınmıyor ise çaldırırız ama tabi çalınmaları için 3d uzayda onlara yeni bir nokta seçeriz (tamamen fantezi için).

 

Ve Beng! Bitirdik. Büyük olasılıkla çoğunuzun anladığı üzere, bir source’den fazlasını çaldırmada çok özel şeyler yapmayız. OpenAL, mesafe ve hızları göre düzgün sesler elde etmek için tüm mixleme özelliklerini kendi yönetecek. Buna hükmetmesi OpenAL’ın güzelliği değil mi?

 

Düşündüğümden daha kolay oldu. Bu dersi yazmak için neden uzun süre beklediğimi bilmiyorum. Her ne ise, okuyucu, gelecek dersler için özel isteklerini (OpenAL’a özgül olması şart değil, oldukça geniş bilgi tabanına sahibim) lightonthewater@hotmail.com ‘a mesaj atabilir. İstek gelmezse bufferların paylaşımı ve daha sonrasında Doppler etkisini ders olarak planlıyorum. Kodla iyi eğlenceler!

 


*Bu dersin Java versiyonu için Java Bindings for OpenAL sayfasına bakın (Athomas Goldberg tarafından adapte edilmiştir)

Dersin Orjinali : http://www.devmaster.net/articles/openal-tutorials/lesson3.php