Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
In Mario Paint Composer you can create music just like in the SNES game Mario Paint, but with some new features such as having sharps and flats. If you like the SNES version, you should definitely check it out.
All songs you make are saved as text files, so this renders itself quite nice for converting other formats into this (simple) format.
I made a script that converts NSF music (music from an NES game) into a Mario Paint song, by first converting it into a MIDI file. Of course there are limitations such as the narrow note range of Mario Paint, but most songs can be played quite nicely. I made a version of Dr Wily stage 2 from Mega Man 3 here:
Link to video
For reference, here's the original song:
http://www.youtube.com/watch?v=GsqMYXqGAVw#t=19s
If anyone's interested I can give details on how these were made and share my scripts. I also take requests! :)
I hope to see other people's Mario Paint Composer work here too!
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
I just tried this song, and although it did work, it didn't sound very good. The notes are all over the octaves, so the Mario Paint version of it only slightly resembles the original song (since i have to increase or increase the octave in order to play them).
Interestingly enough, I had to use a bpm (beats per minute) of 3600 in order to play this song correctly - this is the highest possible bpm for NES songs, since an NES sound channel can't play more than one note per frame = 3600 notes per minute. The Dr Wily song I posted above had a bpm of 360.
This is incredible! What a neat idea! :D
I would love to have access to the scripts, but strictly to toy around, as I'm quite unfamiliar with the NSF and Mario Paint Composer formats. Someday, perhaps :)
How do tracks from games with expansion chips sound? If they're not too bad, I'd love to hear something from Gimmick! Perhaps Dr. Mario tracks would be better adapted, though...
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
I'm glad you like it! Here's a quick breakdown of how these are made:
1. The NSF file is converted to MIDI using the program NSF2MIDI (I use the english version 005a). This can be downloaded from Zophar.net. This is the first step where I rely on an external program to correctly convert the NSF music. I can only hope that nothing gets lost in translation, though I haven't been let down yet. I suppose this is where it gets decided if expansion chips sound gets included or not. I think not, because the Solstice main theme (which uses one, right?) doesn't sound quite right.
2. I'm a Matlab programmer, so the program that converts the MIDI file to MPC text file is a matlab script. The main Matlab toolbox I use is a MIDI toolbox that can be downloaded from
http://www.kenschutte.com/midi
3. Using functions from the toolbox mentioned above, Matlab converts the notes to a matrix where each row is a note being played, and the columns are the note number, start time, end time, sound channel, and some more (for us unnecessary) info. So this matrix contains all information about the song.
4. The last step is quite simple - since I know all the information about the notes, I tell the script the number of beats per minute of the song and the script assigns each note to a beat in the MPC song. This is the main script that I wrote. I don't know how familiar you are with Matlab, but I've uploaded the code here (maybe you can get a rought idea anyway):
http://pastebin.com/yMAAcALA
You should be able to just replace the infile argument to any MIDI you've converted from NSF.
I can select additional parameters to the program, such as bpm, what sound channels I want to use, and what instrument to use for each sound channel. The number of bpm is decided by a parameter I call beattime. A value of 1 means that one MPC beat is 1 frame, so the MPC song will then have 3600 bpm, and can thus play any song as mentioned above (at least in terms of timing, the notes themselves might be out of the range). Usually, a value of 6 is enough for most songs, which gives a bpm of 360. Too high a value will cause too many notes to be assigned to one beat, so you have to trial and error a little until you find the right bmp.
Also, here's Kid Icarus:
Link to video
I'm not sure what I'm doing wrong, but I've only had two successes so far... Some quick questions:
1) What exactly is MarioPaintArrList.txt? I have no such file, yet it seems the script wants to read from it. I have simply commented all related lines for now.
2) Sometimes, F was accessed in an out of bounds location (2nd dimension), which of course halted the script. I'm guessing this is because of the number of instruments in the track?
3) How does one set up MPC so that it realizes we've added a song to it? Editing the songlist file seems to do it, but very often, loading a file halts with a 'Script error; continue?' problem.
4) Long tracks seem to be split in many files. I'm guessing that is because of a limitation of the MPC format?
Thank you for the script, details and help! :)
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
Yeah, perhaps I was a little short in my answer.
This is a text file that contains all all available playlists, called "arrays" in MPC. It should be the Prefs folder in your Mario Paint Composer directory, otherwise my script should create it. An MPC song file can only have 384 beats in total, so most songs have to be split into multiple files. To solve this, you can put multiple songs in a so called "array list" that simply litsts all the songs you want to be played, like a playlist. In order for MPC to know what array lists that shows up when you click on "load array", you have to put the name of the array in the file MarioPaintArrList.txt. What my script does is simply to add the name of the array to the end of this text file so that it shows up when you look at what arrays you have available.
So, you shouldn't comment out this section, since it's necessary for MPC to know what songs it can load.
Yes, that would make sense. As of right now, the script is only intended for MIDIs that come from NSF songs. It could work for any MIDI file in theory, but I would need to tweak the script some - for example, right now it can't play more than one note at any time from one channel - this is no problem for NSF MIDIs but can be a problem for MIDIs in general. Of course, you can get a MIDI to work if you're lucky, but the script isn't intended for that (at least not right now)
Perhaps the next version of the script will be more general in nature. :)
If I understand this question correctly, I answered it in point 1 - the game knows what songs are available from what is in MarioPaintArrList.txt.
To give an example: Let's say you've made a song that is split up into text files metroid01]MarioPaint.txt, metroid02]MarioPaint.txt and metroid03]MarioPaint.txt. What you do(or rather what the script does) in order for MPC to know that you want to play these after each other is to make an array file, let's call it metroid]MarioPaint.txt. This file will contain the text
metroid01
metorid02
metroid03
i.e. all songs to be played. The Matlab script adds this the name of this array file to the list of available arrays automatically, and this is done between lines 124 and 134 in the code (the "arrlist"-part). I hope this made sense!
Yeah, see above. In my first version of this script I didn't know about this, so all songs I made had to be really short. I'm glad I found out about this feature!
No problem, good luck with this. In hindsight I should probably have commented the code better, but hopefully you can make some sense out of it.
Ahhh, somehow it is named 'MarioPaintSongList.txt' in my MPC version.
I only used it with MIDIs made with NSF2Midi... but so far I could only reproduce this with tracks from the StarTropics NSF.
Thanks! All this makes a lot of sense, but somehow I can't even make a usable MPC file anymore. I'm not asking you to, but if you want to try and figure out what's wrong, here's a file containing a modified & stripped down version of your script (mostly so it can run on my version of Matlab, which is 2006b). One notable change is the use of num2str instead of num2str2, since it doesn't appear to exist in 2006b, and I can't figure out the difference in their behavior.
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
I'm currently writing a more general version of this script that will (or at least should) work on any MIDI file. I will continue to test it, but if all goes well this script will replace the one you're using. Its code will be much more commented and won't call any home made external functions (such as this num2str2 that I've made). I'll let you know when this script is finished.
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
The first version of this new script is done.
http://pastebin.com/9tE9J30f
New features:
*Automatic bpm calculator. This works well in some songs, but it assigns too high a bpm for most songs. You can test it out for fun, but you probably want to manually set it if you want a correct bpm.
*Works on any MIDI file with any number of channels, and multiple notes per channel at any time.
If you find a MIDI file it doesn't work for (or works horrible for), please let me know.
Patashu: Yeah, it worked quite nicely with your songs, though I had to manually set the bpm. Here's the text data for "Patashu in the stars" if you want to hear it (you do know how to play this I hope?):
http://pastebin.com/MGVErPBi
Looks nice! :D Thanks!
Unfortunately, loading anything produced by this script in MPC provides an empty track. Somehow, if I copy/paste the track data into a song that "works" (such as mysong), it works fine. Which version of MPC are you using? The fact that I have a file "MarioPaintSongList.txt" and no "MarioPaintArrList.txt" seems pretty weird...
Anyway, here's a quick try!
http://pastebin.com/dRJdu6Ec
Also, I believe line 405 of your script presents a rather nice opportunity to use MPCfold :)
Joined: 4/20/2005
Posts: 2161
Location: Norrköping, Sweden
Ah, yes, you're right about MPCfold. :) Here's an updated version of the script:
http://pastebin.com/EaK6cJxt
I also added the variable "arrfile" so you can change the name of the array file if you find it necessary.
I'm using version 2.0. I got it from here:
http://www.unfungames.com/mariopaint/
The things I did just now in order to be able to play your song was (all this was done in the Prefs-folder):
1. Create a file SMB201]MarioPaint.txt and paste the song data here.
2. Create an array file called SMB2]MarioPaint.txt that only contained the text string SMB201.
3. Append the text string SMB2]MarioPaint* to MarioPaintArrList.
Note that the file names have to have this exact format - for example, at first, I accidentaly named the song file SMB201]MarioPaint.txt.txt (i.e 2 txt at the end), and this crashed the program. Perhaps you did something similar?
All this is done automatically by the program, so it is weird that it doesn't work. Please try again with version 2.0, and if you still have problems you can upload the files and I can take a closer look.
EDIT: Also, Super Mario World (I think this is my best one yet):
Link to video
Well, it seems to be a problem with MPC as I get an empty score when loading the SMB2 track using the steps you described. I doubt it, but perhaps some preference was saved by MPC in my registry and interferes with the process? I'm gonna try on another computer when I get the chance.
Thanks again!