aiff_file_source
ビッグエンディアンの検証用にAIFFファイルのデバイスを作ってみました。
仕様は適当にググって見つけたページを参考にしました。
http://nagasm.suac.net/ASL/sound05/#aiff-1
数値がビッグエンディアンで格納されることを除けばフォーマット自体はWAVEファイルによく似ているので(実際は逆にRIFFがIFFをマネしたものらしい)、コードはほとんどコピペで書けました。
一点、「今のところ使わない」と言っていた80ビット浮動小数点数が使われていて困りました。
とりあえず、64ビット整数で保持できる範囲でデコードしています。
inline boost::uint_least64_t decode_extended(const char* s) { boost::int_least16_t exp = decode_int<big,2>(s); // 手抜きにつき、入力が負でないことを仮定 boost::uint_least64_t mant = decode_uint<big,8>(s+2); if ((exp == 0) && (mant == 0)) return 0; else return mant >> (63-(exp-16383)); } inline void encode_extended(char* s, boost::uint_least64_t n) { if (n == 0) { std::memset(s, 0, 10); return; } boost::int_least16_t exp = 16383+63; boost::uint_least64_t mant = n; while ((mant & 0x8000000000000000) == 0) { --exp; mant <<= 1; } encode_int<big,2>(s, exp); encode_uint<big,8>(s+2, mant); }
いつもの演奏プログラムはこうなります。
audio::aiff_file_source file("doremi.aiff"); audio::pcm_format fmt = file.format(); // pcm_sinkで使用できる形式に変換 if (fmt.type == audio::int8) fmt.type = audio::uint8; else fmt.type = audio::int_le16; io::copy( audio::widen<float>(file), audio::widen<float>(audio::pcm_sink(fmt)) );
今のところ、pcm_sinkはリトルエンディアンしか扱えないので、AIFF側と別のフォーマットを指定してオープンする必要があります。
また、フォーマットが違うので一旦ワイド文字を経由してコンバートを行う必要があります。
SourceとSinkで扱えるフォーマットが違う場合、適切なフォーマットを判定する手段が欲しいですね。