libopenmpt C++ uses C++ exception handling for errror reporting.
Unless otherwise noted, any libopenmpt function may throw exceptions and all exceptions thrown by libopenmpt itself are derived from openmpt::exception. In addition, any libopenmpt function may also throw any exception specified by the C++ language and C++ standard library. These are all derived from std::exception.
libopenmpt can use 3 different strategies for file I/O.
In all cases, the data or stream passed to the constructor is no longer needed after the openmpt::module has been constructed and can be destroyed by the caller.
libopenmpt supports a wide range of PCM output formats: [8000..192000]/[mono|stereo|quad]/[f32|i16].
Unless you have some very specific requirements demanding a particular aspect of the output format, you should always prefer 48000/stereo/f32 as the libopenmpt PCM format.
Using the libopenmpt C++ API when libopenmpt is compiled as a DLL on Windows requires #define LIBOPENMPT_USE_DLL
(or some equivalent build system configuration) before #include <libopenmpt/libopenmpt.hpp>
in order to correctly import the symbols from the DLL.
#if defined( __MINGW32__ ) && !defined( __MINGW64__ )
#include <sys/types.h>
#endif
#include <exception>
#include <fstream>
#include <iostream>
#include <new>
#include <stdexcept>
#include <vector>
#if defined( __clang__ )
#if ( ( __clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__ ) >= 40000 )
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
#endif
#endif
#include <portaudiocpp/PortAudioCpp.hxx>
#if defined( __clang__ )
#if ( ( __clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__ ) >= 40000 )
#pragma clang diagnostic pop
#endif
#endif
#if defined( __DJGPP__ )
#include <crt0.h>
#endif
#if defined( __DJGPP__ )
extern "C" int _crt0_startup_flags = 0
| _CRT0_FLAG_NONMOVE_SBRK
| _CRT0_DISABLE_SBRK_ADDRESS_WRAP
| _CRT0_FLAG_LOCK_MEMORY
| 0;
#endif
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
#if defined( __GNUC__ ) || ( defined( __clang__ ) && !defined( _MSC_VER ) )
extern "C" int wmain( int , wchar_t * [] );
extern "C" int wmain( int argc, wchar_t * argv[] ) {
#else
int wmain( int argc, wchar_t * argv[] ) {
#endif
#else
int main( int argc, char * argv[] ) {
#endif
#if defined( __DJGPP__ )
_crt0_startup_flags &= ~_CRT0_FLAG_LOCK_MEMORY;
#endif
try {
if ( argc != 2 ) {
throw std::runtime_error( "Usage: libopenmpt_example_cxx SOMEMODULE" );
}
constexpr std::size_t buffersize = 480;
constexpr std::int32_t samplerate = 48000;
std::ifstream file( argv[1], std::ios::binary );
portaudio::AutoSystem portaudio_initializer;
portaudio::System & portaudio = portaudio::System::instance();
std::vector<float> left( buffersize );
std::vector<float> right( buffersize );
std::vector<float> interleaved_buffer( buffersize * 2 );
bool is_interleaved = false;
#if defined( _MSC_VER ) && defined( _PREFAST_ )
is_interleaved = false;
portaudio::DirectionSpecificStreamParameters outputstream_parameters( portaudio.defaultOutputDevice(), 2, portaudio::FLOAT32, false, portaudio.defaultOutputDevice().defaultHighOutputLatency(), 0 );
portaudio::StreamParameters stream_parameters( portaudio::DirectionSpecificStreamParameters::null(), outputstream_parameters, samplerate, paFramesPerBufferUnspecified, paNoFlag );
portaudio::BlockingStream stream( stream_parameters );
#else
portaudio::BlockingStream stream = [&]()
{
try {
is_interleaved = false;
portaudio::DirectionSpecificStreamParameters outputstream_parameters( portaudio.defaultOutputDevice(), 2, portaudio::FLOAT32, false, portaudio.defaultOutputDevice().defaultHighOutputLatency(), 0 );
portaudio::StreamParameters stream_parameters( portaudio::DirectionSpecificStreamParameters::null(), outputstream_parameters, samplerate, paFramesPerBufferUnspecified, paNoFlag );
return portaudio::BlockingStream( stream_parameters );
} catch ( const portaudio::PaException & e ) {
if ( e.paError() != paSampleFormatNotSupported ) {
throw;
}
is_interleaved = true;
portaudio::DirectionSpecificStreamParameters outputstream_parameters( portaudio.defaultOutputDevice(), 2, portaudio::FLOAT32, true, portaudio.defaultOutputDevice().defaultHighOutputLatency(), 0 );
portaudio::StreamParameters stream_parameters( portaudio::DirectionSpecificStreamParameters::null(), outputstream_parameters, samplerate, paFramesPerBufferUnspecified, paNoFlag );
return portaudio::BlockingStream( stream_parameters );
}
}();
#endif
stream.start();
while ( true ) {
std::size_t count = is_interleaved ? mod.read_interleaved_stereo( samplerate, buffersize, interleaved_buffer.data() ) : mod.read( samplerate, buffersize, left.data(), right.data() );
if ( count == 0 ) {
break;
}
try {
if ( is_interleaved ) {
stream.write( interleaved_buffer.data(), static_cast<unsigned long>( count ) );
} else {
const float * const buffers[2] = { left.data(), right.data() };
stream.write( buffers, static_cast<unsigned long>( count ) );
}
} catch ( const portaudio::PaException & pa_exception ) {
if ( pa_exception.paError() != paOutputUnderflowed ) {
throw;
}
}
}
stream.stop();
} catch ( const std::bad_alloc & ) {
std::cerr << "Error: " << std::string( "out of memory" ) << std::endl;
return 1;
} catch ( const std::exception & e ) {
std::cerr << "Error: " << std::string( e.what() ? e.what() : "unknown error" ) << std::endl;
return 1;
}
return 0;
}
Definition: libopenmpt.hpp:400