2013年4月7日日曜日

自作OpenALライブラリー!

自作OpenALライブラリを作りました。

OpenALライブラリの構造
1. AL_Attacthment デバイスとコンテキスト生成。
2. AL_Sound スタティックサウンド再生。
3. AL_Stream ストリームサウンド再生。

そして、ロード部
LOAD_WAVEクラス

機能動作はこのような流れで行きます。

Load_Waveクラスはバッファ生成やデータの読み込みを手伝ってくれます、
Load_Wave::fmt_headerと Load_Wave::SOUND_DATAを使いデータバッファを確保し、サウンドデータ形式や実データを読みこみます。

このデータを
AL_Sound型やAL_Stream型に流し込むことによって再生されます。

AL_Streamはまだラッピングが足りなくてむき出しのところや荒いところがただありますが、このように構成されています。

ヘッダー

#pragma once
#include "LOAD_WAV.h"
#include "AL_Attacthment.h"

class AL_Stream
{
private:
 unsigned int m_Buffer_size;
 unsigned int m_Buffer_cnt;

 ALuint* m_Buffers;
 ALuint m_Source;
 LOAD_WAV::WAVEFILE m_file;
 LOAD_WAV::fmt_header m_format_data;
 LOAD_WAV::SOUND_DATA m_Sound_data;
 
protected:
 static void Set_SoundBuffer(ALuint buffer, LOAD_WAV::SOUND_DATA data, unsigned int data_size, const LOAD_WAV::fmt_header* format_data);

public:
 AL_Stream(void) : m_Buffer_cnt(0), m_Buffer_size(0), m_Buffers(0), m_Source(0), m_file(0){}
 ~AL_Stream(void){};

 void Create_SoundBuffer(unsigned int cnt, unsigned int size);
 void Release(void);
 void Rewind_file(void);

 void Play(void);
 void Set_Wave_file(LOAD_WAV::WAVEFILE file, const LOAD_WAV::fmt_header* fmt);
};




実装部
#include "AL_Stream.h"


void AL_Stream::Set_SoundBuffer(ALuint buffer, LOAD_WAV::SOUND_DATA data, unsigned int data_size, const LOAD_WAV::fmt_header* format_data)
{
 ALenum sound_format = NULL;

 if(format_data->m_Channels == 1){
  sound_format = AL_FORMAT_MONO8 + format_data->m_BitsPersample / 16;
 }else if(format_data->m_Channels == 2){
  sound_format = AL_FORMAT_STEREO8 + format_data->m_BitsPersample / 16;
 }

 alBufferData(buffer, sound_format, data, data_size, format_data->m_SamplerPersec);
}

void AL_Stream::Create_SoundBuffer(unsigned int cnt, unsigned int size)
{
 m_Buffer_cnt = cnt;
 m_Buffer_size = size;

 m_Buffers = (ALuint*)malloc(sizeof(ALuint)*m_Buffer_cnt);
 m_Sound_data = LOAD_WAV::Create_SoundBuffer(m_Buffer_size);

 alGenBuffers(m_Buffer_cnt, m_Buffers);
 alGenSources(1, &m_Source);

 
}

void AL_Stream::Release(void)
{
 alSourceStop(m_Source);
 LOAD_WAV::Release_SoundBuffer(m_Sound_data);
 alDeleteSources(1, &m_Source);
 alDeleteBuffers(m_Buffer_cnt, m_Buffers);
 
 if(m_Buffers != NULL){
  free(m_Buffers);
  m_Buffers = NULL;
 }
}

void AL_Stream::Rewind_file(void)
{
 fseek(m_file, m_format_data.m_Data_Position, SEEK_SET);
}


void AL_Stream::Play(void)
{
 ALint buffer_processed = 0;
 ALint source_stats = 0;
 alGetSourcei(m_Source, AL_BUFFERS_PROCESSED, &buffer_processed);
 alGetSourcei(m_Source, AL_SOURCE_STATE, &source_stats);

 if(source_stats == AL_STOPPED || source_stats == AL_INITIAL){
  alSourcePlay(m_Source);
 }

 while (buffer_processed > 0){
  ALuint unqued_buffer = NULL;
  alSourceUnqueueBuffers(m_Source, 1, &unqued_buffer);
  LOAD_WAV::Get_SoundBuffer(m_file, m_Sound_data, m_Buffer_size);
  AL_Stream::Set_SoundBuffer(unqued_buffer, m_Sound_data, m_Buffer_size, &m_format_data);
  alSourceQueueBuffers(m_Source, 1, &unqued_buffer);
  buffer_processed--;
 }
}

void AL_Stream::Set_Wave_file(LOAD_WAV::WAVEFILE file, const LOAD_WAV::fmt_header* fmt)
{
 m_file = file;
 memcpy(&m_format_data, fmt, sizeof(LOAD_WAV::fmt_header));

 for(unsigned int i = 0; i < m_Buffer_cnt; i ++){
  LOAD_WAV::Get_SoundBuffer(m_file, m_Sound_data, m_Buffer_size);
  AL_Stream::Set_SoundBuffer(m_Buffers[i], m_Sound_data, m_Buffer_size, &m_format_data);
 }

 alSourceQueueBuffers(m_Source, m_Buffer_cnt, m_Buffers);
}


ストリーム再生で意外とてこずる方が多かったので、そのような方たちに参考になれるよう全ソース公開しますw
これが参考になればいいですけどww

かなり荒いソースだし、コピペーだけじゃ使えないですけど、読む方によっては参考になれると思います。


0 件のコメント:

コメントを投稿