Midi Tools 1.11


SP4CEBAR 2021-05-02 20:12 (Edited)

click here to read what's new in version 1.11

This program can read, play and convert midi files.

You can choose to use the internal or an external disk, or both, but that's not supported yet. You can also choose what rom entry to use. In this version, you can load midi files of 32KB and below, in a future version I want to increase this to 64KB (with two disks).

Loading A MIDI File

To load in a midi file, you can open a .mid file in a hex editor, if you're on IOS you could use an online hex editor*. In the hex editor you can copy the hex data and paste it in this program, or the disk.nx program, or another program which can use this program as a tool. I've loaded a midi file for the nyan cat song in local rom entry 5.

HEX Editor

* This online hex editor is one of the few which allows you to copy the hex data to clipboard
Make sure to uncheck the "Use 0x and comma as separator".


When converting a midi file to an NX music file you can set the precision of the quantization: a value of 1 means that it'll preserve the music as best as it can, but it'll probably not fit in the 64 tracks of NX music, and the playback speed could be very slow.

Loading 64 KB

Although the program doesn't support it yet, you can theoretically load 64KB using both the internal and an external disk. To do this you'll need to split the file two files of 32KB or less. I think the best way to do this is to use a text editor with numbered lines like this compiler website. Then paste the 64KB of midi data into the text editor, go to the end of line 2048 and hit enter. Copy the first part to the disk.nx program or another program which can use this program as a tool, make sure it doesn't have any other ROM file in it. Finally, copy the second part to the ROM of this program, and remove/replace the midi data stored in ROM 5.


1.11 - lower and higher notes can be played - click to read more
1.10 - no more hanging notes - click to read more
1.9.1 - Embedded Data - click to read more
1.9 - DISPLAYS AND AUTOMATION - click to read more
1.8 - NO MORE FLICKERING - click to read more
1.7 - CONVERTOR IS BACK! - click to read more
1.6 - ACCURACY! - click to read more


1.3 - Never gonna give you up

1.2 - important fix

Known Bugs And Errors:

With each update the program changes quite a bit. So If something doesn't work, just try a previous version.

Big thanks to Timo for helping me with the midi file system

Midi Tools.nx | Open in app
2021-05-06 21:47
Midi Tools.nx | Open in app
2021-05-06 18:31
Midi Tools.nx | Open in app
2021-05-04 10:48
Midi Tools.nx | Open in app
2021-05-03 22:01
Midi Tools.nx | Open in app
2021-05-03 08:36
Midi Tools.nx | Open in app
2021-05-02 20:12

CubicleHead 2021-05-03 11:30

So awesome! This will be very useful!

SP4CEBAR 2021-05-03 18:10


G-9 2021-05-04 12:07 (Edited)

Still not working :(
EDIT : I tried ur file to hex converter and it worked :3

Disk.nx | Open in app
2021-05-04 12:31

SP4CEBAR 2021-05-04 14:17


G-9 2021-05-04 18:54

Nice markdown :3

SP4CEBAR 2021-05-04 21:26 (Edited)

When I realized that markdown is the same markup language discord uses, I could use it straightaway

SP4CEBAR 2022-01-21 16:24

Read, play, and convert used to share the same loop, Man was that annoying to work with
It was one enormous block of code

I've just broken it up into subprograms and separate loops for each operation, it looks so much cleaner now

SP4CEBAR 2022-01-21 17:32 (Edited)

Also I used the variable "I" to hold the memory address, and whats worse is that I made it a global variable, why did I think that was a good idea

SP4CEBAR 2022-01-21 17:43

I managed to change the order of the tasks
It now reads the next delta T after it has executed a midi command (instead of before)
With this I know the time to wait in advance, which is essential if I want to make a scheduler (multitask)

G-9 2022-01-22 14:41

Amazing you did a real great job

SP4CEBAR 2022-01-22 16:54

Thank you!

SP4CEBAR 2022-01-22 21:22 (Edited)

I think I figured out why some tracks won't play correctly
I think that storing the address and the timecodes for each track in the scheduler isn't enough, I think my decoder needs more variables (it's been a while since I last worked on it)

SP4CEBAR 2022-01-22 21:28 (Edited)

I caught my midi decoder jumping $800 addresses ahead, so clearly it's missing something...

SP4CEBAR 2022-01-22 22:50 (Edited)

The jumping is caused by it reading a metadata command with a really long length, which is wrong
So it must've gone off-track earlier...

G-9 2022-01-23 14:36

I'm so hyped for both bugfix and multitrack convert :D
The song output would be amazing 🤩
Also to you have a trick about how to guess precision number ? My #15 file is filled with A-0 😂

SP4CEBAR 2022-01-23 17:51

I'm trying to make it play multiple tracks at once, this requires a scheduler and things get more complicated, I'm currently filling my program with tracers to compare the multitrack player with the single track player
The converter doesn't need a scheduler, it converts the tracks one by one (NX tracks are monophonic)
The precision is used for time quantization (aligning notes to a grid), when the NX file size is too big, you may want it to be less precise, and if it doesn't sound as good, you may want more precision (you may not be able to fit the whole song inside the 64 NX tracks)

(unstable wifi connection made me have to rewrite this)

SP4CEBAR 2022-01-23 19:33

I just got an idea: I could make a new file format called "NX Tracks" which contains just the tracks part of the NX music file format, but I can store as much NX tracks as needed
I could make my music editor compatible with that format as well
It would allow the converter of this midi tool to make music files that are much bigger

SP4CEBAR 2022-01-23 21:02

I have this bug memorial in my code:
I think it just happened again...

SP4CEBAR 2022-01-23 21:04

The first 8 bytes of each midi track contains the size of the track, which shouldn't be read as midi data, because it's not
This is what a good offset looks like: FOR I=INDEX(J)+8 TO INDEX(J+1)-1

SP4CEBAR 2022-01-23 21:06

YAAAS, the multitrack reader can now read the nyan cat midi file (which it couldn't before)

SP4CEBAR 2022-01-23 21:09


SP4CEBAR 2022-01-23 21:28

And the track playback is in sync!

SP4CEBAR 2022-01-23 21:29

It's done!!
*Well at least the scheduler-based midi player*

SP4CEBAR 2022-01-23 21:30

Next I'll try to find a way to optimize the usage of the four voices

SP4CEBAR 2022-01-26 21:18 (Edited)

The tracks slowly drift out of sync
This is probably caused by lag (the program can run behind on schedule), and the rounding of delta times (I have to convert delta times to NX-frames)
That's the issue with delta times, they are relative, it can't know whether or not it's synced with the other tracks unless it has an absolute time count to compare it to.
So I guess I've got to sum the delta times together for each track so that I can convert that to NX-frames and subtract TIMER from it to generate synced delta time values.

SP4CEBAR 2022-01-26 21:26 (Edited)

Also I think the converter needs more options
Currently you can only convert the tracks from the start until the memory (NX tracks) runs out
I want to add an option to select a single track to convert
Also, I want to add an option to export quantized notes as a file
And, I want to add an option to export unquantized notes as a file
I want to make my piano roll music studio compatible with those files so that you can do more post processing to improve the quantization quality
But it's a ton of work I'll probably not do any of this soon

nathanielbabiak 2022-06-05 03:52 (Edited)

Hey, as you were developing this, did you learn anything about the audio registers? I posted a question here... Any chance you could take a look?

SP4CEBAR 2022-06-05 20:15 (Edited)

@nathanielbabiak yes, I've done some tests myself on some of the audio registers, I'll try to answer your questions
I remember that I once understood how sounds are started and stopped via the registers, but I may have forgotten it now, I'll see if I can find some code that starts or stops sounds via registers
Either way, this program displays the state of those registers, and that was quite helpful for my research

SP4CEBAR 2022-06-05 20:20

I found a program that writes registers to start playing an arpeggio when you touch the screen and the sounds stop once you stop touching the screen

Voice Simulator.nx | Open in app
2022-06-05 20:20

SP4CEBAR 2022-06-05 20:29

After analyzing my code, I think this starts a sound
POKE $FF42,PEEK($FF42)MOD 64+64+128
And this stops a sound
POKE $FF42,PEEK($FF42)MOD 64+64

And there's also this, with the comment "INTITALIZE VOICES" above it
'POKE $FF42,PEEK($FF42)MOD 64+128

SP4CEBAR 2022-06-05 20:36

These lines of code read the status byte of voice 1 (peek($FF42)), set the most significant two bits to zero (mod 64), and then add their own most significant bit 2-bit codes (+64) and or (+128)

SP4CEBAR 2022-06-05 21:16

I just posted an answer to your question
I guess I wrote you a textbook

nathanielbabiak 2022-06-06 03:38

Thanks - this is excellent stuff!

SP4CEBAR 2022-07-31 10:39 (Edited)

V1.6 - Accurate Playback

When playing a midi file, tracks don't get out of sync anymore! Even single-track playback has improved, it's much more accurate now!

I used to read each delta time value, round it to NX frames, and store it, this results in some tracks being rounded upwards more and other tracks being rounded downwards more, and thus the tracks get out of sync

The solution was really simple, I didn't need to make an absolute schedule, I just needed to store and sum the delta time values, and round them to NX frames at the very last moment, I also needed to store a TIMER_ZERO value so that I could use TIMER for this. this is a self-correcting system, the sum of delta time values is the exact right moment, no matter what time the program takes to run it

SP4CEBAR 2022-09-21 20:12 (Edited)

V1.7 - Conversion Is back

I've been so focused on multi-track playback that I didn't realize that conversion was broken, and as it turns out it was the lack of testing that broke it
I found this:
Which should've been:
I must've not tested it, otherwise I would've noticed

However, it seems like for some files you need to enter a really high precision value (a high precision value means low precision) like 32 or 64

McPepic 2022-09-22 00:29

I was messing around with different files and I found one that temporarily breaks the LowRes display when played using the tool. There's also some weird stuff going on with the audio. Would you like to have a look?

SP4CEBAR 2022-09-22 08:26 (Edited)

Yeah, sure
does the display flicker? If so then that song probably has a ton of tracks that are played so fast that VBL has to interrupt the graphics, and the four voices are having a hard time...
Ohh, I finally know a solution to the flickering: I shouldn't use CLW
instead, it should just relocate the cursor, and print blank lines when needed

SP4CEBAR 2022-09-22 08:49 (Edited)

V1.8 - No More Flickering on busy MIDI files

SP4CEBAR 2022-09-22 10:05 (Edited)

V1.9 - Displays And Automation

Also... the monkey island midi track, which played OK before, now sounds broken...

SP4CEBAR 2022-09-22 10:15

V19.1 - Embedded Data

McPepic 2022-09-22 15:17

Wow, you’ve been really busy. Super cool program btw! :)

SP4CEBAR 2022-09-22 15:39 (Edited)

Thanks! the last two updates were basically a merge with the instant midi players like the monkey island midi player, this was needed because it's annoying to have two versions that both need updating

Also, Did the converter work this time?
Does the file that looked like it had graphical glitches look better now?

McPepic 2022-09-22 17:20

So, I was messing around with the program some more. After the file plays for a while, it gets stuck on a really high pitched beep on voice 4. I don't know if it ever stops this.

If I try to go to the graphics / sound editor for LowRes, it gives me a black screen. If I try to run the program again from the menu, it gives me the default blue screen of a blank program. After a few seconds, the program finally loads, though.

The converter plays back the result (I find this program works best with a precision value of 64). When I open the music editor, the patterns are all set to track 0 on every voice and the sounds are all set to 0s on every option. The tracks do seem to be filled in properly by the converter, though. Also, the music is always saved to file 15 of the ROM regardless of what you entered in for the conversion. This seems to be hard coded.

SP4CEBAR 2022-09-22 22:54 (Edited)

The stuck beep is probably the same problem that the Monkey Island theme had: for some reason, the program sometimes won't stop a note in running-status files

It's not the program, it's the file that determines what precision value is needed, for example, the midi file at local ROM(5) works with a precision of 2

Yeah, the patterns aren't given any data as the convertor in its current state is pretty limited, it just extracts pitch values and encodes it into tracks

Good that you found that ROM 15 can't be changed, I never realized it, so I must've completely forgotten it

SP4CEBAR 2022-09-23 08:46 (Edited)

It looks like the stuck beep, got missed halfway through the song, and the song happens to not overwrite it (it uses one voice)
The beep has an NX pitch of 117, an NX velocity of 1, and a track of (7 and 16) (midi has tracks (tags) within tracks (data blocks))

SP4CEBAR 2022-10-29 13:00

I caught the hanging note bug!

SP4CEBAR 2022-10-29 13:02

And I found some suspicious code:

  FOR X=0 TO 3
    END IF

SP4CEBAR 2022-10-29 13:03

When PLAYING(0,0)=0
it'll never be able to select PLAYING(0,1)=PITCH to be able to overwrite it

SP4CEBAR 2022-10-29 13:07

It's fixed, it was so simple

SP4CEBAR 2022-10-29 13:15 (Edited)

version 1.10

bugs remaining:

SP4CEBAR 2022-10-29 13:53 (Edited)

monkey island still has hanging notes, I think the issue there is that it doesn't support enough midi commands

SP4CEBAR 2022-10-29 14:52 (Edited)

Next I'll replace PLAY V,N with this function, to get more range:

  POKEW A,O+16*16.35*2^((N-1)/12)
  POKE A+2,PEEK(A+2) OR %11000000

SP4CEBAR 2022-10-29 15:17 (Edited)

Version 1.11

Log in to reply.