続demultiplexer

ノンブロッキングにするまでもなく、demultiplexer内部のバッファリングをやめたらうまくいきました。
というわけで、ステレオ再生は以下のようになります。

asio.create_buffers(0, 2);

io_ex::demultiplexer demuxer(4); // バッファサイズの指定がなくなった
demuxer.push(asio.get_sink(0));
demuxer.push(asio.get_sink(1));

io::copy(
    io::restrict(
        audio::stereo(audio::sine_wave_source(44100, 32, 261.6)),
        0,
        8*44100 * 5
    ),
    demuxer
);

Oggファイルの再生も試してみました。
とりあえず、Ogg=16ビット、ASIO=32ビット決め打ちで次のようなフィルタを作り、

struct convert_16_to_32
{
    typedef char char_type;
    typedef boost::iostreams::multichar_output_filter_tag category;

    template<typename Sink>
    std::streamsize write(Sink& sink, const char* s, std::streamsize n)
    {
        std::streamsize total = 0;
        while (n != 0)
        {
            char buf[4];
            buf[0] = '\0';
            buf[1] = '\0';
            buf[2] = *(s++);
            buf[3] = *(s++);
            boost::iostreams::write(sink, buf, 4);
            n -= 2;
            total += 2;
        }
        return (total != 0) ? total : -1;
    }
};

Boost.Iostreamsのcompositeアダプタでかぶせると再生できました。

asio.create_buffers(0, 2);

io_ex::demultiplexer demuxer(2);
demuxer.push(io::compose(convert_16_to_32(), asio.get_sink(0)));
demuxer.push(io::compose(convert_16_to_32(), asio.get_sink(1)));

io::copy(audio::vorbis_file_source(filename), demuxer);

ただし、まだバッファリング処理がマズいらしく、再生しながら他の作業をしているとノイズが入ることがありました。要調査です。

demultiplexer自体はL/R入れ替え(Reverse Stereo)や特定のチャンネルのみ再生(null_sinkを使う)などにも利用できます。逆の動きをする、multiplexerも作ればもっと面白くなりそうです。