「ストリーミング再生(.wav)(OpenAL)」の編集履歴(バックアップ)一覧はこちら
追加された行は緑色になります。
削除された行は赤色になります。
<p><strong>OpenAL で .wav をストリーミング再生します。</strong></p>
<table width="600" border="1" cellspacing="1" cellpadding="1"><tbody><tr><td>
<p>#pragma comment(lib, "OpenAL32.lib")<br />
#pragma comment(lib, "alut.lib")</p>
<p>#include <stdio.h><br />
#include <AL/alut.h><br />
#include <vector><br />
#include <iostream><br />
#include <fstream></p>
<p>using namespace std;</p>
<p>class WaveFile{<br />
public:<br />
~WaveFile(){<br />
fp.close();<br />
}<br />
bool Open(const char *path);<br />
int Read(void *out, size_t size);<br />
bool IsEnd()const{return (0==LoadedSize)||(DataSize==LoadedSize);}<br />
ALuint CreateBuffer(ALuint size, ALuint buffer);<br />
private:<br />
unsigned short ChannelQuantity;<br />
unsigned short BlockSize;<br />
unsigned short BitPerSample;<br />
unsigned int Bps;<br />
unsigned int SamplingRate;</p>
<p> ifstream fp;<br />
ifstream::pos_type DataHead;<br />
size_t DataSize;<br />
size_t LoadedSize;<br />
};<br />
bool WaveFile::Open(const char *path){<br />
fp.open(path,ios::binary);<br />
// "RIFF" の読み込み<br />
unsigned int riff;<br />
fp.read((char*)&riff,4);<br />
// データサイズを取得<br />
// データサイズ = ファイルサイズ - 8 byte<br />
fp.read((char*)&DataSize,4);<br />
// WAVEの読み込み<br />
unsigned int wave;<br />
fp.read((char*)&wave,4);<br />
// PCM 情報とデータの先頭の取得<br />
for( int i = 0; i < 2; ++i ){<br />
unsigned int res, size;<br />
fp.read((char*)&res,4);<br />
fp.read((char*)&size,4);<br />
if( 0x20746d66u == res ){//fmt<br />
// PCM 情報の取得<br />
unsigned short res16;<br />
fp.read((char*)&res16,2);<br />
if( 1 != res16 ){// 非対応フォーマット<br />
return false;<br />
}<br />
// モノラル(1), ステレオ(2)<br />
fp.read((char*)&ChannelQuantity,2);<br />
if( 2 < ChannelQuantity ){<br />
return false;<br />
}<br />
// サンプリングレート<br />
fp.read((char*)&SamplingRate,4);<br />
// 1秒あたりのバイト数(byte/sec)<br />
fp.read((char*)&Bps,4);<br />
// ブロックサイズ(byte/sample)<br />
fp.read((char*)&BlockSize,2);<br />
// サンプルあたりのビット数(bit/sample)<br />
fp.read((char*)&BitPerSample,2);<br />
}<br />
else if( 0x61746164u == res ){//data<br />
// データの開始位置を保存<br />
DataHead = fp.tellg();<br />
DataSize = size;<br />
// データを読み飛ばす<br />
fp.seekg(size,ios::cur);<br />
}<br />
}<br />
// データの開始位置までシーク<br />
fp.seekg( DataHead );<br />
LoadedSize = 0;<br />
return true;<br />
}</p>
<p>int WaveFile::Read(void *out, size_t size){<br />
if( !out ){<br />
return 0;<br />
}<br />
// データサイズの調整<br />
if( LoadedSize + size > DataSize ){<br />
size = DataSize - LoadedSize;<br />
}<br />
// データを読み出し書き込む<br />
fp.read((char*)out,size);<br />
LoadedSize += size;<br />
if( LoadedSize == DataSize ){<br />
LoadedSize = 0;<br />
fp.seekg(DataHead);<br />
}<br />
return size;<br />
}</p>
<p>ALuint WaveFile::CreateBuffer( ALuint size, ALuint buffer){<br />
if( !buffer ){// 新規にバッファを作成<br />
alGenBuffers( 1, &buffer );<br />
}<br />
vector<char> wavData(size);<br />
int read = Read(&wavData[0],size);<br />
ALenum format;<br />
if( 1 == ChannelQuantity ){// モノラル<br />
format = (8==BitPerSample)?AL_FORMAT_MONO8:AL_FORMAT_MONO16;<br />
}else{// ステレオ<br />
format = (8==BitPerSample)?AL_FORMAT_STEREO8:AL_FORMAT_STEREO16;<br />
}<br />
// OpenAL のバッファにデータの書き込み<br />
alBufferData( buffer, format, &wavData[0], read, SamplingRate);<br />
return buffer;<br />
}</p>
<p>void main (int argc, char **argv){<br />
// alut の初期化<br />
alutInit (&argc, argv);<br />
// Wave ファイルの読み込み<br />
WaveFile wav;<br />
wav.Open("sample.wav");<br />
// ソースの作成<br />
ALuint source;<br />
alGenSources (1, &source);<br />
// バッファを作成しキューイング<br />
ALuint bufferSize = 1*1024*1024;<br />
ALuint buffers[2];<br />
buffers[0] = wav.CreateBuffer( bufferSize, 0 );<br />
buffers[1] = wav.CreateBuffer( bufferSize, 0 );<br />
alSourceQueueBuffers( source, 2, buffers );<br />
// 再生<br />
alSourcePlay (source);<br />
alutSleep (1);<br />
// 再生し終わったらバッファを埋めて再びキューイング<br />
while(1){<br />
// 処理を終えたキューの数を取得<br />
int processed;<br />
alGetSourcei( source, AL_BUFFERS_PROCESSED, &processed );<br />
while( processed-- ){<br />
// 処理を終えたキューをデキュー<br />
ALuint buffer;<br />
alSourceUnqueueBuffers( source, 1, &buffer );<br />
// バッファを埋める<br />
buffer = wav.CreateBuffer( bufferSize, buffer );<br />
// エンキュー<br />
alSourceQueueBuffers( source, 1, &buffer );<br />
}<br />
}<br />
// リソースを開放<br />
alSourceStop(source);<br />
alDeleteSources( 1, &source );<br />
alDeleteBuffers( 2, buffers );<br />
alutExit ();<br />
return;<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p> </p>
<p> </p>
<p> </p>