-
[openAL] #3. Guide 읽기 - 1개발일지 2021. 10. 7. 16:59728x90
동영상 튜토리얼을 마친 후, 어느 정도 소스가 이해되어
이제 직접 공식 홈페이지에 있는 Guide를 읽어보려고 한다.
https://www.openal.org/documentation/OpenAL_Programmers_Guide.pdf
Introduction to OpenAL
세 가지 기본 object 가 있음. Buffer, Source, Listener.
Buffer - 오디오 데이터를 담고 소스에 붙음.
Source - 위치를 형성하고 실제 소리를 재생. 사운드가 어떻게 들리냐는 이 source의 position과 orientation (둘의 차이를 아직은 모르겠음)이 Listener에 대해 상대적으로 어디있느냐에 따라 다르게 들림.
Listener - 소리를 받는 object.

시작시 하나 이상의 Device가 열려야 하고, 그 안에는 적어도 하나의 context가 생성.
context 하나에는 listener가 하나 내재돼있고, 여러개의 source가 생성될 수 있음.
source는 각각 하나 이상의 buffer를 붙일 수 있음.
buffer는 특정한 context에 포함되어 있지 않고 한 device 내에서 모든 context가 공유함.
Device를 열기 위해선
ALCdevice *alcOpenDevice(const ALCchar* devicename);호출.
특정한 device를 열기 위해서는 인자로 devicename이 string 형태로 들어가야하며,
default 로 열기 위해서는 NULL을 넣으면 된다.
device가 열리면 context가 하나 존재하여 준비 완료.
버퍼
버퍼를 사용하기 위해서는
Alenum alGetError(ALvoid);로 에러를 초기화하고,
void alGenBuffers(ALsizei n, Aluint *buffers);로 n개의 버퍼생성을 한다.
마지막으로 다시 alGetError()를 호출해 에러가 있는지 확인한다.
pcm 데이터로 buffer를 채우기 위해서는
void alBufferData(Aluint buffer, Alenum format, const Alvoid *data, ALsizei size, ALsizei freq);를 호출.
소스
소스를 사용하기 위해서는 역시 마찬가지로 alGetError()로 에러를 초기화 시키고,
void alGenSources(Alsizei n, ALuint *sources);로 n개의 소스를 생성한다.
역시나 alGetError()로 에러를 확인한다.
소스에 버퍼를 붙이려면 alSourcei(ALuint source, Alenum param, ALint value)로 붙여주자.
버퍼를 붙이고나면, 소스는 버퍼를
void alSourcePlay(ALuint source);로 실행할 수 있다.
소스와 리스너의 정보들은
void alGetListenerfv(ALenum param, Alfloat *values);void alListener3f(Alenum param, ALfloat v1, ALfloat v2, ALfloat v3);void alSourcei(ALuint source, Alenum param, ALint value);void alGetSource3f(Aluint source, ALenum param, ALfloat *v1, ALfloat *v2, ALfloat *v3);위 함수들을 이용해 바로바로 수정해줄 수 있다.
예제소스
// 초기화 Device = alcOpenDevice(NULL); // 원하는 device 선택 if (Device) { Context = alcCreateContext(Device, NULL); // Device에 Context 생성 alcMakeContextCurrent(Context); // 작업할 Context 선택 } // EAX 2.0 지원 체크 (잘 모르는 내용. 아마 Device가 저걸 지원하는지 체크하는듯. 추후에 확인.) g_bEAX = alIsExtensionPresent("EAX2.0"); // 버퍼 생성 alGetError(); // 에러 초기화 alGenBuffers(NUM_BUFFERS, g_Buffers); // NUM_BUFFERS 만큼 g_Buffers에 버퍼 할당. if ((error = alGetError()) != AL_NO_ERROR) { // 에러 확인시 에러가 있다면 DisplayALError("alGenBuffers :", error); // 에러 표시. return; // 종료 } // Load test.wav loadWAVFile("test.wav", &format, &data, &size, &freq, &loop); // openAL에는 없는 기능. sndfile을 이용해 대체. wav 파일의 format, data, size, format, loop를 기록. if ((error = alGetError() != AL_NO_ERROR) { // 에러 확인시 에러가 있다면 DisplayALError("alutLoadWAVFile test.wav : ", error); // 에러 표시. alDeleteBuffers(NUM_BUFFERS, g_Buffers); // NUM_BUFFERS 만큼의 버퍼 삭제. return; // 종료 } // test.wav 파일 Buffer 0에 복사 alBufferData(g_Buffers[0], format, data, size, freq); // Buffer 0에 wav 파일 데이터 저장 if ((error = alGetError() != AL_NO_ERROR) { // 에러 확인시 에러가 있다면 DisplayALError("alBufferData buffer 0 : ", error); // 에러 표시. alDeleteBuffers(NUM_BUFFERS, g_Buffers); // NUM_BUFFERS 만큼의 버퍼 삭제. return; // 종료 } // Unload test.wav unloadWAV(format, data, size, freq); // 불러왔던 wav 파일 제거. 역시나 sndfile 이용. if ((error = alGetError() != AL_NO_ERROR) { // 에러 확인시 에러가 있다면 DisplayALError("alutUnloadWAV : ", error); // 에러 표시. alDeleteBuffers(NUM_BUFFERS, g_Buffers); // NUM_BUFFERS 만큼의 버퍼 삭제. return; // 종료 } // 소스 생성 alGenSources(1, source); // source에 1개의 소스 생성. if ((error = alGetError() != AL_NO_ERROR) { // 에러 확인시 에러가 있다면 DisplayALError("alGenSources 1 : ", error); // 에러 표시. return; // 종료 } // buffer 0 소스에 연결 alSourcei(source[0], AL_BUFFER, g_Buffers[0]); // 소스 0에 버퍼 0 연결 if ((error = alGetError()) != AL_NO_ERROR) { // 에러 확인시 에러가 있다면 DisplayALError("alSourcei AL_BUFFER 0 : ", error); // 에러 표시. } // 종료 Context = alcGetCurrentContext(); // 작업 선택 Device = alcGetContextsDevice(Context); // 작업 device 선택 alcMakeContextCurrent(NULL); // 작업 context 해제 alcDestroyContext(Context); // context 삭제 alcCloseDevice(Device); // 작업 device 해제'개발일지' 카테고리의 다른 글
[openAL] #5. Guide 읽기 - 3 [소스 스트리밍 및 도플러 효과] (0) 2021.10.08 [openAL] #4. Guide 읽기 - 2 (0) 2021.10.07 [openAL] #2. 음악 재생하기 (0) 2021.10.06 [openAL] #1. 설치하기 (0) 2021.10.04 [개발일지] Transformer로 긴 문서 학습시키기 (0) 2021.07.14