logo

English

이곳의 프로그래밍관련 정보와 소스는 마음대로 활용하셔도 좋습니다. 다만 쓰시기 전에 통보 정도는 해주시는 것이 예의 일것 같습니다. 질문이나 오류 수정은 siseong@gmail.com 으로 주세요. 감사합니다.

OpenAL 사용법 정리

by digipine posted Nov 01, 2017
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print

OpenAL이란?

○ 게임이나 또 다른 오디오 어플리케이션을 위해 고안된 3D Audio API로 플랫폼 독립적인 라이브러리다.

○ 사용법이 그리 어렵지 않기 때문에 누구나 조금만 보면 금방 사용할 수 있다.

○ 공식 사이트 : http://connect.creativelabs.com/openal/default.aspx

 

 

 

 OpenAL 사용을 위한 사전 작업

○ OpenAL을 사용하기 위해서는 먼저 사이트로부터 oalinst.exe 를 다운받아 설치해줘야 한다.

○ oalinst.exe  다운로드 :

http://connect.creativelabs.com/openal/Downloads/Forms/AllItems.aspx

 

 

 

 

 공통된 작업

 

 생성 : OpenAL을 사용하기 위한 초기화 작업이다. 부가적인 코드는 모두 생략했다.

 

bool OpenAlInterface::Create()

{

    ALFWInit();

    if( AL_FALSE == ALFWInitOpenAL() )

    {

           ALFWShutdown();

           return false;

    }

 

    return true;

}

 

 해제 : OpenAL을 해제한다. 어플리케이션이 끝나기 전에 반드시 해줘야 한다.

 

void OpenAlInterface::Destroy()

{

    UnloadWave();  // 로드된 Wave데이터가 있다면 해제 시켜주는 함수다.

 

    ALFWShutdownOpenAL();

    ALFWShutdown();

}

 

// 로드된 Wave데이터가 있다면 해제 시켜주는 함수다.

void OpenAlInterface::UnloadWave()

{

    // Stream Data 해제

    if( m_pStreamData )

    {

           delete m_pStreamData;

           m_pStreamData = 0;

    }

 

    // Stream Play에 사용된 Wave Loader 해제

    if( m_pWaveLoader )

    {

           m_pWaveLoader->DeleteWaveFile(m_waveID);

           delete m_pWaveLoader;

           m_pWaveLoader = 0;

    }

 

    // OpenAL은 각 사운드를 ID로 관리한다.

// 하나의 Sound Data가 생성되면 그 Sound Data를 대표하는 하나의 ID가 보여되고,

// 그 ID를 통해 접근 할 수 있다.

// 현재 로드된 Sound Data가 있다면 해제한다.

    if( m_uiSourceID )

    {

           alDeleteSources(m_uiSourceSize, &m_uiSourceID);

           m_uiSourceID = 0;

           m_uiSourceSize = 1;

    }

 

    // Sound Data가 채워질 버퍼를 대표하는 ID들의 리스트를 해제한다.

    if( m_pBuffersID )

    {

           alDeleteBuffers(m_uiBufferSize, m_pBuffersID);

           delete[] m_pBuffersID;

           m_pBuffersID = 0;

           m_uiBufferSize = 1;

    }

}

 

 

 

 Static Play를 위한 작업 : Static Play에 필요한 기본적인 함수들이다.

 

// Wave 파일을 로드한다.

bool OpenAlInterface::LoadWaveStatic(std::string strFilename)

{

    m_pBuffersID = new unsigned int[m_uiBufferSize];

 

    alGenBuffers(m_uiBufferSize, m_pBuffersID);

    alGenSources(m_uiSourceSize, &m_uiSourceID);

 

    if( AL_FALSE == ALFWLoadWaveToBuffer(strFilename.c_str(), m_pBuffersID[0]) )

           return false;

 

    // Source ID의 Sound Data가 채워질 BufferID를 설정한다.

    alSourcei(m_uiSourceID, AL_BUFFER, m_pBuffersID[0]);

 

    return true;

}

 

bool OpenAlInterface::UpdateStatic()

{

    if( m_iState != AL_PLAYING )

           return false;

 

    Sleep(100);

 

    // 현재 Source의 상태를 플레이 중인지 아닌지를 얻는다.

    alGetSourcei( m_uiSourceID, AL_SOURCE_STATE, &m_iState);

 

    return true;

}

 

// 플레이 시키는 함수

void OpenAlInterface::PlayStatic()

{

    // Play Source

    alSourcePlay( m_uiSourceID );

    m_iState = AL_PLAYING;

}

 

// 스톱 시키는 함수

void OpenAlInterface::StopStatic()

{

    alSourceStop(m_uiSourceID);

    m_iState = AL_INITIAL;

}

 

 

 

 Stream Play를 위한 작업 : 다음은 Stream Play를 위한 함수들이다. 아무래도 기본적인 Static Play보다는 좀더 복잡하다.

 

bool OpenAlInterface::LoadWaveStream(std::string strFilename, unsigned int uiBufferSize)

{

    // static에서는 BufferID가 하나만 잇으면 되엇지만

    // Stream Play시는 적어도 4개 정도의 Buffer가 필요하다.

    m_uiBufferSize = uiBufferSize;

    m_pBuffersID = new unsigned int[m_uiBufferSize];

   

    alGenBuffers(m_uiBufferSize, m_pBuffersID);

    alGenSources(m_uiSourceSize, &m_uiSourceID);

 

    m_pWaveLoader = new CWaves();

   

    // WaveLoader를 통해 WaveFile을 오픈한다.

    // WaveLoader는 직접 만들어도 되고 OpenAL 샘플에서 제공하는 것을 가져다 써도 된다.

    if( WR_OK != m_pWaveLoader->OpenWaveFile(strFilename.c_str(), &m_waveID) )

           return false;

 

    // WaveLoader의 임무 중 하나는 이렇게 Wave의 정보를 얻는대 있다.

    m_pWaveLoader->GetWaveSize(m_waveID, &m_ulStreamDataSize);

    m_pWaveLoader->GetWaveFrequency(m_waveID, &m_ulStreamFrequency);

    m_pWaveLoader->GetWaveALBufferFormat(m_waveID, &alGetEnumValue, &m_ulStreamFormat);

    m_pWaveLoader->GetWaveFormatExHeader(m_waveID, &m_waveFormatEx);

 

    m_uiStreamBufferSize = m_waveFormatEx.nAvgBytesPerSec >> 2;

    m_uiStreamBufferSize -= (m_uiStreamBufferSize % m_waveFormatEx.nBlockAlign);

 

    if( 0 == m_ulStreamFormat )

           return false;

 

    m_pStreamData = malloc(m_uiStreamBufferSize);

    if( 0 == m_pStreamData )

           return false;

 

    // Audio Data의첫번째부터읽도록세팅

    m_pWaveLoader->SetWaveDataOffset(m_waveID, 0);

 

    // Buffer를audio data로채운다.

    unsigned long ulBytesWritten;

    for(int index=0 ; index<m_uiBufferSize ; ++index)

    {

           if( WR_OK == m_pWaveLoader->ReadWaveData(m_waveID, m_pStreamData, m_uiStreamBufferSize, &ulBytesWritten) )

           {

                   alBufferData(m_pBuffersID[index], m_ulStreamFormat, m_pStreamData, ulBytesWritten, m_ulStreamFrequency);

                   alSourceQueueBuffers(m_uiSourceID, 1, &m_pBuffersID[index]);

           }

    }

 

    m_bStreamPlay = false;

 

    return true;

}

 

// 다음은 매 틱마다 플레이시켜주기 위한 함수다.

bool OpenAlInterface::UpdateStream()

{

    if( false == m_bStreamPlay )

           return false;

 

    if( m_iState != AL_PLAYING )

           return false;

 

    Sleep(20);

 

    int iBuffersProcessed = 0;

    alGetSourcei(m_uiSourceID, AL_BUFFERS_PROCESSED, &iBuffersProcessed);

 

    unsigned long ulBytesWritten;

    while( iBuffersProcessed )

    {

           unsigned int uiBuffer = 0;

           alSourceUnqueueBuffers(m_uiSourceID, 1, &uiBuffer);

 

           m_pWaveLoader->ReadWaveData(m_waveID, m_pStreamData, m_uiStreamBufferSize, &ulBytesWritten);

           if( ulBytesWritten )

           {

                   alBufferData(uiBuffer, m_ulStreamFormat, m_pStreamData, ulBytesWritten, m_ulStreamFrequency);

                   alSourceQueueBuffers(m_uiSourceID, 1, &uiBuffer);

           }

 

           iBuffersProcessed--;

    }

 

    alGetSourcei(m_uiSourceID, AL_SOURCE_STATE, &m_iState);

    if( m_iState != AL_PLAYING )

    {

           int iQueuedBuffers;

           alGetSourcei(m_uiSourceID, AL_BUFFERS_QUEUED, &iQueuedBuffers);

           if( iQueuedBuffers )

           {

                   alSourcePlay(m_uiSourceID);

                   m_iState = AL_PLAYING;

           }

           else

           {

                   StopStream();

           }

    }

 

    return true;

}

 

// 플레이 시켜주는 함수.

void OpenAlInterface::PlayStream()

{

    alSourcePlay(m_uiSourceID);

 

    m_bStreamPlay = true;

    m_iState = AL_PLAYING;

}

 

// 스톱 시켜주는 함수

void OpenAlInterface::StopStream()

{

    alSourceStop(m_uiSourceID);

    alSourcei(m_uiSourceID, AL_BUFFER, 0);

 

    m_bStreamPlay = false;

    m_iState = AL_INITIAL;

}

TAG •

List of Articles
No. Subject Author Date Views
24 [Qt] QSettings 클래스의 설명과 사용법, 설정 저장위치 digipine 2017.11.02 1470
23 [Swift, MacOS] 맥 한글 파일명이 윈도우에서 자소 분리되는 현상 해결, NFD, NFC 엉뚱도마뱀 2018.12.11 20080
22 [ubuntu, 우분투] sendmail 설치 digipine 2017.11.02 2317
21 공짜 무료 C/C++ 컴파일러들 file digipine 2017.10.28 4378
20 난수발생기 개론 엉뚱도마뱀 2017.11.22 4314
19 대칭키 암호화관련 개념 정리 digipine 2017.11.09 1641
18 리눅스 /dev/random을 이용한 랜덤값 생성 엉뚱도마뱀 2017.11.22 1556
17 리눅스 커널의 Swap Memory에 대해서 digipine 2017.11.02 675
16 비밀번호 해쉬에 Salt(소금) 첨가하기 file 엉뚱도마뱀 2017.11.23 4273
15 소프트웨어 테스팅 전문가들을 위한 사이트 digipine 2017.11.02 610
14 수학적 구조물 모델링 만들기 소개 비디오 엉뚱도마뱀 2018.09.24 1051
13 악성코드 종류 구분 digipine 2017.11.13 962
12 언어 IDE 별로 git ignore 파일을 자동으로 만들어 주는 사이트 엉뚱도마뱀 2018.12.17 122604
11 우분투 18.04 MongoDB 설치 및 구성 lizard2019 2021.02.26 503
10 우분투 Nabi 한글 입력기 Tray(트레이) 상단 메뉴바로 옮기기 digipine 2017.11.03 1630
9 윈도우 한영 전환 쉬프트 스페이스로 변경 digipine 2017.11.03 413
8 윈도우즈 도스 커멘드(Command) 네트워크 관련 명령어 lizard2019 2019.02.07 1342
7 유닉스/리눅스 명령어 레퍼런스 digipine 2017.11.03 745
6 이벤트 텍소노미(Event Taxonomy)란 무엇인가요? digipine 2023.08.11 259
5 임베디드SW 개발자센터 이용안내(성남시 분당구, 개발공간 무료제공) digipine 2017.11.02 590
Board Pagination Prev 1 2 3 4 5 6 Next
/ 6