http://www.mediafire.com/?4dvmtx4zzuu1xx2 Download a mostly-working version of MIDICraft! Run 'midicraft.py' as either a GUI (by double-clicking it or running through a command line without any arguments) or a CLI (check 'python midicraft.py --help')
Hi Minecraft forums.
I've been working for the past week on a project I'm calling MIDICraft—a Python program that takes MIDI files and converts them to Minecraft maps (via pressure-plate-activated note blocks). There was a lot of nonsense involved (who knew MIDI formatting was such a pain?) and I put way too much time into it, but it's coming along pretty great. Here's the first video I've made, a conversion of Aphex Twin's "Flim" (I made the MIDI myself a few years ago).
The timing is not perfect, of course, since it depends on framerate (which is suffering mostly because of the video recording), but other than that I'm pretty close. The MIDI file was edited a little to fix range problems (that 3-octave limit is kinda rough) and get some better instrument assignments (notice the bass at the end), but other than that was left alone—a MIDI created specifically for conversion could avoid these problems by specifically writing for Minecraft's specifications.
The code is terrible (and please, could someone who has experience with Python, Tkinter, and compiling or whatever help me to make it a little better?), but works pretty much as follows: mclevel.py is used for all actual manipulation, and someone's midi.py module does the (ugly) MIDI file read. A lot of ugly string manipulation gets the instrument, pitch, and timing information. Note boxes are created as either standalone (for single notes) or nifty redstone staircases (for chords, including notes with drums). The whole thing gets drawn on top of a pathway with pressure plates drawn down the middle for activation and fences to keep pigs out. It took probably around a minute to create the file above.
I've got a few bugs in this video—right now, there can be simultaneous instances of the same note, which you can hear in the Youtube when there are several simultaneous bass drum hits. These are a result of rhythms beyond the available level of precision being compressed into one step. I can avoid this by only allowing one instance of each note-instrument pair per step, but there's not much to do about its cause short of adjusting player speed (which isn't really what I want the program to be for). Likewise, rhythm tracks only work well at multiples of block speeds (which I measured at around 4 per second). Anything at 60 or 120 bpm is going to be fine (like the example above), but other tempos won't sound right with dense rhythms. Just a melody should work fine, though, since it's not depending on every single step.
I should also admit that I made a few manual adjustments once the level was generated. I shoveled the snow that had fallen on a few of the note blocks near the end, preventing them from sounding. I also had a few isolated instances of notes not sounding correctly (I'm unsure at this point if they lost the blocks that define their instrument or what), so I just removed those note blocks entirely.
So far, my GUI allows the user to select the pathway blocks, the staircase blocks, and pressure plate block. Obviously, it needs some sort of file dialog as well, and it'd be nice to have control over what world it manipulates and in which direction (although barreling through World 1's positive X axis is charming). Like I said, though, I'm pretty close! I'll upload the map generation code once I clean it up a little bit more and figure out how to package it into some kind of executable.
It would certainly be possible to do a commandline! I imagine it's a lot easier than trying to twist Tkinter's arm into making an ugly dialog window.
As I plugged through the mclevel.py InfDev code I realized that schematics would probably be smarter, but since I don't know how they work I just avoided them. I'll take a look once I'm confident that my code works fine, but it looks like most of the methods are the same.
I apologize that the syncing's so bad on the first video--I don't know if it got worse or if I just didn't notice it while uploading at 5am. I tried refilming in a higher definition but the recorder choked. I promise it's not a hoax, though, and that what you're hearing corresponds to what you're seeing (just not necessarily at the same time).
I understand that the idea of an automated music box is more attractive, but don't inverters take about a tenth of a second (or is it a fifth?) to send? This is the first work I've done with redstone, but my first experiments with vertical towers using inverters introduced a lot more unpredictability. I want to work on it in the future!
And let's say I'll have some sort of public code by Wednesday night I guess? I can get the GUI work knocked out and sure a commandline as well.
Usually the pressure plate sound has been edited out, but you can get around this without edits by putting some distance between listener+noteblocks and the floor plates. This is a little tricky in my mind.
I hope you didn't have a ton of problems with pymclevel. I know I haven't been keeping the "documentation" up to date but if you already know a few things about the level format you should be able to figure it out. Schematic files should be easier to work with since they aren't split into chunks.
pymclevel is pretty great, but I'm not going to argue that it's underdocumented. Tile entities are the trickiest thing, but that's just because they're sort of weirdly implemented in the first place. I also wonder whether a few of the block names are inconsistent with official names with regards to capitalization etc.? I could be wrong on that.
I'm not sure that I agree that the minecart method is "better"—it lower the amount of amount of work you have to do to play the song (so far as walking forward in a straight line is work), but it still requires pressure plates and has the inherent problems that Suo pointed out. Modifying my code to use cart-activated pressure plates shouldn't be very difficult, though, so I'll look at it tonight and see if I can add it as an option.
I removed my pressure plate sounds but I can't get all of my footsteps quiet. Sand and a few other blocks are fine but I still make noise on stone (which looks the best in my program) and dirt. I'll keep trying.
I'll also bump the thread in a few hours with another MIDI that shows the full process (normal map, code running, map with note block path, and playback). I feel like this is pretty impressive and it's not getting a lot of attention :sad.gif:
e: Oh, I did change one thing about mclevel. I needed chunks to be generated if they didn't exist, which it kind of looked like the code meant to do but didn't. It was a one-line change but it's a significant one.
Another video! This is execution of the program in real time (it's hard to tell—I could offer a few more clues that the program's actually running, and iShowU didn't even record the mouse beachballing for some reason). Actual playback begins around 0:57.
You'll notice that some bricks show up about halfway through. I think these are left over from trying to run the program while the chunk was still active (i.e., I forgot to back out to the menu screen before starting my first record attempt). I don't think they get in the way, although it's certainly possible!
Okay, here we go. Didn't get schematics working (how do you create a new one?) but hopefully the GUI and the commandline are both operational. Someone check this out soon and let me know so I can take it down if it's really not working the right way.
Hopefully I included all the other modules you need. You should be able to double-click midicraft.py or whatever for the GUI or check out "python midicraft.py --help" for the CLI.
e: apologies for the readme, i'm sure it's awful. it's 5:30am though
ee: I forgot to mention that it currently starts at the player position. Not really unexpected but worth mentioning.
Sorry, this is the side of Python that I have no idea about. (linkremoved) should work better, but I would appreciate anyone who knows what they're doing with packages helping me out with releasing these.
And Python is cross-platform, you just need to make sure you have it installed on your computer.
Download Python 2.6 (haven't tried other versions yet, but they could work. Any input, codewarrior?) from http://www.python.org/download/releases/2.6.6/. The program also requires numpy, which you can download from http://sourceforge.net/projects/numpy/f ... mPy/1.5.1/. You need a version to match your version of Python, so look for numpy-1.5.1-win32-superpack-python2.6.exe (if you're on Windows). Then you should just be able to double-click minecraft.py and the GUI should come up (hopefully it works, too).
Well, this is kind of a mess. Apologies to everyone for my inexperience with this. I'm going to close the thread (it would probably be best if a mod could delete it) and I'll make a new thread when I actually learn how to release working code.
Feel free to contact me with tips on releasingcode--I've literally never made a program for other people to run. I promise it works for me though!
I don't like that you pulled all of your download links.
Don't give up just because of a NameError. Releasing python programs to the general public is not something that's done often. The dependency thing is rough, but you can work around it (for Windows users, at least) by using py2exe to create a self-contained app with Python and all the dependencies bundled together. I've thrown together a small py2exe setup script for your program, but it's still not a perfect solution. The resulting app folder is 15MB with a ton of files, making it hard to locate 'midicraft.exe'. There are other technologies for packing down that folder into a single .exe file (UPX?) but I haven't tried them.
If this really was your first attempt at releasing public software, you happen to have chosen one of the least forgiving platforms to do it on.
Thanks for the kind words! I'm not giving up at all, I'm just at work and don't want people downloading nonworking code while I can't do anything about it. The worldnum error is from some code shuffling I did around 5am, so I'm not surprised it's screwing things up. I'm beginning to understand that Python is tough to release, and had already been planning to throw an executable together. I don't have nearly as much time to throw at it tonight, but I'm going to try and get it properly compiled and tested before uploading this time. I know I'm just making beginners mistakes, it's just frustrating after so much work. Thanks again for your help!