ストリーミング再生(.wav)(OpenAL)

「ストリーミング再生(.wav)(OpenAL)」の編集履歴(バックアップ)一覧はこちら

ストリーミング再生(.wav)(OpenAL)」(2012/12/18 (火) 15:46:46) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

<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 &lt;stdio.h&gt;<br /> #include &lt;AL/alut.h&gt;<br /> #include &lt;vector&gt;<br /> #include &lt;iostream&gt;<br /> #include &lt;fstream&gt;</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*)&amp;riff,4);<br />     // データサイズを取得<br />     // データサイズ = ファイルサイズ - 8 byte<br />     fp.read((char*)&amp;DataSize,4);<br />     // WAVEの読み込み<br />     unsigned int wave;<br />     fp.read((char*)&amp;wave,4);<br />     // PCM 情報とデータの先頭の取得<br />     for( int i = 0; i &lt; 2; ++i ){<br />         unsigned int res, size;<br />         fp.read((char*)&amp;res,4);<br />         fp.read((char*)&amp;size,4);<br />         if( 0x20746d66u == res ){//fmt<br />             // PCM 情報の取得<br />             unsigned short res16;<br />             fp.read((char*)&amp;res16,2);<br />             if( 1 != res16 ){// 非対応フォーマット<br />                 return false;<br />             }<br />    // モノラル(1), ステレオ(2)<br />             fp.read((char*)&amp;ChannelQuantity,2);<br />             if( 2 &lt; ChannelQuantity ){<br />                 return false;<br />             }<br />             // サンプリングレート<br />             fp.read((char*)&amp;SamplingRate,4);<br />             // 1秒あたりのバイト数(byte/sec)<br />             fp.read((char*)&amp;Bps,4);<br />             // ブロックサイズ(byte/sample)<br />             fp.read((char*)&amp;BlockSize,2);<br />             // サンプルあたりのビット数(bit/sample)<br />             fp.read((char*)&amp;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 &gt; 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, &amp;buffer );<br />     }<br />     vector&lt;char&gt; wavData(size);<br />     int read = Read(&amp;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, &amp;wavData[0], read, SamplingRate);<br />     return buffer;<br /> }</p> <p>void main (int argc, char **argv){<br />     // alut の初期化<br />     alutInit (&amp;argc, argv);<br />     // Wave ファイルの読み込み<br />     WaveFile wav;<br />     wav.Open("sample.wav");<br />     // ソースの作成<br />     ALuint source;<br />     alGenSources (1, &amp;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, &amp;processed );<br />         while( processed-- ){<br />             // 処理を終えたキューをデキュー<br />             ALuint buffer;<br />             alSourceUnqueueBuffers( source, 1, &amp;buffer );<br />             // バッファを埋める<br />             buffer = wav.CreateBuffer( bufferSize, buffer );<br />             // エンキュー<br />             alSourceQueueBuffers( source, 1, &amp;buffer );<br />         }<br />     }<br />     // リソースを開放<br />     alSourceStop(source);<br />     alDeleteSources( 1, &amp;source );<br />     alDeleteBuffers( 2, buffers );<br />     alutExit ();<br />     return;<br /> }</p> </td> </tr></tbody></table><p> </p> <p> </p> <p> </p> <p> </p>

表示オプション

横に並べて表示:
変化行の前後のみ表示: