diff --git a/.gitignore b/.gitignore index 0fae0cfa..4fb88f38 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,5 @@ project.xcworkspace/ # temporary files ------------------------------- -*~ \ No newline at end of file +*~ +.idea diff --git a/audiostream/inc/ni/media/audio/ostream.h b/audiostream/inc/ni/media/audio/ostream.h index 7d3d8981..cdd3b0cc 100644 --- a/audiostream/inc/ni/media/audio/ostream.h +++ b/audiostream/inc/ni/media/audio/ostream.h @@ -66,21 +66,14 @@ class ostream : protected std::ostream auto operator<<( const Range& rng ) -> std::enable_if_t::value, ostream&>; using std::ostream::bad; - using std::ostream::clear; - using std::ostream::eof; using std::ostream::fail; - using std::ostream::good; - using std::ostream::rdbuf; - using std::ostream::rdstate; using std::ostream::setstate; - using std::ostream::tellp; auto frame_tellp() -> pos_type; auto sample_tellp() -> pos_type; // - stream_info - virtual auto info() const -> const info_type&; protected: @@ -113,9 +106,35 @@ auto ostream::operator<<( Value val ) -> std::enable_if_t auto ostream::operator<<( const Range& rng ) -> std::enable_if_t::value, ostream&> { - // TODO fast pcm conversion - for ( auto val : rng ) - *this << val; + using Value = typename boost::range_value::type; + + if ( fail() ) + return *this; + + if ( m_streambuf->overflow() == streambuf::traits_type::eof() ) + { + setstate( rdstate() | failbit ); + return *this; + } + + auto in_beg = std::begin( rng ); + auto in_end = std::end( rng ); + + auto in_iter = in_beg; + do + { + m_streambuf->sync(); + assert( std::distance( m_streambuf->pptr(), m_streambuf->epptr() ) % m_info->bytes_per_sample() == 0 ); + + const auto out_beg = pcm::make_iterator( m_streambuf->pptr(), m_info->format() ); + const auto out_end = pcm::make_iterator( m_streambuf->epptr(), m_info->format() ); + + auto result = pcm::copy( in_iter, in_end, out_beg, out_end ); + + auto count = static_cast( std::distance( in_iter, result.first ) * m_info->bytes_per_sample() ); + in_iter = result.first; + m_streambuf->pbump( count ); + } while ( in_iter < in_end && m_streambuf->overflow() != streambuf::traits_type::eof() ); return *this; }