Mdxmini
Simple-to-use C library to play X68000 MDX chiptunes
Install / Use
/learn @mistydemeo/MdxminiREADME
mdxmini
mdxmini is a C library with a simple API which can play back MDX chiptunes from the X68000 home computer. The X68000 was, for its time, an advanced 16-bit computer with excellent multimedia support; its 8-channel YM2151 sound chip and 1-channel PCM chip gave it excellent music support. A large number of MDX files can be found at the Fossil of FM-sound era MDX archive site.
Usage
Detailed API documentation is available in the mdxmini.h header file, but the following sample program shows how to use mdxmini to open a file, extract some metadata, and play back music:
// Initializes the t_mdxmini struct and opens the file from disk.
// The `path_to_samples` argument is the path to the directory containing the song's
// .pdx files, if any; this can be NULL.
t_mdxmini data;
int success = mdx_open(&data, path_to_file, path_to_samples);
// The return value of mdx_open indicates whether or not the file was opened correctly.
if (success == -1) {
fprintf(stderr, "Failed to open input file: %s\n", path_to_file);
return 1;
}
// Before playback begins, call mdx_set_rate to set the preferred sampling rate
// for generated audio.
int playback_rate = 48000;
mdx_set_rate(playback_rate);
// Get the song duration, in whole seconds.
int length = mdx_get_length(&data);
printf("Song length: %i seconds\n", length);
// mdx_get_title allows the song's title to be fetched; this is usually
// encoded in Shift-JIS.
char title[MDX_MAX_TITLE_LENGTH];
mdx_get_title(&data, title);
printf("Title: %s\n", title);
// For playback, define a buffer into which we'll render raw PCM data.
int buf_len = 8192;
short buf[buf_len];
// Number of channels, which we'll fetch for display later.
// This is constant for a given song, so just fetch it once.
int number_of_channels = mdx_get_tracks(&data);
printf("Number of channels: %i\n", number_of_channels);
// A buffer into which we'll write information about the notes being
// played in a given frame. 16 is the maximum number of channels supported by MDX
// (8 FM channels, up to 8 PCM channels).
int notes[16];
int position;
// mdx_calc_sample will return 0 when the final frame of the song is reached.
int are_samples_remaining = 1;
// Track the number of buffers played so far, which is useful to calculate
// the current position.
int played_buffers = 0;
// The playback loop!
while (are_samples_remaining == 1)
{
// Calculate the song position based on the buffer size and frequency.
position = played_buffers / (((playback_rate * 16 * 2) / 8) / (buf_len * 2));
printf("Current position: %i / %i\n", position, length);
are_samples_remaining = mdx_calc_sample(&data, buf, buf_len / 2);
// Also useful to check the position against the reported duration,
// as the song may not terminate itself if it can loop infinitely.
if (position >= length) {
are_samples_remaining = 0;
}
// Do something with the calculated sample here; this is platform-dependent,
// so this intro will omit it.
// Fill the note buffer with information about the notes in the current frame
mdx_get_current_notes(&data, notes, number_of_channels);
// Channels 0 through 7 are FM channels; any MDX file will always have these tracks.
// The integers for these channels represents a note, divided into standard octaves of 12;
// for example, 0 would be C in the lowest octave, and 24 would be C two octaves up.
// These values can be useful for visualizations;
// for example, the ruby-mdxplay demo program maps these values to piano keys:
// https://github.com/mistydemeo/ruby-mdxplay/blob/8f54c28cefcfcbdee70eca35ca9a93187385eb8f/bin/mdxplay#L93-L175
for (int i = 0; i <= 7; i++) {
printf("Note for FM channel %i is %i\n", i, notes[i]);
}
// Channels 8 through 15, if present, are PCM channels.
// The original X68000's sound chip has one PCM channel;
// through an expansion card, up to 8 PCM channels may be present.
// The integers for these channels indicate the index of the PCM sample in use;
// this is less informative than the note value, but a visualization might
// still be able to use this.
for (int i = 8; i < number_of_channels; i++) {
printf("Sample for PCM channel %i is %i\n", i, notes[i]);
}
// Increment the count of played buffers.
played_buffers++;
}
// When playback is over, finalize the t_mdxmini struct.
mdx_close(&data);
Programs using mdxmini
- MDXPLAYER for Android, by BouKiCHi
- ruby-mdxplay
- Paula
- Modizer by yoyofr
Credits
- milk.K, K.MAEKAWA, Missy.M - authors of the original X68000 MXDRV
- Daisuke Nagano - author of the Unix mdxplay
- BouKiCHi - author of the mdxmini library, and of the Android mdxplayer
- Misty De Meo - bugfixes and improvements to mdxmini, current maintainer
Related Skills
node-connect
330.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
81.3kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
330.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
81.3kCommit, push, and open a PR
