Data Structures | Functions
xm64.h File Reference

Efficient XM module player. More...

Go to the source code of this file.

Data Structures

struct  xm64player_t
 Player of a .XM64 file. More...


void xm64player_open (xm64player_t *player, const char *fn)
 Open a XM64 module file and prepare for playback. More...
int xm64player_num_channels (xm64player_t *player)
 Get the number of channels in the XM64 file. More...
void xm64player_set_loop (xm64player_t *player, bool loop)
 Configure a XM64 file for looping. More...
void xm64player_play (xm64player_t *player, int first_ch)
 Start playing the XM64 module. More...
void xm64player_stop (xm64player_t *player)
 Stop XM playback. More...
void xm64player_tell (xm64player_t *player, int *patidx, int *row, float *secs)
 Read the current position of the XM module. More...
void xm64player_seek (xm64player_t *player, int patidx, int row, int tick)
 Seek to a specific position of the XM module. More...
void xm64player_set_vol (xm64player_t *player, float volume)
 Change the volume of the player. More...
void xm64player_set_effect_callback (xm64player_t *player, void(*cb)(void *, uint8_t, uint8_t, uint8_t), void *ctx)
 Set a custom effect callback to allow music synchronization. More...
void xm64player_close (xm64player_t *player)
 Close and deallocate the XM64 player.

Detailed Description

Efficient XM module player.

This module implements a player of the .XM64 file format, which is based on the Fast Tracker II .XM module format.

The playback relies on the mixer (mixer.h), as it uses it to perform the actual channel playing and mixing. It will use one mixer channel per each XM channel. You need to initialize the mixer (via mixer_init) before using xm64player_t.

The actual XM player is based on libxm (, a very fast and accurate XM player library that has been adapted for usage in libdragon on N64. The main changes are:

Data Structure Documentation

◆ xm64player_t

struct xm64player_t

Player of a .XM64 file.

This structure holds the state a player of a XM64 module. It can be initialized using xm64player_open, and played with xm64player_play.

See the rest of this module for more functions.

Data Fields
xm_context_t * ctx libxm context
waveform_t * waves array of all waveforms (one per XM "sample")
int nwaves number of wavers (XM "samples")
FILE * fh open handle of XM64 file
int first_ch first channel used in the mixer
bool playing playing flag
bool looping true if the XM is configured to loop
struct seek seeking to be performed


Data Fields
int patidx
int row
int tick

Function Documentation

◆ xm64player_open()

void xm64player_open ( xm64player_t player,
const char *  fn 

Open a XM64 module file and prepare for playback.

This function requires the mixer to have been already initialized (via mixer_init).

playerPointer to the xm64player_t player structure to use
fnFilename of the XM64 (with filesystem prefix). Currently, only files on DFS ("rom:/") are supported.

◆ xm64player_num_channels()

int xm64player_num_channels ( xm64player_t player)

Get the number of channels in the XM64 file.

Notice that the player needs to use one mixer channel per each XM64 channel.

◆ xm64player_set_loop()

void xm64player_set_loop ( xm64player_t player,
bool  loop 

Configure a XM64 file for looping.

By default, XM64 files will be played in loop. Use this function to disable looping.

[in]playerXM64 player
[in]looptrue to enable looping, false to disable looping.

◆ xm64player_play()

void xm64player_play ( xm64player_t player,
int  first_ch 

Start playing the XM64 module.

Notice that the player needs to use one mixer channel per each XM64 channel.

playerXM64 player
first_chIndex of the first mixer channel to use for playback.

◆ xm64player_stop()

void xm64player_stop ( xm64player_t player)

Stop XM playback.

The XM module will keep the current position. Use xmplayer_play to continue playback.

◆ xm64player_tell()

void xm64player_tell ( xm64player_t player,
int *  patidx,
int *  row,
float *  secs 

Read the current position of the XM module.

The function returns the current position expressed as pattern/row (internal XM position), and also expressed as number of seconds. You can pass NULL to information that you are not interested in receiving.

playerXM64 player
[out]patidxIndex of the XM pattern
[out]rowRow within the pattern
[out]secsTotal number of seconds

◆ xm64player_seek()

void xm64player_seek ( xm64player_t player,
int  patidx,
int  row,
int  tick 

Seek to a specific position of the XM module.

Seeking in XM module is "broken by design". What this function does is to move the playback cursor to the specified position, but it doesn't take into effect what samples / effects should be active at the seeking point.

playerXM64 player
patidxIndex of the XM pattern to seek to
rowRow within the pattern to seek to
tickTick within the row to seek to

◆ xm64player_set_vol()

void xm64player_set_vol ( xm64player_t player,
float  volume 

Change the volume of the player.

This allows to tune the volume of playback. The default volume is 1.0; smaller values will lower the volume, higher values will amplificate (but may clip).

◆ xm64player_set_effect_callback()

void xm64player_set_effect_callback ( xm64player_t player,
void(*)(void *, uint8_t, uint8_t, uint8_t)  cb,
void *  ctx 

Set a custom effect callback to allow music synchronization.

This function configures a callback that will be called whenever the player finds an unknown / unsupported effect in any channel. These unknown effects can be used to add custom "sync cues" in the music score, and synchronize graphic effects or gameplay logic to them.

There are many unused effect letters in XM format. For instance, a good choice can be effect Xxx which is used as modplug hack for MIDI support, but is unimplemented by standard XM players like this one.

The callback will be called passing as arguments a custom context, the channel number, and the effect code and the effect parameter. The effect code is the code in extended hex format (A-F are 10-15 as in normal hex, but then G-Z are 16-35), while the effect parameter is one free byte that can be inserted in the music score.