![]() |
Hamigaki.Audioを使用した簡単な例として、WAVEファイルを再生するプログラムを紹介する。
#include <hamigaki/audio/pcm_device.hpp> #include <hamigaki/audio/wave_file.hpp> #include <boost/iostreams/copy.hpp> namespace audio = hamigaki::audio; namespace io = boost::iostreams; int main() { audio::wave_file_source wf("doremi.wav"); io::copy(wf, audio::pcm_sink(wf.format())); }
Hamigaki.AudioにおけるオーディオデバイスはBoost.IostreamsのSource/Sinkのモデルとして実装されている。ここではSourceとしてwave_file_source
を、Sinkとしてpcm_sink
を使用している。
wave_file_source
はWAVEファイルを読み出すSourceである。コンストラクタの引数としてファイル名を指定する。
pcm_sink
はPCMデータを再生するためのSinkである。Source/Sink間のデータのやり取りは同じフォーマットで行う必要がある。そのため、pcm_sink
のコンストラクタにはwave_file_source::format()
から取得したpcm_format
を渡す。
Sourceからデータを読み取り、Sinkへ書き出すにはboost::iostreams::copy()
を用いる。もちろん、boost::iostreams::read()
やboost::iostreams::write()
も使用できる。
PCMデータのバイトストリームは、1つのサンプルが複数バイトで表現されたり、一般に実行時までフォーマットが確定しないことから、データの加工を行いにくい性質がある。1つのサンプルをワイド文字1文字で表現できれば、データの加工が容易になる。これはマルチバイトエンコーディングの文字列の扱いに良く似ている。PCMデータの場合、通常ワイド文字にはfloatやdoubleのような浮動小数点数を用いる。これは多くの波形処理にとって都合が良いからである。
例として、440Hzの正弦波を再生するプログラムを示す。
#include <hamigaki/audio/pcm_device.hpp> #include <hamigaki/audio/sine_wave.hpp> #include <hamigaki/audio/wide_adaptor.hpp> #include <boost/iostreams/copy.hpp> namespace audio = hamigaki::audio; namespace io = boost::iostreams; int main() { audio::pcm_format fmt; fmt.type = audio::int_le16; fmt.channels = 1; fmt.rate = 44100; audio::basic_sine_wave_source<float> src(fmt.rate, 440.0f); io::copy(src, audio::widen<float>(audio::pcm_sink(fmt))); }
basic_sine_wave_source
は正弦波を生成するSourceである。コンストラクタの引数としてサンプリング周波数と正弦波の周波数を指定する。
basic_sine_wave_source
の文字型はfloatであり、pcm_sink
の文字型charとは一致しないため、そのままではコピーを行うことができない。コピーを行うためには、Source/Sink間でやり取りする文字型をより「大きな」型に統一しなければならない。widen
()はこのための関数であり、受け取ったデバイスの文字型をテンプレート引数で指定した型に変換したデバイスを返す。(実際には、write()メンバ関数の中で、float文字列をバイト列へと変換する)
basic_sine_wave_source
の出力は-1.0~1.0の範囲になる。これが、widen
()によって-32768~32767にマッピングされる(フォーマットが16ビットの場合)。変換は単純に32768倍することで行われるため、変換元の値が1.0の場合に値が溢れてしまう。溢れた値は最大値に丸められるが、これが再生の際にノイズとなって現れる。これを防ぐためには、amplify
()を使用して振幅を調整すると良い。
#include <hamigaki/audio/amplify.hpp> #include <hamigaki/audio/pcm_device.hpp> #include <hamigaki/audio/sine_wave.hpp> #include <hamigaki/audio/wide_adaptor.hpp> #include <boost/iostreams/copy.hpp> namespace audio = hamigaki::audio; namespace io = boost::iostreams; int main() { audio::pcm_format fmt; fmt.type = audio::int_le16; fmt.channels = 1; fmt.rate = 44100; audio::basic_sine_wave_source<float> src(fmt.rate, 440.0f); io::copy( audio::amplify(src, 0.5f), audio::widen<float>(audio::pcm_sink(fmt))); }
製作著作 © 2006-2008 Takeshi Mouri |