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
20 Iconv 사용법 소스 digipine 2017.11.01 335
19 WPA_SUPPLICANT 빌드 방법 digipine 2017.11.01 113
18 WPA_SUPPLICANT 빌드 방법 digipine 2017.11.01 75
» OpenAL 사용법 정리 1 digipine 2017.11.01 1885
16 QCAD 1.1 한국 최초의 2D CAD 소프트웨어 file digipine 2017.11.01 227
15 Ubuntu Server OS 한국어 모드로 설치 후 서버 콘솔에서 한글 깨짐 해결 방법 digipine 2017.10.31 136
14 Linux(리눅스) 파일 시스템 정리 (ext, ext2, ext3, ext4) digipine 2017.10.29 353
13 FFT (Fast Fourier Transform) 고속 푸리에 변환 예제 소스 digipine 2017.10.29 2449
12 WinPCap과 Ethereal, Wireshark 을 이용한 스니핑(Sniffing) digipine 2017.10.29 147
11 Windows에서 SVN 용 폴더 한 번에 삭제하기 digipine 2017.10.29 145
10 NMEA-0183을 이용한 GPS 애플리케이션 제작 digipine 2017.10.28 117
9 WIN CE, GPS - NMEA protocol - GPS Virtual Driver digipine 2017.10.28 390
8 WIN CE C++ 시리얼 제어 방법 digipine 2017.10.28 82
7 Windows API - 안전한 문자열 함수들 digipine 2017.10.28 87
6 Thread간 동기화관리자 digipine 2017.10.28 134
5 CMM / CMMI 란 무엇인가? digipine 2017.10.28 493
4 ALM의 등장 배경, 오해와 진실 digipine 2017.10.28 71
3 프로세스 능력 성숙도 모델(CMMI)의 적용 digipine 2017.10.28 208
2 UML - 기본편 ( 기본 표기 형식 및 관계 표현법 ) digipine 2017.10.28 118
1 공짜 무료 C/C++ 컴파일러들 file digipine 2017.10.28 2500
Board Pagination Prev 1 2 3 4 Next
/ 4