audio::ifstream
The base class for all audio file input streaming. Inherits from audio::istream
.
Similar to std::ifstrem
, its contructor takes a filepath as argument. Here the filepath must point to an audio file currently supported by ni-media. At this date supported containers are:
NIMEDIA_ENABLE_WAV_DECODING
NIMEDIA_ENABLE_AIFF_DECODING
NIMEDIA_ENABLE_FLAC_DECODING
NIMEDIA_ENABLE_OGG_DECODING
NIMEDIA_ENABLE_MP3_DECODING
NIMEDIA_ENABLE_MP4_DECODING
The constructor will throw a runtime error if the file format is not supported or a codec error occured (e.g. corrupted file).
Example code:
void analyze_file( const std::string& filename )
{
audio::ifstream stream;
try
{
stream = audio::ifstream( filename );
}
catch ( ... )
{
// handle exception
return;
}
// stream from file...
}
You can also allow only a specific container:
void analyze_wav_file( const std::string& filename )
{
audio::ifstream stream;
try
{
stream = audio::ifstream( filename, audio::ifstream::info_type::container_type::wav );
}
catch ( ... )
{
// handle exception
return;
}
// stream from file...
}
An audio::ifstream
also supports multi stream containers, which allows us to stream from e.g. a Native Instruments Stems file. A stem file consists of five audio streams and additional metadata packed inside an mp4 container.
By default, an audio::ifstream
will open the Stems Master Stream, but is also capable of opening any of the other streams by simply passing the desired stream index as argument to the constructor:
void analyze_stem_stream( const std::string& filename, size_t stream_index )
{
audio::ifstream stream;
try
{
stream = audio::ifstream( filename, audio::ifstream::info_type::container_type::mp4, stream_index );
}
catch ( ... )
{
// handle exception
return;
}
// stream from file...
}
info()
: returns the stream info audio::ifstream_info
Extends audio::istream_info
with audio file specific informations like:
num_frames
: the number of sample frames ( one frame consist of num_channels samples )container
: the underlying container( wav, aiff, flac, ogg, mp3, mp4 )codec
: the codec used: ( wav, aiff, flac, vorbis, mp3, aac, alac )⚠️ num_frames
may differ from the actual number of frames in the stream as this information relies on the codec.
The only way to obtain the exact number of frames is by seeking to the end of stream and retrieving the frame position.
In general the num_frames
info provided by the codec is correct for wav, aiff, flac, ogg, mp4 containers ( assuming no errors occured during encoding ). For mp3 num_frames
might be off by up to a few thousand frames.
It is possible to extend ni-media
from the outside by implementing the audio::istream_source
interface. For convenience a specialized audio::ifstream_source
for audio::ifstream
is already defined in ifstream.h
which your decoder stream can implement like this:
#include <ni/media/audio/ifstream.h>
class my_ifstream_source : public audio::ifstream_source
{
std::streampos seek( std::streamoff off, std::ios_base::seekdir dir ) override;
std::streamsize read( char_type* dst, std::streamsize size ) override;
const info_type& info() const override;
}
In this case the char_type
will refer to std::istream::char_type
and the info_type
to audio::ifstream_info
.
Best practice to instantiate an audio::ifstream
based on an audio::ifstream_source
implementation is to use the following factory function which will forward your constructor arguments and use the appropriate constructor of ni-media
:
audio::ifstream my_ifstream = audio::make_ifstream<my_ifstream_source>( ... );
By implementing the audio::custom_backend_source
interface, it is possible to provide a custom byte-stream backend to the existing decoders of ni-media
:
#include <ni/media/audio/custom_backend_source.h>
class my_custom_byte_stream : public audio::custom_backend_source
{
std::streampos seek( std::streamoff off, std::ios_base::seekdir dir ) override;
std::streamsize read( char_type* dst, std::streamsize size ) override;
}
An audio::ifstream
based on a audio::custom_backend_source
can be instantiated with the following constructor:
ifstream( std::unique_ptr<audio::custom_backend_source> source, info_type::container_type container, size_t stream_index = 0 );