Release

Midi Tools 1.15.5

9

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

click here to read what's new in version 1.15.5

This program can read, play, and convert MIDI files.

check out the API

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 that allows you to copy the hex data to your clipboard
Make sure to uncheck the "Use 0x and comma as separator".


Converter

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 into 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 that 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.

Loading From Strings

Since version 1.15.1 you can load MIDI files from strings of hexadecimal characters (without spaces or newlines). These strings have to be written inside the G_FILE_STRING1$ variable inside the GET_FILE_STR subprogram (which is the last subprogram). This method allows you to load infinitely big files. Unfortunately, you wouldn't be able to post any program larger than 128KB, luckily you can use the API to scrape this data and store it as a new file.


Versions:

1.15.5 - QUICK PATCH
1.15.4 - DEBUGGING
1.15.3 - EFFICIENCY
1.15.2 - DEBUGGING TOOLS
1.15.1 - STRINGS ARE SUPPORTED
1.15.0 - SCRAPE HUGE FILES
1.14.0 - CLEANUP CONCLUDED
1.13.8 - "I" INFESTATION CLEARED
1.13.7 - NO MORE J
1.13.6 - ROGUE PRINTS OBLITERATED
1.13.5 - MIDI HEADER REVISIT
1.13.4 - CLEAN UP
1.13.3 - OLD MODES MERGED
1.13.2 - FAST TRANSCODING
1.13.1 - SMOOTH ANIMATIONS
1.13 - THE API IS REAL!
1.12.6 - IT'S TIME TO MERGE
1.12.5 - CLEAN API
1.12.4 - CLEAR GLOBALS
1.12.3 - CORE SEPARATED
1.12.2 - LOADER SEPARATED
1.12.1 - CORE REFACTORED
1.12 - LOADER REFACTORED
1.11 - NOTE RANGE BOOST
1.10 - NO MORE HANGING NOTES
1.9.1 - EMBEDDED DATA
1.9 - DISPLAYS AND AUTOMATION
1.8 - NO MORE FLICKERING
1.7 - CONVERTOR IS BACK!
1.6 - ACCURACY!
1.5 - RELIABILITY!
1.4 - MULTITRACKS!
1.3.1 - EFFICIENT VOICES
1.3 - BIG FILES
1.2 - RUNNING STATUS
1.1 - EXISTENCE

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 1.15.4.nx | Open in app
2024-01-24 16:01
Midi Tools 1.15.3.nx | Open in app
2024-01-12 22:20
Midi Tools 1.15.2.nx | Open in app
2024-01-12 19:28
Midi Tools 1.15.1.nx | Open in app
2024-01-12 15:42
Midi Tools 1.15.0.nx | Open in app
2024-01-07 00:08
Midi Tools 1.14.0.nx | Open in app
2023-10-09 19:11
Midi Tools 1.13.8.nx | Open in app
2023-10-09 16:25
Midi Tools 1.13.7.nx | Open in app
2023-10-09 15:29
Midi Tools 1.13.6.nx | Open in app
2023-10-09 13:06
Midi Tools 1.13.5.nx | Open in app
2023-10-08 12:34
Midi Tools 1.13.4.nx | Open in app
2023-10-07 22:04
Midi Tools 1.13.3.nx | Open in app
2023-10-07 15:15
Midi Tools 1.13.2.nx | Open in app
2023-10-07 11:34
Midi Tools 1.13.1.nx | Open in app
2023-10-07 08:52
Midi Tools 1.13.nx | Open in app
2023-10-04 14:54
Midi Tools 1.12.3.nx | Open in app
2023-09-29 13:34
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

Thanks


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

Great


G-9 2021-05-04 18:54

Nice markdown :3


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

Thanks
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
congrats


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:
'BUG MEMORIAL: FORGOT TO OFFSET THE INDEX VALUES
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

AND THE GLITCHY NOISES IN THE ZELDA THEME ARE GONE!!!


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)

Version history (edit)

1.2 - important fix

1.3 - Never gonna give you up

1.4 - MULTITRACKS!

1.5 - RELIABILITY!


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
return to top


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:
IF NOT(STATUS>$7F AND STATUS<$A0) THEN
Which should've been:
IF STATUS>$7F AND STATUS<$A0 THEN
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
return to top


McPepic 2022-09-22 00:29

@SP4CEBAR
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...
return to top


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

V1.9.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
    IF PLAYING(0,X)=PITCH THEN 
      VOI=X
      EXIT
    ELSE IF PLAYING(0,X)=0 THEN 
      VOI=X
      EXIT
    END IF
  NEXT X


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:

SUB PLAY_(V,N,O)
  A=$FF40+12*V
  POKEW A,O+16*16.35*2^((N-1)/12)
  POKE A+2,PEEK(A+2) OR %11000000
END SUB


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

Version 1.11


SP4CEBAR 2023-09-09 14:47 (Edited)

I'm in the process of refactoring the code so that I can make an API (which I will probably post as a new program). Anyway, when I made this MIDI program I would copy and paste code rather than make functions for it. I just found an inconsistency between these lines of the note scheduler:

Addressing this inconsistency in the code may fix some bugs, like the hanging notes on more complicated midi files


SP4CEBAR (formatted to look like a new post)

EDIT: It didn't fix anything unfortunately


SP4CEBAR 2023-09-09 20:07 (Edited)

Version 1.12 - LOADER REFACTORED


SP4CEBAR 2023-09-11 08:55 (Edited)

Version 1.12.1 - CORE REFACTORED


SP4CEBAR 2023-09-11 16:19 (Edited)

Version 1.12.2 - LOADER SEPARATED


SP4CEBAR 2023-09-13 17:32 (Edited)

Version 1.12.3 - CORE SEPARATED


SP4CEBAR 2023-09-16 07:55 (Edited)

Version 1.12.4 - CLEAR GLOBALS


SP4CEBAR 2023-09-29 13:40 (Edited)

Version 1.12.5 - CLEAN API

(the NX file is accidentally named "1.12.3")


SP4CEBAR 2023-10-04 09:26 (Edited)

Version 1.12.6 - IT'S TIME TO MERGE


SP4CEBAR 2023-10-04 15:05 (Edited)

Version 1.13 - THE API IS REAL!


nathanielbabiak 2023-10-04 21:30

These latest improvements make the code really clean!


SP4CEBAR 2023-10-05 07:09

thank you!
I found that organizing code and merging subprograms is really satisfying to do


SP4CEBAR 2023-10-07 08:54 (Edited)

Version 1.13.1 - SMOOTH ANIMATIONS


SP4CEBAR 2023-10-07 11:37 (Edited)

Version 1.13.2 - FAST TRANSCODING


McPepic 2023-10-07 13:52

What does it mean if I get:
Variable not initialized
V0=V0+256*V
?


SP4CEBAR 2023-10-07 14:34 (Edited)

It means that your file has a MIDI "E" command and that I missed a V when replacing all occurrences of "V" with G_BYTE (where "G_" means that it's global). The line should've been:
V0=V0+256*G_BYTE
Thanks for reporting this by the way!


SP4CEBAR 2023-10-07 15:17 (Edited)

Version 1.13.3 - OLD MODES MERGED


SP4CEBAR 2023-10-07 22:24 (Edited)

Version 1.13.4 - CLEAN UP


SP4CEBAR 2023-10-08 12:47 (Edited)

Version 1.13.5 - MIDI HEADER REVISIT


SP4CEBAR 2023-10-09 11:00 (Edited)

I think I could catch the hardest bugs by exporting the arrays of the MIDI SCRAPER to the disk and then comparing it to the output of a MIDI API in a programming language like Python

Funnily enough, I wanted to learn Python before I started programming (in LowRes Coder), but now I've basically learned and used every programming language but Python.


SP4CEBAR 2023-10-09 13:16 (Edited)

Version 1.13.6 - ROGUE PRINTS OBLITERATED


SP4CEBAR 2023-10-09 15:37 (Edited)

Version 1.13.7 - NO MORE J


SP4CEBAR 2023-10-09 16:27 (Edited)

Version 1.13.8 - "I" INFESTATION CLEARED


SP4CEBAR 2023-10-09 19:15 (Edited)

Version 1.14.0 - CLEANUP CONCLUDED


SP4CEBAR 2024-01-07 00:18 (Edited)

Version 1.15.0 - SCRAPE HUGE FILES


SP4CEBAR 2024-01-12 15:47 (Edited)

Version 1.15.1 - STRINGS ARE SUPPORTED


SP4CEBAR 2024-01-12 19:36 (Edited)

Version 1.15.2 - DEBUGGING TOOLS


SP4CEBAR 2024-01-12 22:26

Version 1.15.3 - EFFICIENCY


McPepic 2024-01-12 22:39

Awesome! I just got it to play the Tetris music and it sounds great. Good work @SP4CEBAR!


SP4CEBAR 2024-01-13 08:30

Thank you!


SP4CEBAR 2024-01-24 16:15 (Edited)

Version 1.15.4 - DEBUGGING


McPepic 2024-01-24 16:40

Argument count mismatch
SUB MIDI_QUANTIZE( G_FILE_OUT )


SP4CEBAR 2024-01-24 18:22 (Edited)

that one must've happened during the clean-up of the code, it has likely been there for a long time (I haven't touched or tested the quantization in a long time)


SP4CEBAR 2024-01-24 18:37

Version 1.15.5 - QUICK PATCH


Log in to reply.