New JavaScript library to write Impulse Tracker mod files

Started by chr15m, May 24, 2024, 08:39:39

Previous topic - Next topic

chr15m

Hey all,

I just released this small library to create .it files from JavaScript. You pass it a JSON definition of your song and it outputs the binary blob for a .it file. It works in Node.js and also in the browser.

I'm going to be using this to build some stuff but I thought it might be useful for other people too.

Code: https://github.com/chr15m/itwriter
Demo: https://chr15m.github.io/itwriter/

Enjoy!

Saga Musix

Interesting project - but if I can ask for one thing: This tool should probably not identify as OpenMPT 1.29 in the header. Depending on the use case this may not be a big problem, but effectively means that if OpenMPT (or libopenmpt) plays any file generated with this tool, it will always do so with the playback settings according to how that OpenMPT version played them (including all playback bugs and differences compared to original Impulse Tracker). It would be safer to either identify as Impulse Tracker 2.14 (0x1402 instead of 0x2951), or allocate your own tracker ID (see wiki page). In the latter case, it may be a good idea to use a single fixed ID in the Dxxx range (like SPC2IT) without any version information attached to it. As yet another alternative, you could of course make this version number configurable.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

chr15m

Thank you yes I was worried about using this value but I wasn't sure how to change it. Now that you have shown me I'll make the change. I created an issue here so I don't forget:

https://github.com/chr15m/itwriter/issues/3

Thanks again!

chr15m

@Saga Musix I have now updated the itwriter library to use the Tracker ID 0xD1CE instead of the OpenMPT one. Will publish the updated library shortly. Thanks for the heads-up on this!

Saga Musix

Nice! I'm not really familiar with the JS DataView but it looks to me like the additional changes in this commit introduce some endianness confusion: All values in IT files are little-endian, but as DataView is big-endian by default, you had to swap some constants in the old code (e.g. OpenMPT's version 1.29 is 0x5129, but the constant in the code said 0x2951 with the two bytes reversed). Now it looks like you forced the Cwmt and flag values to be written as little-endian values but keeping their big-endian representation in the code, so now instead of claiming compatbility with IT 2.14 (0x0214), the file declares compatibility with IT 14.02 - Impulse Tracker would be unable to load the file because of this - and the flag values are also not the ones that you intended to write (they should be 0x0049).
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

chr15m

There's a good chance you're right and I have screwed this up. ;D I was testing with XMP and here are the different results I got after this commit. Each result shows the JavaScript config value passed to itwriter, and then what XMP sees when it opens the resulting example.it file.

"tracker_id": 0x0214
Module type  : Impulse Tracker 2.14 IT 20.02

"tracker_id": 0x5129
Module type  : OpenMPT 1.29 (compat.) IT 20.02

"tracker_id": 0xD1CE
Module type  : unknown (d1ce) IT 20.02


Do these values look right to you?

chr15m

Wait, I see what you are saying. I changed the other constants too without swapping the bytes. Thanks for catching that! Will push a fix.

Saga Musix

Yeah, that fix looks good. There's two more things I would suggest to change to make the code easier to grasp - writing the pattern highlights (PHiligt) as two separate bytes, as this is not really a 16-bit integer value but two individual 8-bit values (the first byte is the rows per beat, the second the rows per measure). The second is the "special" flags, which is a 16-bit value but it's currently written as a big-endian value, so the flag bytes are swapped. This makes it a bit hard to understand which flags are actually set, because the flag for embedding the song message is 1, not 256. :) So my suggestion would be to use data.setUint16(offset, 0x0006 | struct.message ? 0x0001 : 0x0000, true); instead.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.


chr15m

@Saga Musix do you know how I encode the "Sample Volume" slider on the "General" tab that defaults to 48?

Related: where is the best modern description of the layout of IT files? I found some sources but none of them is perfect, and I ended up looking at the OpenMPT source quite a bit when developing itwriter.

chr15m

Actually never mind, I figured it out - mix volume byte.

Saga Musix

I think IT's ITTECH.TXT is pretty accurate and complete apart from a thing or two, which I have documented here: https://wiki.openmpt.org/Development:_Formats/IT
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.