PART I: The BasicsWant to see hear how FLOD sounds? Check out my
FLOD 3 Demo.
NOTE: Christian Corti just released FLOD 4. Like, just yesterday. This tutorial still works with the new version, though! Just copy the code from the "Flod 4.0" folder of the archive instead of "Flod 3.0".
I thought I'd write a tutorial showing how to play .xm and .mod music files using Christian Corti's Flod 3 library. Flod is really great, but the latest version doesn't really have any documentation, and there's no good "Getting Started" guide that I could find. mod and xm files are a great option for browser and mobile games, because they can pack a lot of music into a small file size.
If you don't care about reading the whole tutorial, you can downloaded the completed FlashDevelop project
here.
STEP 1: Downloading FlodFirst, we need to download the Flod source. We can get that HERE:
https://github.com/photonstorm/FlodNear the top of that page, on the right side, you'll see a tab that says Download. Click that, and download the source as a .zip archive.
Once the file's downloaded, open it up. Within the archive, you'll see a folder called Photonstorm-Flod-blablablabbbab.... And inside THAT, you'll find more folders:
Flod 2.0 Archive - contains old versions of Flod. We don't care about these.
Flym - Plays YM files, an old music format from Atari ST computers. We don't care about it for this tutorial.
Media - Contains some PNG files with the FLOD logo. Again, don't care.
Sample Tunes - Contains some songs that you can use for testing. You can use the .mod files in this tutorial if you like...
Flod 3.0 Flod 4.0 - This has all the code we'll be working with.
Open the Flod 3.0 folder. Inside it you'll find a folder called Neoart. Copy Neoart into your project's src folder:
STEP 2: Adding Flod to Your ProjectNow that you've got Flod in your source folder, you'll need to decide what class you'd like to play your songs from. For my games, I usually have an Assets class in the top level, where I embed all my graphics, sounds, and things like that as static constants. I like doing this because it lets me access all my assets globally:
A typical Assets class I'm going to embed all my Flod songs, and also create a function to play them, in this class.
First, we need to import some of Flod's classes, plus Flash's Bytearray class:
package
{
public class Assets
{
import neoart.flod.core.CorePlayer;
import neoart.flod.FileLoader;
import flash.utils.ByteArray;
public function Assets()
{
}
}
}
Now we'll create some variables to help Flod:
package
{
public class Assets
{
import neoart.flod.core.CorePlayer;
import neoart.flod.FileLoader;
import flash.utils.ByteArray;
//Variables for Flod 3:
public static var
player : CorePlayer,
stream : ByteArray,
flodisplaying : Boolean;
;
public function Assets()
{
}
}
}
"stream" is where we'll store the data of the currently playing module. "player" is the... thing that plays it. "flodisplaying" tells us if Flod is playing something.
STEP 3: Embed some songs!Before we can use Flod, we need some songs to play, right? If you want the songs I'm uisng, download the
completed project and look in the Assets folder.
I'm using one .mod, and one .xm, and I've placed them a subfolder within my project folder called assets:
Now we just need to embed them in our Assets class:
package
{
public class Assets
{
import neoart.flod.core.CorePlayer;
import neoart.flod.FileLoader;
import flash.utils.ByteArray;
//Variables for Flod 3:
public static var
player : CorePlayer,
stream : ByteArray,
flodisplaying : Boolean;
;
[Embed(source="../assets/zabutom - ergo-kalyptic chase.xm", mimeType="application/octet-stream")]
public static const Song_Chase:Class;
[Embed(source="../assets/vim-pot_boiled_lunch.mod", mimeType="application/octet-stream")]
public static const Song_Lunch:Class;
public function Assets()
{
}
}
}
You'll notice there are 2 dots ".." at the beginning of the file's path. That's because by default, the class looks in its own folder for files to embed. The ".." tells it to move up one level, so you can fine the assets folder.
STEP 4: Make a Global Function to Play Songs!Now let's make Flod work. We're going to create a function in our Assets class called "playSong:"
package
{
public class Assets
{
import neoart.flod.core.CorePlayer;
import neoart.flod.FileLoader;
import flash.utils.ByteArray;
//Variables for Flod 3:
public static var
player : CorePlayer,
stream : ByteArray,
flodisplaying : Boolean;
;
[Embed(source="../assets/zabutom - ergo-kalyptic chase.xm", mimeType="application/octet-stream")]
public static const Song_Chase:Class;
[Embed(source="../assets/vim-pot_boiled_lunch.mod", mimeType="application/octet-stream")]
public static const Song_Lunch:Class;
public function Assets()
{
}
public static function playSong(Source:Class):void {
}
}
}
We want to be able to access this function from anywhere we want, so we made it a public static function. The function ony takes one argument, "Source". "Source" will be whatever .mod or .xm file we want to play. Now we'll write some stuff in the function:
public static function playSong(Source:Class):void {
var loader:FileLoader = new FileLoader();
stream = new Source as ByteArray;
player = loader.load(stream);
player.play();
}
Now we're ready to test this thing! Since we can call our function from anywhere, let's try playing a song right when the game starts, and do it from our Main function:
package
{
import flash.display.Sprite;
public class Main extends Sprite
{
public function Main():void
{
Assets.playSong(Assets.Song_Lunch);
}
}
}
Now click the Test Project button...
...If you did everything right, you'll hear music. Pretty cool, right?
That's not enough, though! You want to be able to play more than one song. Let's add a keyboard event, so that you can pick a song to play by pressing the number keys:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Main extends Sprite
{
public function Main():void
{
Assets.playSong(Assets.Song_Lunch);
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyboardDown)
}
private function keyboardDown(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.NUMBER_1) {
Assets.playSong(Assets.Song_Lunch);
}
if (e.keyCode == Keyboard.NUMBER_2) {
Assets.playSong(Assets.Song_Chase);
}
}
}
}
With this, you can press 1 to hear "Pot-Boiled Lunch," and 2 to hear "ergo-kalyptic chase".
Don't test it yet, though! Flod doesn't automatically stop the currently playing song before it plays a new one, so we need to do this from our playSong function. Open up your Assets class and add this:
public static function playSong(Source:Class):void {
if (flodisplaying == true) player.stop();
var loader:FileLoader = new FileLoader();
stream = new Source as ByteArray;
player = loader.load(stream);
player.play();
flodisplaying = true;
}
Remember that flodisplaying variable we created before? We'll set that to true whenever we start a new song. We'll also check it before we start playing, so that IF a song is already playing, we stop it.
Now test your program. Press 1 or 2 to play either song.
There's one more thing we need to add: A global function to stop songs. That's super easy! Just add this to your assets class:
public static function stopSong():void {
player.stop();
flodisplaying = false;
}
Now we can add a Stop key to our main class:
private function keyboardDown(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.NUMBER_1) {
Assets.playSong(Assets.Song_Lunch);
}
if (e.keyCode == Keyboard.NUMBER_2) {
Assets.playSong(Assets.Song_Chase);
}
if (e.keyCode == Keyboard.S) {
Assets.stopSong();
}
}
Now when you test it again, you can stop the music with the S key.
You can download the complete project here:
Flod Tutorial Part 1 (for FlashDevelop)Some other things you should know:
-Songs with a lot of channels are pretty heavy on the cpu. I wouldn't use more than 10 channels for a typical game (although you can probably get away with 16-20 channels if you're not doing a lot of other cpu-intensive stuff).
-Playback of some songs can be buggy. Some things like vibratto and pitch slides can sound different in Flod than they do in the program you compose with.
-Flod doesn't correctly play .mod songs saved in MilkyTracker.
-Flod throws a lot of warnings when you compile, because a lot of its internal variables have no type declaration. I don't think this will cause any issues, but it's something to be aware of.
That should be enough to get you started. For our next tutorial, I'll show you how to change some of Flod's settings, and add volume control.
I might even do a little bit about writing songs in MilkyTracker, but until then, check out
01010111's XM Template with NES Samples. It's a great way to get started.