Jump to content

Mod4Play: Lightweight replayer for IT/S3M/XM/MOD music in C


Recommended Posts

Posted (edited)

I spun off a library that I cobbled together for use with EDGE-Classic in case it may be of use for other ports wanting to implement playback of tracker music. It supports the "Big 4" module formats (IT/XM/S3M/MOD), requires only the C standard library, and is BSD-licensed.

 

It unifies two existing projects, ft2play and it2play, which are C ports of the original Fast Tracker 2 and Impulse Tracker 2 replayers. I have removed the dependencies on winmm (or SDL for non-Windows OSes) and created a small set of functions that should make it pretty easy to integrate into existing programs.

 

Although there are arguably lighter libraries for XM, S3M, and/or MOD playback (such as pocketmodmicromod/IBXM, and jar_xm/jar_mod), I struggled to find something that also supported IT playback and didn't want to pull in DUMB, XMP, or other/bigger solutions.

 

Downloads and usage instructions can be found at the Github repo.

 

PS: I have also spun off our C64 SID replayer in a similar fashion, but that is a bit more niche.

Edited by dasho

Share this post


Link to post
Posted (edited)

That's pretty cool, good job.

 

It looks like itplay supports Impulse Tracker format modules only, meaning ModPlug Tracker extensions to the format (like stereo samples) probably won't work? I have no idea how relevant this is since people rarely compose IT music specifically for Doom maps.

Edited by plums

Share this post


Link to post
3 minutes ago, plums said:

That's pretty cool, good job.

 

It looks like itplay supports Impulse Tracker format modules only, meaning ModPlug Tracker extensions to the format (like stereo samples) probably won't work? I have no idea how relevant this is since people rarely compose IT music specifically for Doom maps.

 

The short and honest answer is that I am not familiar enough with the format to know at the moment. My testing was primarily taking WADs like DBP36 and Lazarevenant and comparing their playback to XMP, which EDGE-Classic did have at one point.

Share this post


Link to post
Posted (edited)
10 minutes ago, dasho said:

 

The short and honest answer is that I am not familiar enough with the format to know at the moment. My testing was primarily taking WADs like DBP36 and Lazarevenant and comparing their playback to XMP, which EDGE-Classic did have at one point.

Fair enough. If it's merged into EDGE Classic already maybe I'll give it a test sometime soon.

 

In the late 90s/early 2000s, the .it format had a long and sordid history of ModPlug (and other trackers) adding extensions to it that the original Impulse Tracker couldn't play, as well module players handling weird use of IT features incorrectly/differently from one another because it's such a complex format compared to xm/s3m. (Like, there's something like 8 different ways to set the panning and they all interact with each other in different ways, jesus christ.) Fixing all this is well beyond the scope of this project I'm sure, but I guess it'd be good to know what kind of limits it has.

Edited by plums

Share this post


Link to post
22 minutes ago, plums said:

Fair enough. If it's merged into EDGE Classic already maybe I'll give it a test sometime soon.

 

In the late 90s/early 2000s, the .it format had a long and sordid history of ModPlug (and other trackers) adding extensions to it that the original Impulse Tracker couldn't play, as well module players handling weird use of IT features incorrectly/differently from one another because it's such a complex format compared to xm/s3m. (Like, there's something like 8 different ways to set the panning and they all interact with each other in different ways, jesus christ.) Fixing all this is well beyond the scope of this project I'm sure, but I guess it'd be good to know what kind of limits it has.

 

If you have links or example songs that I can test, I'd be more than willing to do so and at least document what is and isn't supported. You're right in that fixing these things would be a bit of a backburner thing, but people should at least know what they can expect.

Share this post


Link to post
Posted (edited)

Here's wad with an .it module as D_RUNNIN, it's a simple loop that uses stereo samples (which is the most common/important extension) and samples beyond the 99th position. Crispy, GZDoom, dsda-doom and Eternity all handle it properly; Woof doesn't, I guess because they don't use SDL2 mixer.

 

https://user.fm/files/v2-c57ebd8d50beffa9168694bc15007017/it_test.wad

 

Again this is largely theoretical, probably no one but me cares and even then it's more for curiosity than anything.

Edited by plums
better stereo example

Share this post


Link to post
Posted (edited)
1 hour ago, plums said:

Here's wad with an .it module as D_RUNNIN, it's a simple loop that uses stereo samples (which is the most common/important extension) and samples beyond the 99th position. Crispy, GZDoom, dsda-doom and Eternity all handle it properly; Woof doesn't, I guess because they don't use SDL2 mixer.

 

https://user.fm/files/v2-c57ebd8d50beffa9168694bc15007017/it_test.wad

 

Again this is largely theoretical, probably no one but me cares and even then it's more for curiosity than anything.

 

I appreciate the example; mod4play does indeed fail to initialize the track, but I will have to fire up a debugger to know exactly why (although in general I'm just assuming the extension isn't supported). 

 

We also do not use SDL2_mixer, only SDL2's basic audio functions in tandem with our own mixing code. If I do happen to get the library working with stereo samples, I will post an update to the repo and thread.

 

EDIT: Ah, ok, I do see that the new HQ mixer that was created for it2play does support this. I had removed all mixer drivers besides the original SB16. I will poke at it and see how hard it would be to restore this.

Edited by dasho

Share this post


Link to post
Posted (edited)

After looking at the debugger, the stereo samples are actually fine. They are supported even if the HQ mixer isn't used. There is a (what appears to be) arbitrary cap of 100 instruments and 100 samples for a module, which your example wad happened to exceed (according to what it read from the header). If I set the cap to 200 for each, it plays fine.

 

Is there an agreed upon number that modern tracks tend to stick to?

Edited by dasho

Share this post


Link to post
Posted (edited)
4 hours ago, plums said:

Woof doesn't, I guess because they don't use SDL2 mixer

We're using libxmp directly. I'd be surprised if it doesn't support stereo samples. 

 

Edit: Well, at least I hear music on MAP01. What's missing?

Edited by fabian

Share this post


Link to post

The repo and version have been updated to reflect the restored stereo sample support and raised instrument/sample limits. I kept it at 200, which should hopefully cover most use cases.

Share this post


Link to post
5 hours ago, fabian said:
10 hours ago, plums said:

Woof doesn't, I guess because they don't use SDL2 mixer

We're using libxmp directly. I'd be surprised if it doesn't support stereo samples. 

 

Edit: Well, at least I hear music on MAP01. What's missing?

 

It seems there is an issue in libxmp: https://github.com/libxmp/libxmp/issues/600

I guess we can go back to libmodplug (which SDL_Mixer uses).

 

On topic, thanks for the nice library. It looks like EDGE-Classic only has dependency on SDL2, that's impressive.

Share this post


Link to post
Posted (edited)
7 hours ago, fabian said:

We're using libxmp directly. I'd be surprised if it doesn't support stereo samples. 

 

Edit: Well, at least I hear music on MAP01. What's missing?

In case you're still curious: Stereo samples get played in mono, and the sample in the sample list after a stereo sample doesn't get played at all. Also the volume seems much lower compared to other ports that use libmodplug, which probably affects all tracker music. Compare to how it sounds in Crispy Doom, for example.

Edited by plums

Share this post


Link to post

@plums You may probably be able to provide some additional information (and the track in question) to the upstream bug report. libxmp upstream seems to be rather active currently, probably because of the attention boost by the SDL maintainers.

Share this post


Link to post
Posted (edited)
5 hours ago, AnotherGrunt said:

Nice. Maybe you should add some example.c file.

 

I have updated the repo with a test program that can be compiled and will show a window while playing back an embedded MOD file. You can find the code under /example/m4player-sapp.c. Search for the functions that begin with "m4p_" to see their usage.

 

EDIT: I have also added zips with compiled 32 and 64-bit Windows version of this test program to the v1.1 Release page.

Edited by dasho

Share this post


Link to post
24 minutes ago, Herr Dethnout said:

.ftm support when?

 

Honestly, that's out of scope for this project. Anyone that has followed EC's repo knows that I have gone down the rabbit hole plenty of times regarding music format support, but this was a result of 'trimming the fat' and supporting what is practical instead of everything and the kitchen sink. We've even removed the SID library I mention in the OP because it was very cool but not really needed.

 

Between IT/S3M/XM/MOD and Reality Adlib Tracker v2 (since that comes basically for free as we use their Opal OPL emulator for regular OPL playback), I don't think we have plans to add any more module formats.

Share this post


Link to post
On 1/6/2024 at 3:58 AM, dasho said:

I struggled to find something that also supported IT playback and didn't want to pull in DUMB, XMP, or other/bigger solutions.

You mentioned XMP, did you happen to look into XMP-lite? It's supposed to be for lightweight use like in games, and it's a part of the main repository.

Share this post


Link to post
Posted (edited)
32 minutes ago, Lollie said:

You mentioned XMP, did you happen to look into XMP-lite? It's supposed to be for lightweight use like in games, and it's a part of the main repository.

 

I did; in fact EDGE-Classic 1.1 used it for playback. If I recall, I started looking for alternatives because there seemed to be noticeable delays in loading the track upon starting a level that used more complex modules. Hard to say after this long if there was some underlying flaw in our code instead, but I'm pretty happy with m4p.

 

EDIT: I've also updated the libcRSID repo with a similar example program and updated instructions.

Edited by dasho

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...