audio::char_traits
規格(ISO/IEC 14882:2003 17.1.3)を確認したところ、ストリームの文字型はPOD型でなければいけないことが判明しました。
BOOST_STRONG_TYPEDEFを使うと、代入演算子をオーバーロードしてしてしまうため、POD型になりません。
PODにするために、
template<typename T> struct char_ { T value; };
として、char_<float>を使うことも考えましたが、演算子が使えないため不便です。
「やっぱり生のfloatがいい」ということで、Boost.Iostreamsをstd::char_traits以外の文字特性に対応させる道を選びました。
改良版code_converterは、こうなりました。
template < class Device, // ナロー文字デバイス class CharT, // ワイド文字 // ワイド文字の特性 class Traits=std::char_traits<CharT>, // バッファのアロケータ class Allocator=std::allocator< typename boost::iostreams::char_type_of<Device>::type > > class code_converter;
Traitsはなんでも設定可能なので、新たにhamigaki::audio::char_traitsを作り、float用に特殊化します。
なんとか、音が鳴ったコードはこんな感じです。
namespace audio = hamigaki::audio; namespace io_ex = hamigaki::iostreams; namespace io = boost::iostreams; // floatのSource audio::vorbis_file_source vf("doremi.ogg"); const audio::vorbis_info& info = vf.info(); audio::pcm_format fmt; fmt.rate = info.rate; fmt.bits = 16; fmt.channels = info.channels; // floatでwriteするpcm_sink typedef io_ex::code_converter< audio::pcm_sink, float, audio::char_traits<float> > float_pcm_sink; float_pcm_sink sink(audio::pcm_sink(fmt, fmt.optimal_buffer_size())); // 符号付き16ビット(リトルエンディアン)のコンバータを設定 std::locale loc(std::locale(), new audio::codecvt_s16_le); sink.imbue(loc); io::copy(vf, sink);
hamigaki::iostreams::code_converterは手抜き実装なので、まだsinkにしか対応していません。
他のデバイスやアダプタも大量に修正が必要です、、、。