Marc Boucek
Native Instruments
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
class source
{
public:
using char_type = char;
struct category : boost::iostreams::input
, boost::iostreams::device_tag{};
std::streamsize read( char_type* s, std::streamsize n );
}
class seekable_source
{
public:
using char_type = char;
struct category : boost::iostreams::input_seekable
, boost::iostreams::device_tag{};
std::streamsize read( char_type* s, std::streamsize n );
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way );
}
class sink
{
public:
using char_type = char;
struct category : boost::iostreams::output
, boost::iostreams::device_tag{};
std::streamsize write( char_type* s, std::streamsize n );
}
class seekable_sink
{
public:
using char_type = char;
struct category : boost::iostreams::output_seekable
, boost::iostreams::device_tag{};
std::streamsize write( char_type* s, std::streamsize n );
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way );
}
template <class Container>
class container_source
{
public:
using char_type = typename Container::value_type;
struct category : boost::iostreams::input_seekable
, boost::iostreams::device_tag{};
container_device( Container container )
: m_data( std::move( container ) )
{
}
std::streamsize read( char_type* s, std::streamsize n )
{
auto result = std::min( n, std::streamsize( m_data.size() - m_pos ) );
if ( result != 0 )
{
std::copy( m_data.begin() + m_pos, m_data.begin() + m_pos + result, s );
m_pos += result;
return result;
}
else
{
return -1; // EOF
}
}
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way )
{
auto beg = std::streampos( 0 );
auto pos = std::streampos( m_pos );
auto end = std::streampos( m_data.size() );
m_pos = size_t( absolute_position( pos, beg, end, off, way ) );
return m_pos;
}
private:
Container m_data;
size_t m_pos = 0;
};
template <class Container>
class container_sink
{
public:
using char_type = typename Container::value_type;
struct category : boost::iostreams::output_seekable
, boost::iostreams::device_tag{};
container_device( Container container )
: m_data( std::move( container ) )
{
}
std::streamsize write( const char_type* s, std::streamsize n )
{
std::streamsize result = 0;
if ( m_pos != m_data.size() )
{
result = std::min( n, std::streamsize( m_data.size() - m_pos ) );
std::copy( s, s + result, m_data.begin() + m_pos );
m_pos += result;
}
if ( result < n )
{
m_data.insert( m_data.end(), s, s + n );
m_pos = m_data.size();
}
return n;
}
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way )
{
auto beg = std::streampos( 0 );
auto pos = std::streampos( m_pos );
auto end = std::streampos( m_data.size() );
m_pos = size_t( absolute_position( pos, beg, end, off, way ) );
return m_pos;
}
private:
Container m_data;
size_t m_pos = 0;
};
template <class Container>
class container_device
{
public:
using char_type = typename Container::value_type;
using category = boost::iostreams::seekable_device_tag;
container_device( Container container )
: m_data( std::move( container ) )
{
}
std::streamsize read( char_type* s, std::streamsize n )
{
auto result = std::min( n, std::streamsize( m_data.size() - m_pos ) );
if ( result != 0 )
{
std::copy( m_data.begin() + m_pos, m_data.begin() + m_pos + result, s );
m_pos += result;
return result;
}
else
{
return -1; // EOF
}
}
std::streamsize write( const char_type* s, std::streamsize n )
{
std::streamsize result = 0;
if ( m_pos != m_data.size() )
{
result = std::min( n, std::streamsize( m_data.size() - m_pos ) );
std::copy( s, s + result, m_data.begin() + m_pos );
m_pos += result;
}
if ( result < n )
{
m_data.insert( m_data.end(), s, s + n );
m_pos = m_data.size();
}
return n;
}
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way )
{
auto beg = std::streampos( 0 );
auto pos = std::streampos( m_pos );
auto end = std::streampos( m_data.size() );
m_pos = size_t( absolute_position( pos, beg, end, off, way ) );
return m_pos;
}
private:
Container m_data;
size_t m_pos = 0;
};
template <class Container>
class container_source : private container_device<Container>
{
using base_type = container_device<Container>;
public:
using char_type = typename base_type::char_type;
struct category : boost::iostreams::input_seekable
, boost::iostreams::device_tag{};
using base_type::base_type;
using base_type::read;
using base_type::seek;
};
template <class Container>
class container_sink : private container_device<Container>
{
using base_type = container_device<Container>;
public:
using char_type = typename base_type::char_type;
struct category : boost::iostreams::output_seekable
, boost::iostreams::device_tag{};
using base_type::base_type;
using base_type::write;
using base_type::seek;
};
class audio_source
{
public:
using char_type = char;
struct category : boost::iostreams::input
, boost::iostreams::device_tag{};
using info_type = audio::stream_info;
info_type info() const;
std::streamsize read( char_type* s, std::streamsize n );
}
class seekable_audio_source
{
public:
using char_type = char;
struct category : boost::iostreams::input_seekable
, boost::iostreams::device_tag{};
using info_type = audio::stream_info;
info_type info() const;
std::streamsize read( char_type* s, std::streamsize n );
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way );
}
class audio_sink
{
public:
using char_type = char;
struct category : boost::iostreams::output
, boost::iostreams::device_tag{};
using info_type = audio::stream_info;
audio_sink( info_type info );
std::streamsize write( char_type* s, std::streamsize n );
}
class seekable_audio_sink
{
public:
using char_type = char;
struct category : boost::iostreams::output_seekable
, boost::iostreams::device_tag{};
using info_type = audio::stream_info;
audio_sink( info_type info );
std::streamsize write( char_type* s, std::streamsize n );
std::streampos seek( boost::iostreams::stream_offset off, BOOST_IOS::seekdir way );
}
template <class Container, class Info>
class container_source : private boostext::iostreams::container_source<Container>
{
using base_type = boostext::iostreams::container_source<Container>;
public:
using base_type::char_type;
using base_type::category;
using info_type = Info;
container_source( Container container, const info_type& info );
info_type info() const { return m_info; }
using base_type::read;
using base_type::seek;
private:
info_type m_info;
};
template <class Container, class Info>
class container_sink : private boostext::iostreams::container_sink<Container>
{
using base_type = boostext::iostreams::container_sink<Container>;
public:
using base_type::char_type;
using base_type::category;
using info_type = Info;
container_sink( Container container, const info_type& info );
info_type info() const { return m_info; }
using base_type::write;
using base_type::seek;
private:
info_type m_info;
};
namespace audio
{
class istream_info
{
public:
virtual ~istream_info() = default;
using format_type = ::pcm::format;
void format( format_type format );
auto format() const -> format_type;
void sample_rate( size_t val );
size_t sample_rate() const;
void num_channels( size_t num_channels );
size_t num_channels() const;
size_t bits_per_sample() const;
size_t bytes_per_sample() const;
size_t bytes_per_frame() const;
friend bool operator==( const istream_info& lhs, const istream_info& rhs );
friend bool operator!=( const istream_info& lhs, const istream_info& rhs );
private:
// Members
size_t m_sample_rate = 44100; //!< sample rate
size_t m_num_channels = 1; //!< number of channels
format_type m_format; //!< pcm format
};
} // namespace audio
namespace audio
{
class istream : protected std::istream
{
public:
istream();
template <class AudioSource>
istream( AudioSource source );
istream( const istream& ) = delete;
istream( istream&& );
istream& operator=( istream& ) = delete;
istream& operator =( istream&& );
// - std::istream
using char_type = std::istream::char_type;
using traits_type = std::istream::traits_type;
using int_type = std::istream::int_type;
using pos_type = std::istream::pos_type;
using off_type = std::istream::off_type;
using std::istream::operator bool;
using std::istream::operator!;
using std::istream::bad;
using std::istream::clear;
using std::istream::eof;
using std::istream::fail;
using std::istream::good;
using std::istream::rdstate;
using std::istream::setstate;
using std::istream::rdbuf;
auto read( char_type* s, std::streamsize n ) -> istream&;
template <class Value>
auto operator>>( Value& val ) -> std::enable_if_t<std::is_arithmetic<Value>::value, istream&>;
template <class Range>
auto operator>>( Range&& rng ) -> std::enable_if_t<boost::has_range_iterator<Range>::value, istream&>;
auto seekg( pos_type pos ) -> istream&;
auto sample_seekg( pos_type pos ) -> istream&;
auto frame_seekg( pos_type pos ) -> istream&;
auto seekg( off_type off, std::ios_base::seekdir dir ) -> istream&;
auto sample_seekg( off_type off, std::ios_base::seekdir dir ) -> istream&;
auto frame_seekg( off_type off, std::ios_base::seekdir dir ) -> istream&;
using std::istream::gcount;
auto sample_gcount() const -> std::streamsize;
auto frame_gcount() const -> std::streamsize;
using std::istream::tellg;
auto frame_tellg() -> pos_type;
auto sample_tellg() -> pos_type;
// - stream_info
using info_type = istream_info;
virtual auto info() const -> const info_type&;
private:
std::unique_ptr<info_type> m_info;
std::unique_ptr<streambuf> m_streambuf;
};
} // audio
namespace audio
{
class ifstream_info : public istream_info
{
public:
enum class container_type {aiff, flac, mp3, mp4, ogg, wav, wma};
enum class codec_type {aac, alac, aiff, flac, mp3, vorbis, wav, wma};
void num_frames( size_t num_frames );
size_t num_frames() const;
void codec( codec_type value );
auto codec() const -> codec_type;
void container( container_type value );
auto container() const -> container_type;
friend bool operator==( const ifstream_info& lhs, const ifstream_info& rhs );
friend bool operator!=( const ifstream_info& lhs, const ifstream_info& rhs );
private:
size_t m_num_frames = 0;
container_type m_container;
codec_type m_codec;
};
} // namespace audio
// ifstream.h
namespace audio
{
class ifstream : public istream
{
public:
using info_type = ifstream_info;
ifstream() = default;
ifstream( const std::string& file );
ifstream( const std::string& file, info_type::container_type container, size_t stream_index = 0 );
ifstream( ifstream&& );
ifstream& operator=( ifstream&& );
const info_type& info() const override;
};
} // audio
// ifstream.cpp
istream make_istream( const std::string& file
, ifstream_info::container_type container, size_t stream_index = 0 )
{
using container_type = ifstream_info::container_type;
if ( container != container_type::mp4 && stream_index != 0 )
{
throw std::runtime_error( "Unsupported stream index" );
}
switch ( container )
{
#if NIMEDIA_ENABLE_AIFF_DECODING
case container_type::aiff:
return { aiff_file_source( file ) };
#endif
#if NIMEDIA_ENABLE_FLAC_DECODING
case container_type::flac:
return { flac_file_source( file ) };
#endif
#if NIMEDIA_ENABLE_MP3_DECODING
case container_type::mp3:
return { mp3_file_source( file ) };
#endif
#if NIMEDIA_ENABLE_MP4_DECODING
case container_type::mp4:
return { mp4_file_source( file, stream_index ) };
#endif
#if NIMEDIA_ENABLE_OGG_DECODING
case container_type::ogg:
return { ogg_file_source( file ) };
#endif
#if NIMEDIA_ENABLE_WAV_DECODING
case container_type::wav:
return { wav_file_source( file ) };
#endif
#if NIMEDIA_ENABLE_WMA_DECODING
case container_type::wma:
return { wma_file_source( file ) };
#endif
default:
break;
}
throw std::runtime_error( "Unsupported container_type" );
}
istream make_istream( const std::string& file )
{
if ( auto container = ifstream_container( file ) )
return make_istream( file, *container );
throw std::runtime_error( "Unsupported file extension" );
}
} // namespace
//----------------------------------------------------------------
ifstream::ifstream( const std::string& file )
{
istream::operator=( make_istream( file ) );
}
} // audio
Format | Windows | Osx | Ios | Linux |
---|---|---|---|---|
wav | native | native | native | native |
aiff | native | native | native | native |
flac | libFlac | libFlac | libFlac | libFlac |
ogg/vorbis | libVorbis | libVorbis | libVorbis | libVorbis |
mp3 | WMF | CoreAudio | CoreAudio | No :( |
mp4 | WMF | CoreAudio | CoreAudio | No :( |
Format | CMake Option |
---|---|
wav | NIMEDIA_ENABLE_WAV_DECODING |
aiff | NIMEDIA_ENABLE_AIFF_DECODING |
flac | NIMEDIA_ENABLE_FLAC_DECODING |
ogg/vorbis | NIMEDIA_ENABLE_OGG_DECODING |
mp3 | NIMEDIA_ENABLE_MP3_DECODING |
mp4 | NIMEDIA_ENABLE_MP4_DECODING |
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.aiff");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.flac");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.ogg");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.mp3");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.mp4");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.mp4");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.mp4");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
namespace pcm
{
enum number_type : uint8_t
{
signed_integer = 0,
unsigned_integer,
floating_point
};
enum bitwidth_type : uint8_t
{
_8bit = 8,
_16bit = 16,
_24bit = 24,
_32bit = 32,
_64bit = 64
};
enum endian_type : uint8_t
{
big_endian = 0,
little_endian,
#if defined( BOOST_BIG_ENDIAN )
native_endian = big_endian,
#elif defined( BOOST_LITTLE_ENDIAN )
native_endian = little_endian,
#else
#error "unable to determine system endianness."
#endif
};
} // pcm
namespace pcm
{
template <number_type n = signed_integer, bitwidth_type b = _8bit, endian_type e = native_endian>
struct compiletime_format
{
constexpr auto number() const { return n; }
constexpr auto bitwidth() const { return b; }
constexpr auto endian() const { return e; }
};
template <number_type ln, bitwidth_type lb, endian_type le, number_type rn, bitwidth_type rb, endian_type re>
constexpr auto operator==( compiletime_format<ln, lb, le>, compiletime_format<rn, rb, re> )
{
return std::is_same<compiletime_format<ln, lb, le>, compiletime_format<rn, rb, re>>::value;
}
template <number_type ln, bitwidth_type lb, endian_type le, number_type rn, bitwidth_type rb, endian_type re>
constexpr auto operator!=( compiletime_format<ln, lb, le>, compiletime_format<rn, rb, re> )
{
return !std::is_same<compiletime_format<ln, lb, le>, compiletime_format<rn, rb, re>>::value;
}
} // namespace pcm
namespace pcm
{
struct runtime_format
{
runtime_format( const runtime_format& ) = default;
template <class Format = compiletime_format<>, class = enable_if_supported<Format>>
constexpr runtime_format( const Format& fmt = {} )
: m_number( fmt.number() )
, m_bitwidth( fmt.bitwidth() )
, m_endian( fmt.endian() )
, m_index( uint8_t( detail::tuple_find<Format, decltype( compiletime_formats() )>::value ) )
{
}
runtime_format( number_type n, bitwidth_type b, endian_type e = native_endian )
{
static auto const formats = detail::tuple_to_array<runtime_format>( compiletime_formats() );
auto it = boost::find_if( formats, [n, b, e]( const auto& fmt ) {
return fmt.number() == n && fmt.bitwidth() == b && fmt.endian() == e;
} );
if ( it == formats.end() )
throw std::runtime_error( "Invalid format" );
*this /*is*/ = *it;
}
auto number() const { return m_number; }
auto bitwidth() const { return m_bitwidth; }
auto endian() const { return m_endian; }
auto index() const { return m_index; }
private:
number_type m_number;
bitwidth_type m_bitwidth;
endian_type m_endian;
uint8_t m_index;
};
inline bool operator==( const runtime_format& lhs, const runtime_format& rhs )
{
return lhs.index() == rhs.index();
}
inline bool operator!=( const runtime_format& lhs, const runtime_format& rhs )
{
return lhs.index() != rhs.index();
}
} // namespace pcm
namespace pcm
{
inline constexpr auto compiletime_formats()
{
return std::tuple<compiletime_format<signed_integer, _8bit, big_endian>,
compiletime_format<signed_integer, _8bit, little_endian>,
compiletime_format<signed_integer, _16bit, big_endian>,
compiletime_format<signed_integer, _16bit, little_endian>,
compiletime_format<signed_integer, _24bit, big_endian>,
compiletime_format<signed_integer, _24bit, little_endian>,
compiletime_format<signed_integer, _32bit, big_endian>,
compiletime_format<signed_integer, _32bit, little_endian>,
compiletime_format<signed_integer, _64bit, big_endian>,
compiletime_format<signed_integer, _64bit, little_endian>,
compiletime_format<unsigned_integer, _8bit, big_endian>,
compiletime_format<unsigned_integer, _8bit, little_endian>,
compiletime_format<unsigned_integer, _16bit, big_endian>,
compiletime_format<unsigned_integer, _16bit, little_endian>,
compiletime_format<unsigned_integer, _24bit, big_endian>,
compiletime_format<unsigned_integer, _24bit, little_endian>,
compiletime_format<unsigned_integer, _32bit, big_endian>,
compiletime_format<unsigned_integer, _32bit, little_endian>,
compiletime_format<unsigned_integer, _64bit, big_endian>,
compiletime_format<unsigned_integer, _64bit, little_endian>,
compiletime_format<floating_point, _32bit, big_endian>,
compiletime_format<floating_point, _32bit, little_endian>,
compiletime_format<floating_point, _64bit, big_endian>,
compiletime_format<floating_point, _64bit, little_endian>>();
}
inline auto runtime_formats()
{
static auto const fs = detail::tuple_to_array<runtime_format>( compiletime_formats() );
return fs;
}
} // namespace pcm
=> 24 formats
=> 576 conversions!
namespace pcm {
namespace detail {
template <typename Value, typename Iterator, typename Format>
Value read_impl( Iterator iter )
{
auto data = intermediate<Format>( iter );
return convert_to<Value>( data.value() );
}
template <typename Value, typename Iterator, typename... Ts>
auto make_read_impls( const std::tuple<Ts...>& ) -> std::array<Value ( * )( Iterator ), sizeof...( Ts )>
{
return {{&read_impl<Value, Iterator, Ts>...}};
}
} // namespace detail
template <typename Value, typename Iterator, number_type n, bitwidth_type b, endian_type e>
Value read( Iterator iter, const compiletime_format<n, b, e>& )
{
return detail::read_impl<Value, Iterator, compiletime_format<n, b, e>>( iter );
}
template <typename Value, typename Iterator, typename... Ts>
Value read( Iterator iter, const runtime_format& fmt )
{
static auto const impls = detail::make_read_impls<Value, Iterator>( std::tuple<Ts...>{} );
return impls.at( fmt.index() )( iter );
}
} // namespace pcm
namespace pcm {
namespace detail {
template <typename Value, typename Iterator, typename Format>
void write_impl( Iterator iter, Value val )
{
auto data = intermediate<Format>{convert_to<typename intermediate<Format>::value_type>( val )};
std::copy( data.begin(), data.end(), iter );
}
template <typename Value, typename Iterator, typename... Ts>
auto make_write_impls( const std::tuple<Ts...>& ) -> std::array<void ( * )( Iterator, Value ), sizeof...( Ts )>
{
return {{&write_impl<Value, Iterator, Ts>...}};
}
} // namespace detail
template <typename Value, typename Iterator, number_type n, bitwidth_type b, endian_type e>
void write( Iterator iter, Value val, const compiletime_format<n, b, e>& )
{
detail::write_impl<Value, Iterator, compiletime_format<n, b, e>>( iter, val );
}
template <typename Value, typename Iterator, typename... Ts>
void write( Iterator iter, Value val, const runtime_format& fmt )
{
static auto const impls = detail::make_write_impls<Value, Iterator>( std::tuple<Ts...>{} );
impls.at( fmt.index() )( iter, val );
}
} // namespace pcm
// floating point <- floating point
// static_cast
template <typename Target, typename Source>
Target convert_to( Source src )
{
return static_cast<Target>( src );
}
// fixed point <- floating point
// clamp, upscale, round_cast, sign_cast
template <typename Target, typename Source>
Target convert_to( Source src )
{
using boost::algorithm::clamp;
using SignedTarget = std::make_signed_t<Target>;
using PromotedSource = promote_t<Source, sizeof( Target ) * 8>;
static constexpr auto scale = PromotedSource{1ull << ( sizeof( Target ) * 8 - 1 )};
static constexpr auto lo = PromotedSource{-1};
static constexpr auto hi = ( scale - PromotedSource{1} ) / scale;
return sign_cast<Target>( round_cast<SignedTarget>( scale * clamp( PromotedSource{src}, lo, hi ) ) );
}
// floating point <- fixed point
// sign_cast + downscale
template <typename Target, typename Source>
Target convert_to( Source src )
{
using SignedSource = std::make_signed_t<Source>;
using PromotedTarget = promote_t<Target, sizeof( Source ) * 8>;
static constexpr auto scale = PromotedTarget{1} / ( 1ull << ( sizeof( Source ) * 8 - 1 ) );
return static_cast<Target>( scale * sign_cast<SignedSource>( src ) );
}
// fixed point <- fixed point
// sign_cast, shift_cast
template <typename Target, typename Source>
Target convert_to( Source src )
{
using SignAdjustedSource = std::conditional_t<std::is_signed<Target>::value, //
std::make_signed_t<Source>,
std::make_unsigned_t<Source>>;
return shift_cast<Target>( sign_cast<SignAdjustedSource>( src ) );
}
template <typename Value,
typename Iterator,
typename Format,
typename Category = typename std::iterator_traits<Iterator>::iterator_category>
class iterator : public boost::iterator_facade<iterator<Value, Iterator, Format, Category>,
Value,
Category,
iterator_reference_t<Value, Iterator, Format>>
{
public:
iterator() = default;
template <class OtherIterator,
class OtherFormat,
class = std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value
&& std::is_convertible<OtherFormat, Format>::value>>
iterator( const iterator<Value, OtherIterator, OtherFormat>& other )
: m_proxy( other.m_proxy )
{
}
iterator( Iterator iter, const Format& fmt )
: m_proxy( fmt, iter )
{
}
private:
void increment()
{
std::advance( m_proxy.iter, m_proxy.step() );
}
void decrement()
{
std::advance( m_proxy.iter, -m_proxy.step() );
}
void advance( difference_type offset )
{
std::advance( m_proxy.iter, offset * m_proxy.step() );
}
difference_type distance_to( const iterator& other ) const
{
return std::distance( m_proxy.iter, other.m_proxy.iter ) / m_proxy.step();
}
template <class OtherIterator,
class OtherFormat,
class = std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value
&& std::is_convertible<OtherFormat, Format>::value>>
bool equal( const iterator<Value, OtherIterator, OtherFormat>& other ) const
{
return equal_format( m_proxy.format(), other.m_proxy.format() ) && m_proxy.iter == other.m_proxy.iter;
}
reference dereference() const
{
return m_proxy;
}
friend class ::boost::iterator_core_access;
proxy_t m_proxy;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <class Value, class Iterator, class Format>
struct proxy : Format
{
proxy() = default;
proxy& operator=( Value val )
{
write( iter, val, format() );
return *this;
}
operator Value() const
{
return read<Value>( iter, format() );
}
private:
template <class OtherIterator,
class OtherFormat,
class = std::enable_if_t<std::is_convertible<OtherIterator, Iterator>::value
&& std::is_convertible<OtherFormat, Format>::value>>
proxy( const proxy<Value, OtherIterator, OtherFormat>& other )
: Format( other.format() )
, iter( other.iter )
{
}
proxy( const Format& fmt, Iterator it )
: Format( fmt )
, iter( it )
{
}
auto step() const -> typename std::iterator_traits<Iterator>::difference_type
{
return format().bitwidth() / 8;
}
const Format& format() const
{
return static_cast<const Format&>( *this );
}
Iterator iter;
};
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
std::copy( pcm::make_iterator<float>( in.begin(), format )
, pcm::make_iterator<float>( in.end(), format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
std::copy( in.begin()
, in.end()
, pcm::make_iterator<float>( out.begin(), format ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
std::copy( pcm::make_iterator<float>( in.begin(), format )
, pcm::make_iterator<float>( in.end(), format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
std::copy( in.begin()
, in.end()
, pcm::make_iterator<float>( out.begin(), format ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
boost::copy( in | pcm::converted_to<float>( format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
boost::copy( in
, std::begin( out | pcm::converted_to<float>( format ) ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
boost::copy( in | pcm::converted_to<float>( format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
boost::copy( in
, std::begin( out | pcm::converted_to<float>( format ) ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
std::copy( pcm::make_iterator<float>( in.begin(), format )
, pcm::make_iterator<float>( in.end(), format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
std::copy( in.begin()
, in.end()
, pcm::make_iterator<float>( out.begin(), format ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
std::copy( pcm::make_iterator<float>( in.begin(), format )
, pcm::make_iterator<float>( in.end(), format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
std::copy( in.begin()
, in.end()
, pcm::make_iterator<float>( out.begin(), format ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
pcm::copy( pcm::make_iterator<float>( in.begin(), format )
, pcm::make_iterator<float>( in.end(), format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
pcm::copy( in.begin()
, in.end()
, pcm::make_iterator<float>( out.begin(), format ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
pcm::copy( pcm::make_iterator<float>( in.begin(), format )
, pcm::make_iterator<float>( in.end(), format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
pcm::copy( in.begin()
, in.end()
, pcm::make_iterator<float>( out.begin(), format ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
boost::copy( in | pcm::converted_to<float>( format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
boost::copy( in
, std::begin( out | pcm::converted_to<float>( format ) ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
boost::copy( in | pcm::converted_to<float>( format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
boost::copy( in
, std::begin( out | pcm::converted_to<float>( format ) ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
pcm::copy( in | pcm::converted_to<float>( format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format(pcm::signed_integer, pcm::_16bit, pcm::little_endian);
pcm::copy( in
, std::begin( out | pcm::converted_to<float>( format ) ) );
}
{ // read pcm data
std::vector<char> in;
std::vector<float> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
pcm::copy( in | pcm::converted_to<float>( format )
, out.begin() );
}
{ // write pcm data
std::vector<float> in;
std::vector<char> out;
auto format = pcm::make_format<pcm::signed_integer, pcm::_16bit, pcm::little_endian>();
pcm::copy( in
, std::begin( out | pcm::converted_to<float>( format ) ) );
}
namespace pcm
{
template <class OutputIt, class Value, class Iterator>
auto copy( iterator<Value,Iterator,runtime_format> beg
, iterator<Value,Iterator,runtime_format> end
, OutputIt out )
{
assert ( beg.format() == end.format() );
auto fmt = beg.format();
if ( fmt == compiletime_format<signed_integer, _8bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _8bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _8bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _8bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _8bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _8bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _16bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _16bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _16bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _16bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _16bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _16bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _24bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _24bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _24bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _24bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _24bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _24bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _32bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _32bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _32bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _32bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _32bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _32bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _64bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _64bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _64bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<signed_integer, _64bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<signed_integer, _64bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<signed_integer, _64bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _8bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _8bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _8bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _8bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _8bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _8bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _16bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _16bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _16bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _16bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _16bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _16bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _24bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _24bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _24bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _24bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _24bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _24bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _32bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _32bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _32bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _32bit, little_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _32bit, little_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _32bit, little_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _64bit, big_endian>{} )
return std::copy( make_iterator<Value>( beg.base(), compiletime_format<unsigned_integer, _64bit, big_endian>{} )
, make_iterator<Value>( end.base(), compiletime_format<unsigned_integer, _64bit, big_endian>{} )
, out );
else if ( fmt == compiletime_format<unsigned_integer, _64bit, little_endian>{} )
.
.
.
}
} // namespace pcm
namespace pcm
{
template <class InputIt, class Value, class Iterator>
auto copy( InputIt beg
, InputIt end
, iterator<Value,Iterator, runtime_format> out )
{
auto out = beg.format();
if ( fmt == compiletime_format<signed_integer, _8bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _8bit, big_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _8bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _8bit, little_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _16bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _16bit, big_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _16bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _16bit, little_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _24bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _24bit, big_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _24bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _24bit, little_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _32bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _32bit, big_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _32bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _32bit, little_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _64bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _64bit, big_endian>{} ) );
else if ( fmt == compiletime_format<signed_integer, _64bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<signed_integer, _64bit, little_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _8bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _8bit, big_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _8bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _8bit, little_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _16bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _16bit, big_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _16bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _16bit, little_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _24bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _24bit, big_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _24bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _24bit, little_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _32bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _32bit, big_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _32bit, little_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _32bit, little_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _64bit, big_endian>{} )
return std::copy( beg
, end
, make_iterator<Value>( out.base(), compiletime_format<unsigned_integer, _64bit, big_endian>{} ) );
else if ( fmt == compiletime_format<unsigned_integer, _64bit, little_endian>{} )
.
.
.
}
} // namespace pcm
namespace pcm
{
namespace detail
{
struct copy_impl
{
template <class InputIt, class OutputIt>
OutputIt operator()( InputIt beg, InputIt end, OutputIt out ) const
{
return std::copy( beg, end, out );
}
};
} // namespace detail
// iterator based
template <class InputIt, class OutputIt>
auto copy( InputIt beg, InputIt end, OutputIt out )
{
return dispatch( detail::copy_impl{}, beg, end, out );
}
// range based
template <class InputRange, class OutputIt>
auto copy( const InputRange& range, OutputIt out )
{
return ::pcm::copy( std::begin( range ), std::end( range ), out );
}
} // namespace pcm
namespace pcm
{
namespace detail
{
struct copy_n_impl
{
template <class InputIt, class Size, class OutputIt>
OutputIt operator()( InputIt first, Size count, OutputIt result ) const
{
return std::copy_n( first, count, result );
}
};
} // namespace detail
template <class InputIt, class Size, class OutputIt>
OutputIt copy_n( InputIt first, Size count, OutputIt result )
{
return dispatch( detail::copy_n_impl{}, first, count, result );
}
} // namespace pcm
namespace pcm { namespace detail {
struct catch_t{};
struct try_t : catch_t{};
template <class Result, class F>
auto invoke( try_t, F f, Ts... ts ) -> decltype( f( ts... ), Result() )
{
return f( ts... );
}
template <class Result, class F>
Result invoke( catch_t, F, Ts... )
{
throw std::runtime_error( "runtime argument mismatch" );
}
template <class...>
struct dispatch_impl{};
// Base case
template <class R, class F, class... Bs, class... Fs>
struct dispatch_impl<R, F, std::tuple<>, std::tuple<Bs...>, std::tuple<Fs...>>
{
auto operator()( F f, Bs... bs )
{
return invoke<R>( try_t{}, f, bs... );
}
};
// Recursive case without dispatch
template <class R, class F, class A, class... As, class... Bs, class... Fs>
struct dispatch_impl<R, F, std::tuple<A, As...>, std::tuple<Bs...>, std::tuple<Fs...>>
{
auto operator()( F f, A a, As... as, Bs... bs )
{
auto impl = dispatch_impl<R, F, std::tuple<As...>, std::tuple<Bs..., A>, std::tuple<Fs...>>();
return impl( f, as..., bs..., a );
}
};
// Recursive case, with dispatch, with return type
template <class R, class F, class V, class I, class... As, class... Bs, class... Fs>
struct dispatch_impl<R, F, std::tuple<iterator<V, I>, As...>, std::tuple<Bs...>, std::tuple<Fs...>>
{
auto operator()( F f, iterator<V, I> it, As... as, Bs... bs )
{
R r;
[]( ... ) {}( it.format() == Fs{}
&& ( r = ( dispatch_impl<R,
F,
std::tuple<As...>,
std::tuple<Bs..., iterator<V, I, Fs>>,
std::tuple<Fs...>>()(
f, as..., bs..., make_iterator<V>( it.base(), Fs{} ) ) ),
false )... );
return r;
}
};
// Recursive case, with dispatch, without return type
template <class F, class V, class I, class... As, class... Bs, class... Fs>
struct dispatch_impl<void, F, std::tuple<iterator<V, I>, As...>, std::tuple<Bs...>, std::tuple<Fs...>>
{
auto operator()( F f, iterator<V, I> it, As... as, Bs... bs )
{
[]( ... ) {}( it.format() == Fs{}
&& ( dispatch_impl<void,
F,
std::tuple<As...>,
std::tuple<Bs..., iterator<V, I, Fs>>,
std::tuple<Fs...>>()(
f, as..., bs..., make_iterator<V>( it.base(), Fs{} ) ),
false )... );
}
};
} // namespace detail
template <class F, class... Ts>
auto dispatch( F f, Ts... ts )
{
using Result = decltype( f( ts... ) );
using Formats = decltype( compiletime_formats() );
auto impl = detail::dispatch_impl<Result, F, std::tuple<Ts...>, std::tuple<>, Formats>();
return impl( f, ts... );
}
} // namespace pcm
template <class Range>
auto istream::operator>>( Range&& rng ) -> std::enable_if_t<boost::has_range_iterator<Range>::value, istream&>
{
using Value = typename boost::range_value<Range>::type;
using Difference = typename boost::range_difference<Range>::type;
auto beg = std::begin( rng );
auto end = std::end( rng );
const auto samples_requested = std::distance( beg, end );
const auto samples_available = Difference( m_info->num_samples() - sample_tellg() );
auto iter = pcm::make_iterator<Value>( std::istreambuf_iterator<char>( rdbuf() ), m_info->format() );
std::fill( pcm::copy_n( iter, std::min( samples_requested, samples_available ), beg ), end, Value{} );
if ( samples_available < samples_requested )
setstate( rdstate() | eofbit );
return *this;
}
template <class Range>
auto istream::operator>>( Range&& rng ) -> std::enable_if_t<boost::has_range_iterator<Range>::value, istream&>
{
using Value = typename boost::range_value<Range>::type;
using Difference = typename boost::range_difference<Range>::type;
auto beg = std::begin( rng );
auto end = std::end( rng );
const auto samples_requested = std::distance( beg, end );
const auto samples_available = Difference( m_info->num_samples() - sample_tellg() );
auto iter = pcm::make_iterator<Value>( std::istreambuf_iterator<char>( rdbuf() ), m_info->format() );
std::fill( pcm::copy_n( iter, std::min( samples_requested, samples_available ), beg ), end, Value{} );
if ( samples_available < samples_requested )
setstate( rdstate() | eofbit );
return *this;
}
template <class Range>
auto istream::operator>>( Range&& rng ) -> std::enable_if_t<boost::has_range_iterator<Range>::value, istream&>
{
using Value = typename boost::range_value<Range>::type;
using Difference = typename boost::range_difference<Range>::type;
auto beg = std::begin( rng );
auto end = std::end( rng );
const auto samples_requested = std::distance( beg, end );
const auto samples_available = Difference( m_info->num_samples() - sample_tellg() );
auto iter = pcm::make_iterator<Value>( std::istreambuf_iterator<char>( rdbuf() ), m_info->format() );
std::fill( pcm::copy_n( iter, std::min( samples_requested, samples_available ), beg ), end, Value{} );
if ( samples_available < samples_requested )
setstate( rdstate() | eofbit );
return *this;
}
template <class Range>
auto istream::operator>>( Range&& rng ) -> std::enable_if_t<boost::has_range_iterator<Range>::value, istream&>
{
using Value = typename boost::range_value<Range>::type;
using Difference = typename boost::range_difference<Range>::type;
auto beg = std::begin( rng );
auto end = std::end( rng );
const auto samples_requested = std::distance( beg, end );
const auto samples_available = Difference( m_info->num_samples() - sample_tellg() );
auto iter = pcm::make_iterator<Value>( std::istreambuf_iterator<char>( rdbuf() ), m_info->format() );
std::fill( pcm::copy_n( iter, std::min( samples_requested, samples_available ), beg ), end, Value{} );
if ( samples_available < samples_requested )
setstate( rdstate() | eofbit );
return *this;
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.aiff");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.flac");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.ogg");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.mp3");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.mp4");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<float>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<double>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<int8_t>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<uint8_t>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<int16_t>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<uint16_t>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<int32_t>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<uint32_t>(1024 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<uint32_t>(256 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::vector<uint32_t>(42 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = std::list<uint32_t>(42 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}
#include <ni/media/audio/ifstream.h>
#include <vector>
int main()
{
auto stream = audio::ifstream("hello.wav");
auto samples = my::array<uint32_t>(42 * stream.info().num_channels());
while(stream >> samples)
process(samples);
}