libopenmpt  0.2.5787-autotools
cross-platform C++ and C library to decode tracked music files
C API

Error Handling

  • Functions with no return value in the corresponding C++ API return 0 on failure and 1 on success.
  • Functions that return a string in the corresponding C++ API return a dynamically allocated const char *. I case of failure or memory allocation failure, a NULL pointer is returned.
  • Functions that return integer values signal error condition by returning an invalid value (-1 in most cases, 0 in some cases).

Strings

  • All strings returned from libopenmpt are encoded in UTF-8.
  • All strings passed to libopenmpt should also be encoded in UTF-8. Behaviour in case of invalid UTF-8 is unspecified.
  • libopenmpt does not enforce or expect any particular unicode normalization form.
  • All strings returned from libopenmpt are dynamically allocated and must be freed with openmpt_free_string(). Do NOT use the C standard library free() for libopenmpt strings as that would make your code invalid on windows when dynamically linking against libopenmpt which itself statically links to the C runtime.
  • All strings passed to libopenmpt are copied. No ownership is assumed or transferred.

Detailed documentation

libopenmpt C

In case a function is not documented here, you might want to look at the libopenmpt C++ documentation. The C and C++ APIs are kept semantically as close as possible.

Examples

Unsafe, simplified example without any error checking to get a first idea of the API

/*
* libopenmpt_example_c_unsafe.c
* -----------------------------
* Purpose: libopenmpt C API simplified example
* Notes : PortAudio is used for sound output.
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
/*
* Usage: libopenmpt_example_c_unsafe SOMEMODULE
* CAUTION: This simple example does no error cheking at all.
*/
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <portaudio.h>
#define BUFFERSIZE 480
#define SAMPLERATE 48000
static int16_t left[BUFFERSIZE];
static int16_t right[BUFFERSIZE];
static int16_t * const buffers[2] = { left, right };
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
int wmain( int argc, wchar_t * argv[] ) {
#else
int main( int argc, char * argv[] ) {
#endif
FILE * file = 0;
openmpt_module * mod = 0;
size_t count = 0;
PaStream * stream = 0;
(void)argc;
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
file = _wfopen( argv[1], L"rb" );
#else
file = fopen( argv[1], "rb" );
#endif
mod = openmpt_module_create( openmpt_stream_get_file_callbacks(), file, NULL, NULL, NULL );
fclose( file );
Pa_Initialize();
Pa_OpenDefaultStream( &stream, 0, 2, paInt16 | paNonInterleaved, SAMPLERATE, paFramesPerBufferUnspecified, NULL, NULL );
Pa_StartStream( stream );
while ( 1 ) {
count = openmpt_module_read_stereo( mod, SAMPLERATE, BUFFERSIZE, left, right );
if ( count == 0 ) {
break;
}
Pa_WriteStream( stream, buffers, (unsigned long)count );
}
Pa_StopStream( stream );
Pa_CloseStream( stream );
Pa_Terminate();
return 0;
}

FILE*

/*
* libopenmpt_example_c.c
* ----------------------
* Purpose: libopenmpt C API example
* Notes : PortAudio is used for sound output.
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
/*
* Usage: libopenmpt_example_c SOMEMODULE
*/
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <portaudio.h>
#define BUFFERSIZE 480
#define SAMPLERATE 48000
static int16_t left[BUFFERSIZE];
static int16_t right[BUFFERSIZE];
static int16_t * const buffers[2] = { left, right };
static void libopenmpt_example_logfunc( const char * message, void * userdata ) {
(void)userdata;
if ( message ) {
fprintf( stderr, "%s\n", message );
}
}
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
int wmain( int argc, wchar_t * argv[] ) {
#else
int main( int argc, char * argv[] ) {
#endif
int result = 0;
FILE * file = 0;
openmpt_module * mod = 0;
size_t count = 0;
PaError pa_error = paNoError;
int pa_initialized = 0;
PaStream * stream = 0;
if ( argc != 2 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c SOMEMODULE'." );
goto fail;
}
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
if ( wcslen( argv[1] ) == 0 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c SOMEMODULE'." );
goto fail;
}
file = _wfopen( argv[1], L"rb" );
#else
if ( strlen( argv[1] ) == 0 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c SOMEMODULE'." );
goto fail;
}
file = fopen( argv[1], "rb" );
#endif
if ( !file ) {
fprintf( stderr, "Error: %s\n", "fopen() failed." );
goto fail;
}
mod = openmpt_module_create( openmpt_stream_get_file_callbacks(), file, &libopenmpt_example_logfunc, NULL, NULL );
if ( !mod ) {
fprintf( stderr, "Error: %s\n", "openmpt_module_create() failed." );
goto fail;
}
pa_error = Pa_Initialize();
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_Initialize() failed." );
goto fail;
}
pa_initialized = 1;
pa_error = Pa_OpenDefaultStream( &stream, 0, 2, paInt16 | paNonInterleaved, SAMPLERATE, paFramesPerBufferUnspecified, NULL, NULL );
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_OpenStream() failed." );
goto fail;
}
if ( !stream ) {
fprintf( stderr, "Error: %s\n", "Pa_OpenStream() failed." );
goto fail;
}
pa_error = Pa_StartStream( stream );
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_StartStream() failed." );
goto fail;
}
while ( 1 ) {
count = openmpt_module_read_stereo( mod, SAMPLERATE, BUFFERSIZE, left, right );
if ( count == 0 ) {
break;
}
pa_error = Pa_WriteStream( stream, buffers, (unsigned long)count );
if ( pa_error == paOutputUnderflowed ) {
pa_error = paNoError;
}
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_WriteStream() failed." );
goto fail;
}
}
result = 0;
goto cleanup;
fail:
result = 1;
cleanup:
if ( stream ) {
if ( Pa_IsStreamActive( stream ) == 1 ) {
Pa_StopStream( stream );
}
Pa_CloseStream( stream );
stream = 0;
}
if ( pa_initialized ) {
Pa_Terminate();
pa_initialized = 0;
}
if ( mod ) {
mod = 0;
}
if ( file ) {
fclose( file );
file = 0;
}
return result;
}

in memory

/*
* libopenmpt_example_c_mem.c
* --------------------------
* Purpose: libopenmpt C API example
* Notes : PortAudio is used for sound output.
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
/*
* Usage: libopenmpt_example_c_mem SOMEMODULE
*/
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <portaudio.h>
#define BUFFERSIZE 480
#define SAMPLERATE 48000
static int16_t left[BUFFERSIZE];
static int16_t right[BUFFERSIZE];
static int16_t * const buffers[2] = { left, right };
static void libopenmpt_example_logfunc( const char * message, void * userdata ) {
(void)userdata;
if ( message ) {
fprintf( stderr, "%s\n", message );
}
}
typedef struct blob_t {
size_t size;
void * data;
} blob_t;
static void free_blob( blob_t * blob ) {
if ( blob ) {
if ( blob->data ) {
free( blob->data );
blob->data = 0;
}
blob->size = 0;
free( blob );
}
}
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
static blob_t * load_file( const wchar_t * filename ) {
#else
static blob_t * load_file( const char * filename ) {
#endif
blob_t * result = 0;
blob_t * blob = 0;
FILE * file = 0;
long tell_result = 0;
blob = malloc( sizeof( blob_t ) );
if ( !blob ) {
goto fail;
}
memset( blob, 0, sizeof( blob_t ) );
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
file = _wfopen( filename, L"rb" );
#else
file = fopen( filename, "rb" );
#endif
if ( !file ) {
goto fail;
}
if ( fseek( file, 0, SEEK_END ) != 0 ) {
goto fail;
}
tell_result = ftell( file );
if ( tell_result < 0 ) {
goto fail;
}
if ( (unsigned long)tell_result > SIZE_MAX ) {
goto fail;
}
blob->size = (size_t)tell_result;
if ( fseek( file, 0, SEEK_SET ) != 0 ) {
goto fail;
}
blob->data = malloc( blob->size );
if ( !blob->data ) {
goto fail;
}
memset( blob->data, 0, blob->size );
if ( fread( blob->data, 1, blob->size, file ) != blob->size ) {
goto fail;
}
result = blob;
blob = 0;
goto cleanup;
fail:
result = 0;
cleanup:
if ( blob ) {
free_blob( blob );
blob = 0;
}
if ( file ) {
fclose( file );
file = 0;
}
return result;
}
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
int wmain( int argc, wchar_t * argv[] ) {
#else
int main( int argc, char * argv[] ) {
#endif
int result = 0;
blob_t * blob = 0;
openmpt_module * mod = 0;
size_t count = 0;
PaError pa_error = paNoError;
int pa_initialized = 0;
PaStream * stream = 0;
if ( argc != 2 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c_mem SOMEMODULE'." );
goto fail;
}
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
if ( wcslen( argv[1] ) == 0 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c_mem SOMEMODULE'." );
goto fail;
}
#else
if ( strlen( argv[1] ) == 0 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c_mem SOMEMODULE'." );
goto fail;
}
#endif
blob = load_file( argv[1] );
if ( !blob ) {
fprintf( stderr, "Error: %s\n", "load_file() failed." );
goto fail;
}
mod = openmpt_module_create_from_memory( blob->data, blob->size, &libopenmpt_example_logfunc, NULL, NULL );
if ( !mod ) {
fprintf( stderr, "Error: %s\n", "openmpt_module_from_memory() failed." );
goto fail;
}
pa_error = Pa_Initialize();
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_Initialize() failed." );
goto fail;
}
pa_initialized = 1;
pa_error = Pa_OpenDefaultStream( &stream, 0, 2, paInt16 | paNonInterleaved, SAMPLERATE, paFramesPerBufferUnspecified, NULL, NULL );
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_OpenStream() failed." );
goto fail;
}
if ( !stream ) {
fprintf( stderr, "Error: %s\n", "Pa_OpenStream() failed." );
goto fail;
}
pa_error = Pa_StartStream( stream );
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_StartStream() failed." );
goto fail;
}
while ( 1 ) {
count = openmpt_module_read_stereo( mod, SAMPLERATE, BUFFERSIZE, left, right );
if ( count == 0 ) {
break;
}
pa_error = Pa_WriteStream( stream, buffers, (unsigned long)count );
if ( pa_error == paOutputUnderflowed ) {
pa_error = paNoError;
}
if ( pa_error != paNoError ) {
fprintf( stderr, "Error: %s\n", "Pa_WriteStream() failed." );
goto fail;
}
}
result = 0;
goto cleanup;
fail:
result = 1;
cleanup:
if ( stream ) {
if ( Pa_IsStreamActive( stream ) == 1 ) {
Pa_StopStream( stream );
}
Pa_CloseStream( stream );
stream = 0;
}
if ( pa_initialized ) {
Pa_Terminate();
pa_initialized = 0;
}
if ( mod ) {
mod = 0;
}
if ( blob ) {
free_blob( blob );
blob = 0;
}
return result;
}

reading FILE* and writing PCM data to STDOUT (usable without PortAudio)

/*
* libopenmpt_example_c_stdout.c
* -----------------------------
* Purpose: libopenmpt C API simple example
* Notes : This example writes raw 48000Hz / stereo / 16bit native endian PCM data to stdout.
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
/*
* Usage: libopenmpt_example_c_stdout SOMEMODULE | aplay --file-type raw --format=dat
*/
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define BUFFERSIZE 480
#define SAMPLERATE 48000
static void libopenmpt_example_logfunc( const char * message, void * userdata ) {
(void)userdata;
if ( message ) {
fprintf( stderr, "%s\n", message );
}
}
static ssize_t xwrite( int fd, const void * buffer, size_t size ) {
size_t written = 0;
ssize_t retval = 0;
while ( written < size ) {
retval = write( fd, (const char *)buffer + written, size - written );
if ( retval < 0 ) {
if ( errno != EINTR ) {
break;
}
retval = 0;
}
written += retval;
}
return written;
}
static int16_t buffer[BUFFERSIZE * 2];
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
int wmain( int argc, wchar_t * argv[] ) {
#else
int main( int argc, char * argv[] ) {
#endif
int result = 0;
FILE * file = 0;
openmpt_module * mod = 0;
size_t count = 0;
size_t written = 0;
if ( argc != 2 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c_stdout SOMEMODULE'." );
goto fail;
}
#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
if ( wcslen( argv[1] ) == 0 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c_stdout SOMEMODULE'." );
goto fail;
}
file = _wfopen( argv[1], L"rb" );
#else
if ( strlen( argv[1] ) == 0 ) {
fprintf( stderr, "Error: %s\n", "Wrong invocation. Use 'libopenmpt_example_c_stdout SOMEMODULE'." );
goto fail;
}
file = fopen( argv[1], "rb" );
#endif
if ( !file ) {
fprintf( stderr, "Error: %s\n", "fopen() failed." );
goto fail;
}
mod = openmpt_module_create( openmpt_stream_get_file_callbacks(), file, &libopenmpt_example_logfunc, NULL, NULL );
if ( !mod ) {
fprintf( stderr, "Error: %s\n", "openmpt_module_create() failed." );
goto fail;
}
while ( 1 ) {
count = openmpt_module_read_interleaved_stereo( mod, SAMPLERATE, BUFFERSIZE, buffer );
if ( count == 0 ) {
break;
}
written = xwrite( STDOUT_FILENO, buffer, count * 2 * sizeof( int16_t ) );
if ( written == 0 ) {
fprintf( stderr, "Error: %s\n", "write() failed." );
goto fail;
}
}
result = 0;
goto cleanup;
fail:
result = 1;
cleanup:
if ( mod ) {
mod = 0;
}
if ( file ) {
fclose( file );
file = 0;
}
return result;
}