マルチストリームとサンプルサイズ

昨日はマルチストリームの長さを考えましたが、今日は要素のサイズについて考えます。
複数のストリームがあるとき、各ストリームの要素サイズもまた異なる場合があります。実際、ASIOの場合は一つのデバイスが複数のインタフェース(アナログ、S/PDEIFなど)を持つことがあり、インタフェース毎に要素のサイズが違うことも考えられます。
サンプルサイズの違うストリームを扱うとなると、multiplexer/demultiplexerも、要素のサイズをコンストラクタではなく、push()のタイミングで設定する必要があります。

// 入力、出力ともに2つずつ
asio.create_buffers(2, 2);

// コンストラクタではサイズを指定しない
io_ex::multiplexer muxer;

// 第2引数は要素のサイズ
muxer.push(asio.get_source(0), asio.get_source(0).block_size());
muxer.push(asio.get_source(1), asio.get_source(1).block_size());

io_ex::demultiplexer demuxer;

// 入力チャンネルのサイズから出力チャンネルのサイズへ変換
demuxer.push(
    io::compose(
        audio::sample_cvt(
            asio.get_source(0).block_size(),
            asio.get_sink(0).block_size()
        ),
        asio.get_sink(0)
    )
    asio.get_source(0).block_size()
);
demuxer.push(
    io::compose(
        audio::sample_cvt(
            asio.get_source(1).block_size(),
            asio.get_sink(1).block_size()
        ),
        asio.get_sink(1)
    )
    asio.get_source(1).block_size()
);

// バッファサイズは、まだ決め打ち
io_ex::background_copy bg_copy(muxer, demuxer, 2*64*4);
std::cin.ignore(256, '\n');

block_size()はBoost.Iostreamsのコンセプトでないため、アダプタをかぶせるとアダプタのメンバ関数には現れません。このため、要素のサイズを推定するのが難しくなっています。
もし、Boost.Iostreamsにblock_size()のコンセプトがあれば、メンバ関数block_size()の存在を期待して(あるいはヘルパ関数を介して)値を推定できるため、次のように短く書くことができます。

// sample_cvtとSinkを合成する架空の関数
template<class Source, class Sink>
cvt_sink<Sink> make_cvt_sink(const Source& src, const Sink& snk);

asio.create_buffers(2, 2);

io_ex::multiplexer muxer;
muxer.push(asio.get_source(0));
muxer.push(asio.get_source(1));

io_ex::demultiplexer demuxer;
demuxer.push(make_cvt_sink(asio.get_source(0), asio.get_sink(0)));
demuxer.push(make_cvt_sink(asio.get_source(1), asio.get_sink(1)));

io_ex::background_copy bg_copy(muxer, demuxer, 2*64*4);
std::cin.ignore(256, '\n');

無いものねだりしても仕方がないので、こんな関数でお茶を濁しておきます。

template<class Sink>
void push_with_cvt(
    io_ex::demultiplexer& demuxer, const Sink& snk,
    std::streamsize in_size, std::streamsize out_size)
{
    demuxer.push(
        io::compose(
            audio::sample_cvt(in_size, out_size),
            snk
        )
        in_size
    );
}

io_ex::demultiplexer demuxer;
push_with_cvt(demuxer, asio.get_sink(0),
    asio.get_source(0).block_size(), asio.get_sink(0).block_size());
push_with_cvt(demuxer, asio.get_sink(1),
    asio.get_source(1).block_size(), asio.get_sink(1).block_size());