sample_cvt

PCMフォーマット変換フィルタの入出力サイズを可変になるように修正してみました。
(2の補数表現以外も考慮しているため、意外に時間がかかりました←かなり無駄)

asio.create_buffers(0, 2);

io_ex::demultiplexer demuxer(2);
// 16ビット -> 32ビット
demuxer.push(io::compose(audio::sample_cvt(2,4), asio.get_sink(0)));
demuxer.push(io::compose(audio::sample_cvt(2,4), asio.get_sink(1)));

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

sample_cvt自体はこんな感じです。

class sample_cvt
{
public:
    typedef char char_type;
    typedef boost::iostreams::multichar_output_filter_tag category;

    sample_cvt(std::streamsize from, std::streamsize to)
        : from_size_(from), to_size_(to)
    {
    }

    template<typename Sink>
    std::streamsize write(Sink& sink, const char* s, std::streamsize n)
    {
        // サイズが同じならそのまま
        if (from_size_ == to_size_)
            return boost::iostreams::write(sink, s, n);

        // それ以外はint32_tを経由して
        std::streamsize total = 0;
        while (n != 0)
        {
            boost::int32_t val = decode(s);

            char buf[4];
            encode(buf, val);
            boost::iostreams::write(sink, buf, to_size_);

            s += from_size_;
            n -= from_size_;
            total += from_size_;
        }
        return (total != 0) ? total : -1;
    }

private:
    std::streamsize from_size_;
    std::streamsize to_size_;

    boost::int32_t decode(const char* s)
    {
        // 実装は省略
        if (from_size_ == 1)
            return detail::cvt_8::decode(s);
        else if (from_size_ == 2)
            return detail::cvt_16::decode(s);
        else if (from_size_ == 3)
            return detail::cvt_24::decode(s);
        else
            return detail::cvt_32::decode(s);
    }

    // 略
    void encode(char* s, boost::int32_t val);
};

まだ、float/doubleには対応していません。
それと、2回変換が必要なのとサイズと処理のマッピングが気になります。テンプレートメタプログラミングを使ってうまいことできないか考え中です。