Xeen Wiki
Advertisement

MIDI Music vs FM[]

Oh. My. God! Like... seriously! So I was futzing with my MIDI writer, and I noticed that sometimes I would get "No instrument mapped to tone bank 0" warnings. Further investigation led me to note that my sound font was extremely incomplete, and not the least bit out of date. So I updated it, and... just... WOW! I had no idea how POWERFUL the MIDI music could actually sound. 15 years ago, MIDI sound fonts were crap, that's why I was working on the FM player. Today, it sounds like there's an entire orchestra playing just for me! Seriously, I played BIGTHEME and was just blown away. The FM version of SF05.M has NOTHING on the MIDI version.

--WizardStan 21:19, 28 June 2009 (UTC)

Your sound font? What OS/audio card are you using? I've been using "Microsoft GS Wavetable SW Synth" as my Midi playback device (installs by default with Windows XP, I think), which sounds fine.

Yep, SF05.M sounds much better in Midi. In fact, pretty much all the MM5 songs sound better in Midi. The biggest problem I've run into is, the FM versions (which I'm used to) don't have any of the percussion of the Midi versions, and in some cases, the percussion completely changes the sound and feel of the song (not always for the better, as in some of the MM4 songs).

-- Phynnboi 20:13, 9 July 2009 (UTC)

I run Linux by default, and only use Windows when I have to. As such, my synth of choice is the open source Timidity. A sound font is the definition of the wave forms of each instrument in the MIDI standard. Just like different character fonts look different to represent the same letter, different sound fonts sound a little different for each instrument. The default sound font, freepats, is entirely free and GPL compatible, but it doesn't sound the best, and has some missing instruments. I found a different sound font, composed of instruments which are not necessarily free for all uses but sound a lot better. Timidity can change its sound font with a simple config change. I have no idea how to do that within Windows.

The freepats sound font file is 28 megs in size. It might seem today that 28 megs is nothing, but 15 years ago that was a HUGE amount of memory to put on a sound card. I'd be surprised if the sound cards from the late 80s/early 90s had more than a 1 meg sound font. The amount of compression that would have been required to get it down that small would have also made them sound a lot worse, which is why my memory of MIDI is so unfavourable. But now, with a roaring 28 megs or more for a complete font, it's glorious and warm.

--WizardStan 20:51, 9 July 2009 (UTC)

Oh, and incidentally, the sound font file I'm using (SGM-150, you can google for it) is a lot more engrossing than the default Windows synth, or so I feel.

--WizardStan 20:53, 9 July 2009 (UTC)

Well, I found SGM-150 v2.01 (wow, I wasn't expecting 240MB!), but only the v1.40 Timidity .cfg file for it, so I don't know if I'm hearing what I'm supposed to be hearing. The overall sound is certainly smoother than the Windows synth, but it lacks almost all of the punch. The drums are much weaker, and the bass guitar is nearly invisible (heck, the bass, period, is just about invisible). SF05 is great example--the Windows synth version is far more powerful, IMO. On the other hand, the SGM-150 version of MM4's CASTLE song is much more pleasant to listen to (the vocal effects in the Windows synth version make it unlistenable).

-- Phynnboi 05:41, 10 July 2009 (UTC)

Alright, I've done a deeper comparison and the SGM-150 versions are way better. The main thing is, instruments seem to blend together much better. In the Windows synth versions, the instruments sound separated from each other, like they're all playing in different rooms or something.

I feel like I'm hearing the songs as they were intended, but truthfully, we're probably hearing them BETTER than the original musicians got to!

-- Phynnboi 05:54, 23 July 2009 (UTC)

M to Midi converter?[]

I don't suppose you've worked on an M to MIDI converter? I took a quick shot at it, but the note values in the M files often exceed 127, which is the maximum allowed by MIDI. When I compared an M and MIDI (dumped from DOSBox) of the same song, it looked like the note values in the MIDI were roughly half the corresponding note values in the M, but it was never exactly one half, and occasionally, the values were equal. So, I'm completely stumped.

-- Phynnboi 23:24, 24 June 2009 (UTC)

No, I haven't dealt with the MIDI portion of the M files very much. A .M file isn't even a MIDI file. It's a custom music format that contains instrument definitions and then a string of commands, the commands not having a 1:1 relationship with any of the Midi commands themselves. The instrument definitions include FM, MIDI, PC Speaker, and possibly a few others that I hadn't bothered to look into. It plays the different instruments in different ways depending on which driver was loaded. Personally, I found the FM music to sound the best, so once I worked out how to play back the FM instruments, I didn't go much beyond that. If there's demand, I'll certainly look into how to parse the MIDI portion of the .M file and create a MIDI file from that. If someone wants to have a play around with what I hacked together, download the source at http://www.rebirthofxeen.com/files/musictest.tar.gz It uses SDL and the same OPL emulator in DosBox. It compiles in both Windows and Linux.

-- WizardStan 00:31, 25 June 2009 (UTC)

I realize they're not the same; were they, I wouldn't be here asking about a converter! :)

What I did was parse an M file according to the specifications on the two related wiki pages here, parse a MIDI capture of the same song using a third party library, and compare the resulting dumps. The relationship between the two is actually very tight for a while. For instance, M instructions 0x2, 0x6, 0x9, and 0xA do, in fact, map 1:1 to MIDI events. Even most of the parameters are the same; only the note values are significantly different. It's not until M instructions 0x1 and 0x8 that the relationship really breaks down.

Anyway, thanks for the code; I'll check it out.

UPDATE: I compiled and ran the program but it doesn't make any noise. All I get are status updates, like these:

TEMPLE.M
Initializing SDL.
SDL initialized correctly
keyScale is 128 for instrument 0 on channel 0
keyScale is 128 for instrument 3 on channel 2
keyScale is 128 for instrument 3 on channel 4
keyScale is 128 for instrument 3 on channel 6
Hard quit requested.  Stopping.

I did notice in the code you did some extra parsing on the note value that isn't discussed on the wiki pages. It looks like you split the note value into two parts: The three most significant bits are the octave and the five least significant bits get mapped to some kind of frequency value (?). I don't really understand the frequency mapping. It looks somewhat similar to what's reported on the "Programming the...FM..." page linked off the M article, but the numbers aren't the same.

Do you remember how the frequency part of the note value works?

-- Phynnboi 15:04, 25 June 2009 (UTC)

You know, this might be a little easier if you were to create an account. Or you could even email me: wizard (at) houseoffire (dot) ca :P

Anywho, there's a bug in the code I posted. It's initializing the video system without creating a video window, which for some reason prevents the audio from playing. In musictest.cpp, the line:
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO)< 0) {
should be
if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_AUDIO)< 0) {
I'll have an updated download later tonight, but you should be able to make the change yourself.
As far as the extra processing, I assume you mean the noteToFreq function. I forget where I grabbed the algorithm from, but it's a clever way of turning a midi note (with 0 being the lowest, 127 the highest, and middle C at 60) into its FM frequency equivalent. Each octave is divided into 256 possible frequencies, so it does some funky shift math to turn the given note into an octave/frequency byte pair, stored in a 16 bit integer.

-- WizardStan 19:35, 25 June 2009 (UTC)

Ok, I've started looking at the Midi engine. It actually looks really easy. There's some tweaking with the notes that needs to be done, which I'll experiment with this weekend, but otherwise it shouldn't be too much problem. I've already started some experimental stuff using PortMidi (an open source cross platform Midi API) and hope to have an update by Monday.

-- WizardStan 05:23, 27 June 2009 (UTC)

Cool. Now that I've gotten DOSBox up and running, though, I've discovered something horrible. All these years, I thought it was the MIDI versions I was hearing; that's why I was working on that MIDI converter. Turns out I was hearing the FM versions! While the MIDI versions do sound more realistic, I was surprised at how bombastic they are: They practically consume the entire gameplay experience! I much prefer the mellowness of the FM versions.

I've run into a weird quirk with the M files. Some of them end in a big MIDI blob that lacks an 0xF7 terminator, and the M file itself lacks a pop instruction at the end. Your program refuses to even process them. This became an issue when I was trying to add some extra delay to the ends of songs for recording purposes. The songs with that quirk also tend to be the ones that most need a delay at the end, since they tend to loop immediately. Adding a delay and pop to the end of any M file with that quirk did not result in a delay (in the game). Maybe in your work with the MIDI player you'll figure out what's going on, there!

-- Phynnboi 02:12, 28 June 2009 (UTC)

Do you have an example? I've tried a handful of music files, and they all play just fine.
Incidentally, I added MIDI playback anyway, with a preliminary MID file writer. The file writer mostly works, but seems to get corrupt about 10 seconds into any song for some reason. I can't figure out why yet. It uses PortMidi, a cross platform open source midi API. I'll try and have a Windows binary online Monday or Tuesday for those that have trouble compiling libraries.

--WizardStan 04:21, 28 June 2009 (UTC)

I can't remember which files were doing it, sorry. It triggered the 'WARNING: Reached end of file. File should end with cmd 0xF with \"channel\" 0xF to indicate reset, or any other value to stop playing.' message is all I remember. SDL_INIT_VIDEO was still in, I think.

Also, I figured out that the quirk was actually my M parser's missing a few vital pieces. I compared my parser to your code and found a few places where I wasn't reading bytes and should have been (the wiki page claims there's no data bytes), and I wasn't moving around the M file at all in response to push and pop instructions (the wiki page isn't really clear on how to do it). It's fixed now, I think. At least, its dump of CASTLE.M makes a heck of a lot more sense, now. :)

So basically, disregard the last paragraph of my last post. I think I better bow out now before I make a bigger ass of myself. :P

-- Phynnboi 09:30, 28 June 2009 (UTC)

Ah, the warning. Yeah, when I was first investigating, the files all ended in 0xFF to reset, or 0xF0 to indicate a stop playing. After I did the initial code, I threw some more music at it and a few would crash at the end, simply because they didn't have this terminating byte. So if it reaches the end of the file and doesn't have a terminator, it throws up the warning and assumes the file should be looped, because that's what the game does.
I also have a tendency of figuring something out, coding it up, telling myself I need to fix the wiki, and then forgetting to do it. Sorry about that. I'll have a look and see if I can't clear up the file info. Alternatively, if you were to sign up, you could help contribute too, you know. :P

--WizardStan 12:56, 28 June 2009 (UTC)

I'm embroiled in a different revival project at the moment or I'd be more contributory. Plus, I don't seem to be very good at this at all. The project I'm on is a lot easier because I have the original C source code. (Which isn't to say it's easy. The C code is horrid--the second worst I've seen that wasn't intended to be bad. I'm not sure where someone gets the idea to #include 10 different .C files into a .H file, but I digress.)

In other news, I did a little research about the Roland sound options. What it amounts to is that there's basically two different MIDI versions of each song: an MT-32 version and a Canvas version. The former is poorly emulated (IMO), and is the version I was basing my "I hate the MIDI versions of these songs" rant on. The Canvas version is pretty good, though. This isn't terribly surprising, since the MT-32 isn't a general MIDI synth, but the Canvas is.

Anyway, I'm not sure if that will affect your work on the MIDI converter/player, but it's something to keep in mind.

-- Phynnboi 05:14, 2 July 2009 (UTC)

Good find with the Canvas/MT-32 thing. I was actually using what I think was the WaveBlaster driver (the filename is WAVEMUS) as the basis for my hacking, but intrigued by your note I investigate what I think is the MT-32 (driver filename ROLMUS) and the Canvas (CANMUS). Interestingly, they're all very close, but CANMUS had a few differences: most notably, it uses a different instrument set (Canvas references byte 25 of the instrument definitions while the other two use byte 24. FM uses the first 11 bytes to define its instruments, and the interceding 14 bytes are for PC speaker and the Pro-Audio Spectrum, supposedly) The Canvas driver also implemented another command in the M file which I had previously labeled as "skips two" because that's all it seemed to do: skip two bytes. Now I see it's used as a bank switch command to give access to more than just the basic 128 instruments. Without an actual Canvas to test against, the bank switching does nothing, unfortunately. Or maybe Windows is using some extended Midi magic and it is working, I can't tell. I'm sure it would sound a lot better if it could actually access the instruments it was intended for, rather than just the basic ones at any rate. As it is, some songs do actually sound better with the Canvas driver, but others sound better with the basic midi. You'll have to have a listen yourself.
Which brings me to my next point: xeenmusic.exe is the most recent update to my music player to date. Given a .M file as an argument, it will play the music. By default it plays the FM version of the music, courtesy of the OPL emulator I ripped out of the DosBox source. Given a -M argument, it will play the basic Midi version of the file. If you give it a -C option instead, it will play the Canvas version, with the slightly different instruments. Finally, if you have it playing Midi (with either -M or -C) and supply a final file name, it will use that filename to write the midi stream to before it actually plays the music.
For example, to play just the FM music for the tavern: xeenmusic TAVERN.M
To hear the Canvas Midi music: xeenmusic TAVERN.M -C
To hear the Basic Midi music and output a file: xeenmusic TAVERN.M -M tavern.mid
And so on. It currently plays it through whatever is the first midi device on your computer, usually the default software synth that comes with Windows I think. This should be fine for most users, but some users may have different midi devices they want to use: a different software synth they've installed (timidity for example), or if they actually have a sound card with an actual OPL3 chip (do they even still make those?) or a passthrough device if they want to play it to their Midi enabled keyboard. In those cases, I'll have to add some kind of selector.

To extract files from the CC data file, try extract.exe. It takes as arguments a CC file, and then the file you want to extract. Easy, no? Use the Filenames table to figure out which files you want and where they are.

Hopefully this all makes sense. Enjoy the music! And let me know if you encounter any problems.

--WizardStan 21:14, 8 July 2009 (UTC)

What do all the "Uh oh, interval is getting too small!" messages mean?

There are a couple of issues with the Midi file that gets written to disk with the -C option. The tempo of the Midi file is too fast (although oddly, xeenmusic.exe seems to play the Midi at the right tempo). Also, the volumes on the channels don't seem to be right (even when playing back in xeenmusic.exe). For instance, on MM5's SF05.M, the synth organ(?) should be quieter than the bass guitar, but isn't.

As an aside, the -M version seems to match up to the MT-32 version. It sounds a lot better if you have an MT-32 emulator.

Finally, out of curiosity, what did you have to do to convert the M note values to Midi note values?

-- Phynnboi 11:35, 9 July 2009 (UTC)

The notes are supposed to play ever 13.x something milliseconds. SDL doesn't guarantee that level of precision, millisecond like accuracy. You may not notice the difference between a few notes off by 3 millisecond or so, but over the course of a song, you'll notice that it is playing faster or slower. I wrote the timer code to do its best, pausing for as long as it needs to make the whole song flow: For example, the first note it is supposed to pause for 13 ms, but SDL only pauses for 10ms. After the second note, it sends a pause for 16 ms (the 10 ms it really did pause, plus 16 = 26 = 13+13), for which SDL actually pauses for 20 ms. The third time through, it sends a pause for 9ms, for which SDL pauses for 10 ms again. And so on and so forth. Due to the imperfections of the SDL timer, sometimes the delay drops to 0. That triggers the "interval getting too small" warning. It then plays the next note immediately without pause, giving an extra 10 ms to play with. Like I said, from one note to the next, the differences are so small that you don't notice, but over the course of the entire song, you'd notice that it wasn't quite right. At least I did. If your ears can detect the rare moments where the timer skips, then you are a super hero. ;) In the final product, all these warnings will be removed and you'll never know. Or I'll change to a different timer which guarantees better accuracy.

Unlike in the EXE where I have a timer I use to wait for the next note, the MIDI file format uses a "beats per second" and "message delta" time stamping system to know when to play the next note. 40 BPS seemed about right, though I guess it is a little fast. Should probably be closer to 30. I'll experiment some more when I get the chance. If you want, you can open a MIDI file up in a hex editor, change offset 13 from 0x28 to 0x1E or something to change the tempo from 40 to 30.

I'll take a look at the volume stuff. I may be sending the wrong messages to the synth for volume control. I know it doesn't work in FM, but I thought I got it working in MIDI.

Here's the code for converting the .M note data into a MIDI note value:

 Uint8 midiNotes[24] = {
 0x00, 0x0C, 0x0E, 0x10, 0x11, 0x13, 0x15, 0x17,
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
 0x00, 0x0B, 0x0D, 0x0F, 0x10, 0x12, 0x14, 0x16};
 Uint8 noteToMidi(Uint8 note)
 {
 	if ((note & 0x1F) > 23)
 	{ // A properly formatted music file should never do this!!!
 		std::cerr << "Encountered note " << (int)note << ".  note&0x1F = " << (int)(note & 0x1F) << std::endl;
 	}
 	Uint8 freq = midiNotes[note & 0x1F];
 	freq += (note & 0xE0) >> 2;
 	freq += (note & 0xE0) >> 3;
 	return freq;
 }

--WizardStan 12:33, 9 July 2009 (UTC)

Well, 40 is a little too fast, but looks like roughly half of 72.8. So, my guess is, the correct BPS should be exactly half of that: 36.4. I assume the value must be integral, in which case 36 (0x24) is as close as we can get. I tested it out and it's quite close. The adjacent values--35 and 37--are both off by quite a bit more.

You might want to just tweak the lengths of the notes you write out so that you can use whatever tempo you want.

-- Phynnboi 05:46, 10 July 2009 (UTC)

If you think 36.4 is the perfect tempo, I suppose I could multiply all the timings by 5: increase it to 182 beats per second, but make each delta 5 beats instead of 1. I can try it tonight, see what comes up.

--WizardStan 11:07, 10 July 2009 (UTC)

Good idea.

About the volume, here's part of a DOSBox Midi capture for MM4's OUTDOORS.M (it's some of the events from the only track):

control_change 0 1 7 76
control_change 0 2 7 64
control_change 0 3 7 106
control_change 0 4 7 106
control_change 0 5 7 81
control_change 0 6 7 97
control_change 0 7 7 97
control_change 0 9 7 50

These are volume change events. The numbers go 0, channel #, 7 (signifying a volume control message), and the actual volume.

Here's the corresponding part of xeenmusic's Midi:

control_change 0 1 110 0
control_change 0 2 110 0
control_change 0 3 110 0
control_change 0 4 110 0
control_change 0 5 110 0
control_change 0 6 110 0
control_change 0 7 110 0
control_change 0 9 79 0

I'm honestly not sure what those messages are doing, but they're definitely not changing the volume! :)

-- Phynnboi 18:45, 10 July 2009 (UTC)

I created an account and redid my signatures.

-- Phynnboi 22:02, 10 July 2009 (UTC)

Yeah, I've definitely been doing very wrong with the volume. I have no idea what I was thinking when I wrote those MIDI messages. It's such a simple conversion, only an idiot could screw it up. Oops :P

I'll update this weekend, rebuild, and should get the fixed binary online on Monday. Thanks for pointing all this out :)

--WizardStan 23:01, 10 July 2009 (UTC)

Or maybe this Monday? :)

-- Phynnboi 02:17, 20 July 2009 (UTC)

GASP! I seem to have been sucked through a hole in time to exactly one week in the future! You can download the updated binary at xeenmusic.exe and the source at xeenmusic-src.rar

--WizardStan 14:25, 20 July 2009 (UTC)

I went ahead and finished my own M-to-MIDI converter with the help of your source code. A few comments:

  • To get the right tempo, I used Midi format=0 and ticks=500, and multiplied midiTicks by 1000/72.8 (and rounded) before applying it to an event. (In my case, I only ever set midiTicks to a non-zero value in command 0x1, and then I burn it all up in the next Midi event.)
  • I think midiNote[] (in xeenMusic.cpp) needs 9 elements, not 8. At least, my program complained when the last element was missing. Could be I'm doing something wrong.
  • Also in xeenMusic.cpp, in case 0xF of musicInterrupt(), there's the if-statement "if (chan = 0xF)" which I'm pretty sure should be "if (chan == 0xF)". Ah, wonderful C. :)

-- Phynnboi 08:53, 21 July 2009 (UTC)

Or, use 182 ticks and multiply midiTicks by 5, like you said. Duh! :)

Seriously, though, I was trying to match up with the DOSBox dump, which the 500 and 1000/72.8 thing did really well (for some reason, DOSBox's MIDI dump uses 500 ticks). Comparing our programs' MIDIs against the DOSBox MIDI is a handy debugging tool. :)

Now I just need to find a way to make the songs end pleasantly. Many of them seem intended for looping, so cut off rather abruptly at the end. Maybe some kind of fade+delay command-line option? Hmm....

Anyway, thanks.

-- Phynnboi 10:27, 21 July 2009 (UTC)

There should only be 8 channels, the first 7 are instruments and the 8th is an "effect" or something, but I may have missed the 9th, so there may, in fact, be more going on in the music still that we don't quite have. No matter.
That if (chan = 0xF) thing is a little embarrassing. Fortunately its only purpose is to either repeat the music or stop it, and since most music is expected to loop anyway, it's easy to miss.

--WizardStan 10:33, 21 July 2009 (UTC)

The Canvas version has lots of events for chan=8 (MIDI channel 9). Your case 0x9 code will try to access midiNote[8] for those. (Unless I'm missing something.) (Beware also that you need patch-change events for that channel, at least according to the DOSBox dumps I'm comparing against.)

Incidentally, the latest xeenmusic.exe is now playing MIDI at the wrong tempo. It's always something. :)

-- Phynnboi 20:11, 21 July 2009 (UTC)

Hmm.... It seems that CANTHEME.M for MM4 goes up to channel 10 (chan=9), and CANTHEME.M for MM5 goes up to channel 11 (chan=10)! [insert Spinal Tap joke here] (I wonder if CANTHEME means "Canvas Theme". It certainly seems to make sense, what with all the channels.)

Also, have you found any songs that actually use command 0xB?

-- Phynnboi 21:53, 21 July 2009 (UTC)

I'll take a closer look at the channel stuff over the next few days. If nothing else, just increasing the notes array should be enough.

As for 0xB, it isn't used in any music files across Xeen. By this point I have extracted every single .M file and played it through my player, and with that cerr output, something would have shown up if it were. My guess is that it was used in MM3, and since the XEEN engine is based off the MM3 one, some things got carried over.

--WizardStan 00:02, 22 July 2009 (UTC)

Well, I'm pretty much done with my converter. Would you like to add it to the stash of Xeen-hacking files? It's a fairly readable Perl script that uses the MIDI-Perl module to create the MIDI file. It can also produce a textual dump of the M file. Lemme know.

(Yes, I often do binary hacking in Perl. What can I say? I'm a freak.)

-- Phynnboi 08:14, 22 July 2009 (UTC)

 For some games, including Xeen, the FM version of the music sounds better to me.  Is there a way to save a Xeen music file so that it plays back sounding like FM?  I'm hoping to include some of these pieces in an unrelated game mod I'm making.  I have mp3s of them, but they take up too much space.

--Naniyue 06:49, January 2, 2010 (UTC)

I actually wrote a program to play the music. Very simple, command line only, no GUI or anything like that. Download here. You'll need the extract utility (also command line, sorry, I'm lazy about GUIs) to get the .M files out of the .CC file. You can then play those .M files with xeenmusic.exe. It doesn't have the ability to save the output directly, but Windows Recorder has the ability to record what is being played. You start up the recorder, start it recording, start the xeenmusic.exe and you'll get a .WAV file that you can do whatever you want with.

WizardStan 15:38, January 2, 2010 (UTC)

Hi there, WizardStan! I've followed your work on the Xeen project for a couple years, but I've only recently gotten around to messing with the CC files and such. I created a C# application that can parse through the CC files and extract files, and so far it seems to be working well. However, I'm interested in the source code for the MIDI playback of the .M files, so that I can hopefully port this to C# (or C++, in which case, I'll write a wrapper around it) and listen to the files. WoX is one of my 2 favorite RPGs of all time (it shares the number one slot with Chrono Trigger), and the music is very dear to me.

I've read through the information you posted regarding the music playback, but I'm afraid I'm very ignorant on mapping the MIDI commands, and I'm not certain where to start on creating a player. Even if you don't want to re-post your source code, I'd love to have that music player Windows executable just to listen to the M files (which I can extract with no problem using the aforementioned utility I built).

If you're still monitoring this or working on this project, is there any chance you could post updated files? The links provided for all the utilities you've written (here and elsewhere, such as the gamefaqs forums, gamespot forums, etc) I would greatly appreciate it. Thank you for your time, and thank you very much for providing so much fantastic information on one my favorite games!

Sakairu 03:30, December 1, 2010 (UTC)

Ack. Code used to be available online, someone even turned it into a Winamp plugin, but my host suffered a catastrophic system failure and I never got around to reuploading it. Here you go, just for you. :) I've even included the updates I made to support FM (default), midi, or Canvas Midi (which is slightly different than regular midi for some reason)

http://www.rebirthofxeen.com/files/xeenMusicSrc.rar

--WizardStan 14:35, December 1, 2010 (UTC)

You, sir, are too generous! Thank you VERY much for providing that source code; I'm excited to review it, and I cannot tell you how much I appreciate your sharing it. As an aside, have you worked any further on your WoX 3D project? Also, is there anything that I can contribute to the project, perhaps?

Thank you again for the code and your generosity!

--Sakairu 16:58, December 1, 2010 (UTC)

Hi again! So after finally getting this compiled and running using VC++ (VS 2008), I ran the application only to be confronted with the repeated "Uh oh, interval is getting too small!" debug messages after the "SDL initialized successfully" message. Was this issue resolved? I read through the thread above, but I'm not sure if I missed something or not regarding that issue.

If you have any pointers about this, I'd love to read them. Thank you again for posting this source code; it was quite an exercise to get this running, and I would love to see this through to a successful run!

--Sakairu 20:18, December 1, 2010 (UTC)

"Interval is too small" is really just a debug message, you can safely ignore it.

Because the delay isn't guaranteed to be microsecond accurate, it tries to average the time it waits between notes to ensure the music plays more or less accurately, some notes just get held a few microseconds too long or short. Usually it pauses for less time than it wanted to (like it tries to delay 35ms, but only delays 30ms so those extra 5 are carried over to the next delay) but sometimes it pauses for longer than it expected to (like trying to delay 35ms but actually getting 40ms, that -5ms difference triggers the "interval too small" message). It's an SDL thing, unfortunately. There are better timers that are more accurate that can be used, but SDL's works well enough that I never bothered to look at what it would take to change. It shouldn't be causing any real problems with the output, so feel free to ignore (or even comment out) that warning.

--WizardStan 20:30, December 1, 2010 (UTC)

Thank you for the prompt response! When I run the application, the machine on which I run it slows to a crawl, but nothing happens. No music output or anything, and it pops up my debugger dialog, though I cannot load anything running in memory for this instance. Once I set the debugger to a new instances of VS 2008, it then runs the debug messages in the command window and continues running sluggishly. When I feed in a mid file name (such as bigtheme.mid), the same thing as above happens, though I don't always get the debugger window to pop, and when it finally completes (takes a few minutes), there is a 0 byte file called bigtheme.mid that, of course, contains nothing.

Am I missing something here? Everything has compiled properly (with warnings, but none of which seem like show stoppers), but when I attempt to run the music, it just hangs while processing until it completes. Do I need a different midi outputer other than the Microsoft MIDI Mapper or the Microsoft GS Wavetable SW Synth (Geez, maybe I should just run on Linux and be done with it, huh)? i compiled SDL just fine, and I compiled PortMIDI just fine, and everything seems to init properly, so I'm not sure what I've done wrong here (though I'm sure I've done SOMETHING wrong, obviously).

Again, I really appreciate your feedback on this, and thank you for your responses.

--Sakairu 20:50, December 1, 2010 (UTC)

Can't imagine what you've done wrong. Are you sure you are loading a properly extracted .m file? I don't think I added any intelligence to make sure it's a valid file, so it will simply plow through whatever file you give it as best it can, which will generally not result in anything useful.

Here's the executable I just built: http://www.rebirthofxeen.com/files/musictest.exe

It's big because I had debug options on. Optimized should only be a few hundred K, but I like leaving debug on just in case.

--WizardStan 22:15, December 1, 2010 (UTC)

Evening, Wizardly One. Okay, so running your binary with my sdl.dll and my portmidi.dll runs fine. Therefore, I've done something wrong with my VS 2008 C++ build. I'll try and figure out what I did wrong. In the meantime, your music test works awesomely, and I've extracted the requisite M files to hear some fantastic stuff with it! So far that means my CC file break out software works well (thanks to your awesome instructions in this wiki!), and now I just have to figure out what I did wrong in my compilation of the music test source code you sent me.

Thank you again for your feedback, Stan! You have provided so much, and I really appreciate it. I'll get back to you on here when I make some progress on this mishap. I'm sure I just did something wrong--perhaps in my preprocessor setup or maybe I've linked some incorrect files. *shrug* Thank you again!

--Sakairu 03:29, December 2, 2010 (UTC)

Well I'll be... I switched to a debug build from a release build, included everything the linker needed, and voila! It works! My debug exe is very small compared to your build (84K vs ~1.9M), but it works like yours does, and that is wonderful. I'm going to play with this some more to see what I can do with it. Thank you yet again, WizardStan, for all the work you've put into this wiki, and for taking the time to share this code with me. I truly appreciate it, and if there's anything I can do to help with this effort, please let me know.

--Sakairu 04:32, December 2, 2010 (UTC)

Huh, that's weird. Not the first time I've seen debug succeed where release was failing, but usually those are quite complex processes with a lot of memory manipulation going on. Oh well, glad you got it working. I'm curious as to how yours is so compact though. Even the release build was 300K. Now what am I doing that results in such a large executable? :P

Real life kinda swamped me, and laziness and lack of motivation carried me further away from the project. I keep saying I'll get back to it soon. Maybe this week will be the week. :)

--WizardStan 14:19, December 2, 2010 (UTC)

No worries on the project getting away from you; that happens to everyone. Reality has that effect! As to the debug and release versions behaving differently... I couldn't tell you why that is, and I don't know why my build is so much smaller, to be honest. I'm not creating managed C++ code here; I'm also not using MFC, nor am I using precompiled headers. Do you incorporate any of the SDL or Portmidi stuff in your build directly? I'm just linking them in. I still haven't gotten a release version to work, but I've been slammed with work the past two days, so I'm a bit slow right now, too!

Which dev tools do you use to compile? Do you just compile with GCC? Any special compiler flags for your Windows builds? Just wondering.

Thanks again for checking in and for the code!

--Sakairu 15:16, December 3, 2010 (UTC)

I was taking a look at your M reader to get started on reading sound effects from the music drivers, and I noticed some missing notes in some FM songs (OUTDOORS.M in clouds, for example). After some experimentation I figured out that the fault was with the FM synth library you were using, not the xeen decoding itself. I switched the synth out for fmopl and now everything sounds perfect.

Mrspathi 04:48, March 5, 2012 (UTC)

I sure would like to get a copy of the code that converts M files to MIDI. Sadly the links mentioned above seem to have died. Can anyone suggest a way to get a copy of the conversion code discussed in this thread?

StephenPerrin (talk) 20:03, May 25, 2015 (UTC)

Hi Stephen, the code is still there I just moved it to its own directory.  Try http://rebirthofxeen.com/files/xeen/musicTest.tar.gz

WizardStan (talk) 20:11, May 25, 2015 (UTC)

Or it was this one: http://rebirthofxeen.com/files/xeen/xeenMusicSrc.rar

WizardStan (talk) 20:14, May 25, 2015 (UTC)

Thanks WizardStan! I hate to mess up this wiki page with the trivialities of my current problem accessing your site. If you would like to pursue it in email you can reach me at stephen underscore perrin at att.net When I ping rebirthofxeen.com DNS translates the name into 74.54.91.226. But no pings are replied to. My web browser can't access any URL that starts with rebirthofxeen.com.

StephenPerrin (talk) 20:57, May 25, 2015 (UTC)

Try www.rebirthofxeen.com.  You won't get any ping replies because it is configured not to respond to pings.

You may need the www just for your browser to resolve it properly, I dunno, it works fine for me both ways, but if you can't get it to work I'll email you the files.  Actually I'll just do that now, save the trouble.

23.91.132.60 21:44, May 25, 2015 (UTC)


Is there a way that someone could get me the most-recent version of xeenmusic.exe? The rebirthofxeen website only gives blank pages. Please send to lord UNDERSCORE skylark AT yahoo DOT com

199.27.190.12 04:13, October 5, 2016 (UTC)


Sorry for the bad edits. I think the file you are looking for is: http://www.rebirthofxeen.com/files/musictest.exe

The directory structure can still be browsed on: http://www.rebirthofxeen.com/files/

MagicLizard (talk) 20:52, December 15, 2016 (UTC)

Advertisement