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
#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;
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
fclose( file );
Pa_Initialize();
Pa_OpenDefaultStream( &stream, 0, 2, paInt16 | paNonInterleaved, SAMPLERATE, paFramesPerBufferUnspecified, NULL, NULL );
Pa_StartStream( stream );
while ( 1 ) {
if ( count == 0 ) {
break;
}
Pa_WriteStream( stream, buffers, (unsigned long)count );
}
Pa_StopStream( stream );
Pa_CloseStream( stream );
Pa_Terminate();
return 0;
}
FILE*
#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;
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;
}
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 ) {
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
#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;
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;
}
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 ) {
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)
#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;
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;
}
if ( !mod ) {
fprintf( stderr, "Error: %s\n", "openmpt_module_create() failed." );
goto fail;
}
while ( 1 ) {
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;
}