- 追加された行はこの色です。
- 削除された行はこの色です。
*第19回目 OpenALでストリーム再生 [#q39c64b5]
OpenALでwavファイルのストリーム再生をしてみた。
前回作成したリングバッファクラスやストリームクラスを使用していません。
今回はOpenALで作ったサンプルプログラムです。
手抜き実装のためwavファイルのフォーマットが8ビットの場合は再生できません。
**動作環境 [#e8ce4f71]
Windows版はWindowsXP SP2でMacOSXは10.5.5で動作確認した。
ソースファイルについては以下の通り。
Windows版はVisualStudio.NET2003用のWin32コンソールプロジェクト。
MacOSX版はXcode3.0のCommandLineUtilityのC++Toolプロジェクト。
**サンプルプログラム (Windows版) [#ldd8f0da]
#include "stdafx.h"
#include <windows.h>
#include "standard.h"
#include "OpenAL/include/al.h"
#include "OpenAL/include/alc.h"
#pragma comment(lib, "OpenAL/libs/Win32/OpenAL32.lib")
static const ALint BUFFER_MAX = 4;
static const size_t DATA_SAMPLE_MAX = 44100 * 2;
#pragma pack(push, 1)
struct RiffHeader
{
uint32_t riff;
uint32_t size;
uint32_t type;
};
struct Chank
{
uint32_t id;
uint32_t size;
};
struct Fmt
{
uint16_t format_id;
uint16_t channel;
uint32_t sampls_per_sec;
uint32_t average_bytes_per_sec;
uint16_t block_size;
uint16_t extension_size;
uint8_t extension[1];
};
#pragma pack(pop)
int _tmain(int argc, _TCHAR* argv[])
{
if(argc < 2)
{
exit(-1);
}
// waveファイル読み込み
FILE* file;
file = _tfopen(argv[1], _T("rb"));
if(file == NULL)
{
exit(-1);
}
// waveヘッダ解析
RiffHeader header;
fread(&header, 1, sizeof(RiffHeader), file);
if((header.riff != 'FFIR') || (header.type != 'EVAW'))
{
fclose(file);
exit(-1);
}
// waveチャンク解析
uint32_t channel = 0;
uint32_t sampls_per_sec = 0;
Chank chank;
Fmt* fmt = NULL;
for(;;)
{
if(fread(&chank, 1, sizeof(Chank), file) == 0)
{
fclose(file);
exit(-1);
}
if(chank.id == 'atad')
{
// dataチャンクなら終了
break;
}
else if(chank.id == ' tmf')
{
// fmtチャンクならfmtを読み込み
fmt = reinterpret_cast<Fmt*>(new char[chank.size]);
if(fread(fmt, 1, chank.size, file) == 0)
{
delete [] fmt;
fclose(file);
exit(-1);
}
channel = fmt->channel;
sampls_per_sec = fmt->sampls_per_sec;
delete [] fmt;
}
else
{
// その他のチャンクならスキップ
if(chank.size != 0)
{
if(fseek(file, chank.size, SEEK_CUR) != 0)
{
fclose(file);
exit(-1);
}
}
}
}
if(((channel < 1) && (channel > 2)) || (sampls_per_sec == 0))
{
fclose(file);
exit(-1);
}
// OpenAL初期化
ALCdevice* device_handle;
ALCcontext* context_handle;
ALuint source_handle;
ALint state;
device_handle = alcOpenDevice(NULL);
context_handle = alcCreateContext(device_handle, NULL);
alcMakeContextCurrent(context_handle);
alGenSources(1, &source_handle);
// waveをOpenALでストリーミング再生
for(;;)
{
ALint processed_count;
ALint buffer_count;
// 再生し終わったバッファがあれば削除する
alGetSourcei(source_handle, AL_BUFFERS_PROCESSED, &processed_count);
if(processed_count)
{
ALuint delete_buffer_handle[BUFFER_MAX];
alSourceUnqueueBuffers(source_handle, processed_count, delete_buffer_handle);
}
// ソースに登録可能ならバッファを作成して登録する
alGetSourcei(source_handle, AL_BUFFERS_QUEUED, &buffer_count);
if(buffer_count < BUFFER_MAX)
{
int16_t data[DATA_SAMPLE_MAX];
size_t readsize;
// wave読み込み
readsize = fread(data, 1, DATA_SAMPLE_MAX * 2, file);
if(readsize != 0)
{
ALuint buffer_handle;
// バッファ作成
alGenBuffers(1, &buffer_handle);
alBufferData(buffer_handle, (channel == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16), data, static_cast<ALsizei>(readsize), sampls_per_sec);
// ソースに登録
alSourceQueueBuffers(source_handle, 1, &buffer_handle);
alDeleteBuffers(1, &buffer_handle);
// 再生していない場合は再生する
alGetSourcei(source_handle, AL_SOURCE_STATE, &state);
if(state != AL_PLAYING)
{
alSourcePlay(source_handle);
}
}
else
{
// データの終わりに到達したので再生が終了したら演奏終了
alGetSourcei(source_handle, AL_SOURCE_STATE, &state);
if(state != AL_PLAYING)
{
break;
}
}
}
Sleep(100);
}
// 終了
fclose(file);
alDeleteSources(1, &source_handle);
alcMakeContextCurrent(NULL);
alcDestroyContext(context_handle);
alcCloseDevice(device_handle);
return 0;
}
**操作方法 [#o16de76c]
***windows [#sa60be8d]
wavファイルをopenalstream_sample.exeにドラッグアンドドロップしてください。
***MacOSX [#ea91e7be]
アプリケーション→ユーティリティに入っているターミナルを開く。
openalstreamの実行ファイルをドラッグアンドドロップでターミナルにドロップする。
次に再生したいwavファイルをターミナルにドロップする。
ターミナルでReturn(Enter)キーを押して実行する。
**ダウンロード [#g1d85df4]
***実行ファイル [#q0779f83]
(Windows版)
#ref(http://www.ripple.gr.jp/~kuran_kuran/bin/download/openalstream_sample_windows_20090814.zip)~
(MacOSX版)
#ref(http://www.ripple.gr.jp/~kuran_kuran/bin/download/openalstream_sample_osx_20090816.zip)~
***ソースファイル [#na90fb3b]
(Windows版)
#ref(http://www.ripple.gr.jp/~kuran_kuran/bin/download/openalstream_sample_windows_source_20090814.zip)~
(MacOSX版)
#ref(http://www.ripple.gr.jp/~kuran_kuran/bin/download/openalstream_sample_osx_source_20090816.zip)~
[[前に戻る>プログラミング]]