Reusable MOD Player in Flash with full source code released :-)

Discussion in 'Announcements' started by Bad Sector, Aug 4, 2008.

  1. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    Here it is, finally i managed to implement most commands and test them with MilkyTracker (which is accurate enough). A few commands (three to be exact) aren't implemented yet, one of them will be soon. But all of them are rare and most modules play without problem. Also commands about panning are ignored because there is nothing to pan - the playback is in mono.

    The player is written in haXe but it should be easy to use it with the normal Flash IDE (by generating the ActionScript 3 code with haXe's -as3 flag). If in doubt, just rewrite your game in haXe :D. The code is licensed under the zlib license, so you can use it without obligations.

    Have fun and tell me if you find any issues (with info on how to fix, if you know :)) or if you use this player in your games.
     
  2. lexaloffle

    Indie Author

    Joined:
    Jul 27, 2004
    Messages:
    207
    Likes Received:
    0
    Wow, that's very cool. It's enough to make me want to make games in flash.
     
  3. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    Would be nice if the readme would point out that there is also playBytes. Initially I thought you forgot to add something like that.

    Converting to AS3 sorta worked with haXe 2.0. It was necessary to change ModPlayer.as:230 to "var stamp : Number = haxe.Timer.stamp();" though (ambiguous reference to Timer).

    "modplayer.showTraces = true;" doesn't seem to work at all. It complains about some NPE. I was too lazy to investigate that further.

    Other than that it seems to work fine.

    Here is some embedded Flex example:
    Code:
    [Embed(source = '../music/suprex.mod', mimeType = "application/octet-stream")]
    private var ModClass:Class;
    private var mod:ByteArray = new ModClass() as ByteArray;
    [...]
    var mp:ModPlayer = new ModPlayer();
    [...]
    mp.playBytes(mod);
    
    Is there some easy way to make it replay the mod once it's done?

    Edit: Decoding this module takes about 50(!) seconds with the AS3 converted version. Whereas the haXe version only needs 3.4 seconds.
     
    #3 oNyx, Aug 4, 2008
    Last edited: Aug 4, 2008
  4. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    Well i can only think about one thing (which happened to Nicolas): your AS3 version has a debugging flag enabled and you use the debug version of Flash (perhaps you use IE?). Debugging flag in compiler + debug version = very slow decoding :).
     
  5. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    D'oh... I was using the standalone debug player. Didn't realize it's so much slower. It runs fine in FF and Opera for example. But it's debug-slow in IE6 and IE7... oh yea... I remember... I installed the debug ActiveX component.

    Oh boy... that stuff is free in Java. ;)
     
  6. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    I believe you can disable debugging output from somewhere. In haXe you have to *enable* it with -debug (i forgot it in the compile script and this is why in Nicolas' computer it needed 25-30secs to build it) and without it the speed is about the same in normal and debugging versions. I believe you can disable it somewhere in the AS3 compiler too.
     
  7. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    I only found "verbose stacktraces" which was already set to false. And there is also "optimize bytecode" which was already set to true.
     
  8. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    Wee! Made it loop! \:D/

    Code:
    // StartSound tag
    writeTagInfo(swf,15,2 + 1);
    swf.writeShort(1);
    //swf.writeByte(0); <- old
    swf.writeByte(4); //00000100
    swf.writeShort(65535);//2^16-1
    And here is a really short mod (6.4 seconds) for testing:
    http://kaioa.com/k/pot.mod

    Really great. With this piece of information at hand it should be also possible to create gapless mp3 loops without the Flash authoring tool (you can set start and end positions for looping there).

    Edit: Corrected the loop count.
     
    #8 oNyx, Aug 5, 2008
    Last edited: Aug 6, 2008
  9. Spore Man

    Indie Author

    Joined:
    Jun 19, 2007
    Messages:
    843
    Likes Received:
    0
    This is great, but is it restricted to 8 bit 22hz wav files like original MODs were??

    Game authors back in mid 90's stopped using MOD and moved on to S3M (Scream Tracker) and XI (FastTracker) in order to get 16 bit sound quality.
     
  10. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    Eh, S3M uses 8bit samples too (i was reading the specs a few hours ago with the intention to add S3M support at some point). The major difference of S3M vs MOD files back in the days were more channels (up to 32), but the MOD format was extended since then to support more channels to (my player supports 4, 6 and 8 channel MODs, but its a matter of adding 4-5 lines to support more). XM (XI is FastTracker 2 "I"instrument btw) do support 16bit samples, instruments with multiple samples, envelopes more commands, etc but they're way more complicated than MOD. It'll take ages (minutes actually) to render a XM file (it already takes more time to render a 8-channel MOD...).

    However 8bit vs 16bit when it comes to MOD files won't make a big difference really*. What matters more is playback rate and this is done in 44100Hz (the mixing is done in 22050 to increase rendering speed but its played in 44100Hz which gives cleaner sound). Many players at the past supported only 22050Hz playback because that was what GUS (a popular modscene card) supported with multiple voices.

    In any case, yes my player supports only the classic MOD format with the only extension of more than four channels (because it was easy to do). It can play also some MODs with extended octaves but it'll have trouble applying some effects (arpeggio basically) to them. However when making a MOD file, most trackers will warn about compatibility issues (well MilkyTracker does...).

    *=i'm talking about making Flash games here. Currently a good MOD file can provide much better music quality than most Flash games have these days while spending much less space (and bandwidth).
     
  11. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    Creating gapless MP3 loops this way is clearly possible. I even already know what needs to be done... but boy... it's a lot of messy work. It also would require looking up two numbers with Audacity (or whatever) for each MP3 file, but that's probably alright.

    I'll probably give it a whirl once this game is done.
     
  12. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    I'm not sure what you actually mean with "gapless MP3" but note that there is a latency between calling DynSound.playSound and the sound start playing, even for very small sounds.
     
  13. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    >I'm not sure what you actually mean with "gapless MP3"[...]

    You can only create gapless MP3 loops with the Flash authoring tool. The MP3 encoding process adds a little bit of leading and trailing silence which breaks loops. If you use the authoring tool and let it handle the MP3 compression (i.e. you use WAVs), it will insert a corresponding SOUNDINFO record with matching HasOutPoint and HasInPoint bits together with two UI32 values for number of samples to skip at the beginning and another one for the last sample to play.

    With those bits of information the Flash VM is able to loop an MP3 without any audible gaps.

    The idea is to mimic that behavior by injecting MP3s into dynamically created SWFs which contain these necessary pieces together with those frames from that MP3.

    >[...]note that there is a latency between calling DynSound.playSound and
    >the sound start playing, even for very small sounds.

    Yes, that's why my modification injects a SOUNDINFO record which tells the VM to loop it. So, you only get that very first delay and then it loops away.

    Edit: My modification only sets the HasLoops bit and then it writes the loop count... and uhm... it should write 2^16-1 instead of 2^32-1 :>
     
  14. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    Well, that modification makes that generated WAV loop flawlessly, but the generated WAV itself isn't necessarily perfectly loop-able.

    Say you play some sample at the last row of the last pattern. This means it will get cut off at the end of the song and this also means it will be missing at the beginning.

    If you want to fix that you would have to overwrite the data from the beginning (once you're through it) until you reach... end_of_last_sample % song_length.

    E.g. if the very latest end of some sample is at 1:02 and the song is 1:00 long, then you would have to mix from 0:00-1:00 and then from 0:00-0:02.

    Or you could start at the last pattern, then continue to the first (and start copying to the buffer) and continue till the end. Yea, that's probably easier.

    Basically you have to emulate those steps one would usually do in an audio editor:
    http://kaioa.com/node/47
     
  15. Mike Wiering

    Original Member

    Joined:
    Jul 28, 2004
    Messages:
    246
    Likes Received:
    0
    I think the problem with that is that you can't change anything after you start playing (I´d to change the SOUNDINFO during playback to allow intros and different endings).

    Bad Sector, would it be very hard to implement optional stereo sound (for users who with lots of memory who want high quality sound or for tunes like a logo sound or sound effect)?
     
  16. oNyx

    Original Member

    Joined:
    Jul 26, 2004
    Messages:
    1,212
    Likes Received:
    0
    Ehm... well, you don't. I was referring to the part where the WAV is generated.

    (The whole mod is rendered as monolithic wav before it's shoved into an swf which is then loaded... and the loading itself triggers the playback via special markers and with my modification the same also goes for the looping.)
     
  17. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    @oNyx:
    Yes looping is a problem. However i decided to look more into it in a next release because some songs do not loop from the beginning. I was thinking to use the last loop command (there is a MOD command that can be used to loop a song from a particular position) to loop more precisely (f.e. you could have an 'intro' part and then a 'main' part looping). But the 'cutting' problem would still exist because mixing the end with the beginning would only work for non looping samples (most MOD samples are looping though). If i was to see when a MOD ends, for those MODs (most of the cases really) it would never end.

    @Mike:
    Not very hard, but it'll be slower (double the data to fill). However since its optional, i'll add it.

    But i think for a logo or effect sound, you'll be better with a plain wav file.
     
  18. jetro

    Original Member

    Joined:
    Jan 21, 2005
    Messages:
    130
    Likes Received:
    0
    Could you consider implementing XM support, even if limited availability of effects? 16 bit samples sound much better (22 KHz 16 bit sounds better than 44 KHz 8 bit, although byte size is same).
     
  19. Bad Sector

    Original Member

    Joined:
    May 28, 2005
    Messages:
    2,742
    Likes Received:
    5
    I will implement XM support at some point when Flash10 is out and i can use the streaming sound API (Flash9 will still be there as fallback, since the same code will be used). However XM has many differences with MOD in the playback level.

    If all you need is 16bit sample support though, i can hack the player to load and use 16bit samples with MODs that use a special signature (FM16 - FlashMOD 16bit - for example). I'll also need to use a tool that converts MOD files to this format and loads the 16bit version of the samples from external files.

    However i'm still not sure if 16bit is what makes XMs sound better. XM have better sound mostly because of instruments (which can use multiple samples, envelopes and other fine tuning attributes). These will be VERY slow to precalculate in Flash9 (and i just hope that the Flash10 vm will be fast enough to do this in realtime).

    But keep in mind that i'm also developing a couple of web games right now and since this player does the trick for me, its not a very high priority :). However i'm also thinking at the future to write a special tracker for this limited files with extra stuff such as generated sound waves, multiple commands per channel, etc that will lower the file size while increasing the sound quality. But again this isn't a project that i'll start today so dont hold your breath :).
     
  20. tolik

    Original Member

    Joined:
    Sep 20, 2004
    Messages:
    1,407
    Likes Received:
    0
    Great stuff! This and popforge's bitboy (mod player as well) are very important steps towards much better flash games. This will revive importance of module music and make Flash games to sound much better with unlimited music tracks in small sizes. Hurray for oldskool!

    Just some more tips for people who want a very full robust support of any sound format in their downloadable product with Flash - saves resources and provides wider format support.

    Few years ago we did Audiere (open source library similar to BASS/FMOD) wrapper for mProjector - one of the Flash wrappers that has some cool features like AS extensibility through custom DLL modules! We have a separate thread playing the music in downloadable version of the game. Unfortunately mProjector is as unstable as other wrappers, but you get the basic idea.

    A great game called Betrapped ("Minesweeper quest" set in a setting similar to Agatha Christie) was one of the first Flash downloadable casual games on the market to extensively use their own custom Flash wrapper features during... AS1. File/registry saves and playing of MIDI files!
    Play this great game yourself http://www.oberongames.com/betrapped_static.asp
     

Share This Page

  • About Indie Gamer

    When the original Dexterity Forums closed in 2004, Indie Gamer was born and a diverse community has grown out of a passion for creating great games. Here you will find over 10 years of in-depth discussion on game design, the business of game development, and marketing/sales. Indie Gamer also provides a friendly place to meet up with other Developers, Artists, Composers and Writers.
  • Buy us a beer!

    Indie Gamer is delicately held together by a single poor bastard who thankfully gets help from various community volunteers. If you frequent this site or have found value in something you've learned here, help keep the site running by donating a few dollars (for beer of course)!

    Sure, I'll Buy You a Beer