Artefact2/libxm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A small XM (Fasttracker II Extended Module) player library. Main features:

  • Small and hackable: many features can be disabled at compile-time, or are optimized out by the compiler if not used. It is easy to bundle libxm in your game, demo, intro, etc.

  • Fairly portable. Minimal dependencies (just libm). No memory allocations. Big-endian compatible (tested on s390x).

  • Reasonable accuracy compared to Fasttracker 2. Deviations from FT2 playback, that aren't obviously bugs in FT2, are also libxm bugs. If you have a module that plays incorrectly, please test it in FT2/FT2clone and open an issue!

  • Can load most XM/MOD files, however playback accuracy of non-XM is best-effort.

  • Timing functions for synchronising against specific instruments, samples or channels.

  • Samples can be loaded and altered at run-time, making it possible to use libxm with softsynths or other real-time signal processors.

Written in C23 and released under the WTFPL license, version 2.

  • Build the library:

    cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -Bbuild -Ssrc
    make -C build
    
  • Build a specific example:

    cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -Bbuild-FOO -Sexamples/FOO
    make -C build-FOO
    
  • To build a shared library and link dynamically, use cmake -DBUILD_SHARED_LIBS=ON.

  • To see a list of build options, use cmake -L or cmake-gui.

  • To use libxm in your program, put these lines in the CMakeLists.txt of your project, then #include <xm.h>:

    add_subdirectory(/path/to/libxm/src libxm_build)
    target_link_libraries(my_stuff PRIVATE xm)
    

libxmtoau can be compiled (with all playback features enabled) and crushed to about 3871 bytes (x86_64-linux-gnu).

cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DXM_VERBOSE=OFF -DXM_LIBXM_DELTA_SAMPLES=OFF -DXM_LINEAR_INTERPOLATION=OFF -DXM_RAMPING=OFF -DXM_STRINGS=OFF -DXM_TIMING_FUNCTIONS=OFF -DXM_MUTING_FUNCTIONS=OFF -DXM_SAMPLE_TYPE=float -DXM_SAMPLE_RATE=44100 -Bbuild-libxmize -Sexamples/libxmize
make -C build-libxmize libxmtoau
strip -R .eh_frame_hdr -R .eh_frame build-libxmize/libxmtoau
xzcrush build-libxmize/libxmtoau

If you are using libxm to play a single module (like in a demo/intro), disable features as suggested by libxmize --analyze to save a few more bytes.

For example, libxmize --analyze mindrmr.xm suggests -DXM_DISABLED_EFFECTS=0xFFFFD9FBFFDE68E1 -DXM_DISABLED_VOLUME_EFFECTS=0x0CC0 -DXM_DISABLED_FEATURES=0xFFFFFFFFFFF7EE04 -DXM_PANNING_TYPE=8. We only want to play the module once and quit, so we can use -DXM_LOOPING_TYPE=1. Compiling with these new flags, the resulting binary is crushed to 2705 bytes.

  • libxm.js is a very simple XM player/visualiser that runs in a browser (emscripten port).

  • xmgl is a simple music visualiser that uses OpenGL, GLFW and JACK for very precise audio synchronisation. See a demo here: https://www.youtube.com/watch?v=SR-fSa7J698

  • xmprocdemo: a simple non-interactive demo that plays back a single module with procedurally generated samples. Somewhat optimized for size. (Dream Candy by Drozerix, public domain. Thank you Drozerix for the great music!)

  • libxmize converts a .xm module to the libxm format. It is highly non-portable and is meant for static linking and sizecoding (loading code is much shorter and libxm format compresses better).

  • libxmtoau reads standard input (a file generated by libxmize) and writes a .AU file to standard output. Somewhat optimized for size, see size section above. You can test it with, for example, libxmize file.xm | libxmtoau | mpv -.

Here are some interesting modules, most showcase unusual or advanced tracking techniques (and thus are a good indicator of a player's accuracy):

  • E8y panning effect is supported, FT2 has no support for this command
  • Glissando control (E3y) with Amiga frequencies is not yet supported
  • Arpeggios after pitch slides with Amiga frequencies are subtly incorrect
  • Amiga filter toggle (E0y) is not supported, and is unlikely to be
  • Invert loop / funk repeat (EFy) is not supported, and is unlikely to be
  • Period wraparound after a long slide down (with eg, 2xx) is not accurate
  • Global volume effects (Gxx/Hxy) are subtly incorrect
  • Tone portamento (3xx/Mx) does not "lock" its direction
  • Arpeggio (0xy) does not reset vibrato offset (Vy) when Spd=1
  • (MOD only) Sample offset (9xx) beyond sample loop end will cut the note
    • Can be manually toggled with FEATURE_ACCURATE_SAMPLE_OFFSET_EFFECT

To report more, please open an issue.

Some test XM files are in the tests directory.

A few tests can be automatically run (failing tests marked XXX are not regressions, but bugs/inaccuracies that have yet to be fixed):

cmake -Bbuild-tests -Stests
make -C build-tests all test

Other tests require manual checking, see the table below.

Test                            | Status         | Tested against         | Extras
--------------------------------+----------------+------------------------+------------------------------------------------
autovibrato-triggers.xm         | MOSTLY         | FT2clone 1.94          | Should sound identical. Use a spectrogram as it is very hard to hear subtle changes in pitch.
pattern-loop-quirk.xm           | PASS           | MilkyTracker           | Should play the same notes at the same time.
pos_jump.xm                     | PASS           | Milkytracker, OpenMPT  | Only one beep should be heard.
ramping.xm                      | PASS           | FT2clone 1.94          | If XM_RAMPING is ON, output should be mostly frame for frame identical.
waveform-control-autovibrato.xm | PASS           | FT2clone 1.94          | Should sound identical. Patterns 0 and 1 should also sound identical. Use a spectrogram as it is very hard to hear subtle changes in pitch.
waveform-control-combo.xm       | PASS           | FT2clone 1.94          | Should sound identical.
waveform-control-tremolo.xm     | PASS           | FT2clone 1.94          | Should sound identical.
waveform-control-vibrato.xm     | PASS           | FT2clone 1.94          | Should sound identical.

Thanks to:

  • Thunder [email protected], for writing the modfil10.txt file;

  • Matti "ccr" Hamalainen [email protected], for writing the xm-form.txt file;

  • Mr.H of Triton and Guru and Alfred of Sahara Surfers, for writing the specification of XM 1.04 files;

  • All the MilkyTracker contributors, for the thorough documentation of effects;

  • Vladimir Kameñar, for writing The Unofficial XM File Format Specification;

  • All the people that helped on #milkytracker IRC;

  • All the libxm contributors.

About

A small XM (Fasttracker II Extended Module) player library.

Topics

Resources

License

Stars

Watchers

Forks

Contributors 7