Wednesday, January 5, 2011

Project Jumper Part 6: Sound; Bleeps Bloops and Frustrated Screams

OK, time to buckle down and get sound sorted out. You guys have no idea how super excited I am this. No idea.

Actually, for the most part it's not too bad. Yeah, Flash only lets you embed mp3 files. But a lot of the time, that'll work just fine, and if the limitations aren't anything that will affect you, then everything is gravy.

Obviously, we're going to need some sounds. Let's make a quick shopping list:
  • Background music
  • Player jump
  • Player death


Music
I'm not going to spend time or money making a good music track for this project. Sorry. Once upon a time, I had a couple sites bookmarked where free music was available. That was several computers ago, though, and that resource is gone. A little poking around, and I found a track I rather like called Scrolling Space by Caleb Cuzner over at Cartesian Paper Plane. Sticking it into the game is pretty easy. Just embed it into PlayState.as, and put

FlxG.playMusic(bgMusic, 1); // bgMusic is whatever you named the embedded sound file, 1 is the volume
someplace where it will only run once. The constructor is a good place. In my case, it didn't play first time. That's because flixel seems to remember your sound settings from one session to the next, and my game got muted. It took me a bit trying to track down a bug before I realized I just needed to unmute. That's the troubleshooting process at work right there.

Sound effects
Next up, some sound effects. I could go search the internet again for something to steal, but I want to show off something different this time. I'm going to use a program called sfxr. If you don't want to download it, there's a flash based version. The flash version actually works a lot better for me for some reason. There's really not much to it, just keep mashing buttons and playing with the sliders until you get a sound you like, then export it to a .wav file. Easy.
Except now we have a .wav file, and we need an .mp3 file. Going to need another tool for this. I'm going to use Audacity because it's free. Just load the .wav file, then hit file->export to save it as an mp3. So now I have a jump.mp3 and a death.mp3


Since both of the sounds are associated with the player, I'm just going to put them in Player.as.

[Embed(source = '../../../../sounds/death.mp3')]public var sndDeath:Class;
[Embed(source = '../../../../sounds/jump.mp3')]public var sndJump:Class;
And then it's just a matter of finding the places to play them. In the case of jump, I add

FlxG.play(sndJump, 1, false);
inside the if statement that handles jumping. Easy. Similarly, I put the death sound effect right next to the lines that emit gibs when helmutguy dies. At this point everything pretty much works. Testing tells me that the background music is balanced too loud, so I turn it down by about a quarter half. If the results here are acceptable, great. Done. No need to read any further. Here, give it a try and see for yourself.

Fixing it
Yeah, do you notice the problem? There's a brief delay between when helmutguy starts to jump and when the sound actually plays. It's not flixel's fault. It's a limitation with the mp3 format. The format requires a moment of silence at the beginning and end of the file. You can't get rid of it. Go ahead and try. So we're going to have to find some way to fix that.

The forced silence also affects any looping sound effects, like the background music. The music I chose doesn't loop properly to begin with, but even if it did there would always be a brief hiccup each time it loops.

There are solutions. Multiple solutions, in fact. I'm going to try out two different ones.
  1. Don't use an mp3
  2. Tell flixel to skip the silent part.
Both cases are easier said than done, but let's give it a go anyway.

Don't use an mp3
The basics to do this can be found over on flashgamedojo. Trouble is, most of that tutorial is how to do this in the Flash IDE. Which costs money. Money I don't want to spend. There must be another way. (If you DO have the Flash IDE for the love of god skip this section and spare yourself a headache. Just use the flashgamedojo tutorial.)

OK, seriously, I just spent two days trying to get various utilities to work. If you don't have the Flash IDE, then you're really just stuck with the mp3 format. All hope is not lost, though, because I did find SOMETHING that helps. Let's just change the name of this section to:

Fine, use an mp3 but make it work better
You'll need a utility called mp3loop. You'll also need the LAME mp3 encoder. They suggest the one that comes with winamp pro, but you can get one for free off of the audacity site that works just as well. However you get it, just put lame_enc.dll in the same folder that you put mp3loop. Then you just run the program, feed it your .wav file, and it will spit out an mp3 file that doesn't have such a bad gap at the beginning. It's not perfect, but in my case it cut a 50ms delay into a 10ms delay. At this point, I only notice the delay because I know it's there. I can live with it. If you'd like to compare the difference, give it a try.  In this version, pressing up plays the old sound effect, pressing W plays the new sound effect. See if you can tell them apart!

Yeah, I drove myself crazy over a very small gain. Let's just move on.


Make Flixel do it
Over on the forums, user Geti offered up a modification to the FlxSound class that will let you seamlessly loop embedded sound files. Unfortunately, the modification is on the 1BarDesign website, which is down at the moment that I'm writing this. When it's back up, I'll try to remember to come back and work on this.

Giving Wrapping up
Overall, I'm not really pleased with the progress on this update. I put a lot of work into researching ways to improve how sounds play, but by far the best answer I've come up with in all cases is 'just pony up for the Flash IDE, cheapskate.' I need to find something to work on that gives some tangible results to get my spirits back up. See you next time.

Edit: OK, I couldn't let this one lie and I attacked the problem again. Head on over to part 8 to see how to trim up your sound effects.

5 comments:

  1. thank you! very helpful!

    look forward to continuing

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. One issue that I ran into. When you import the .wav-->.mp3 sound effect into FlashDevelop, then it gives you this:

    [Embed(source = '../die.mp3', mimeType = 'application/octet-stream')]public var dieSound:Class;

    But this gave me the error:

    [Fault] exception, information=TypeError: Error #1034: Type Coercion failed: cannot convert Player_dieSound@510d161 to flash.media.Sound.

    Turns out you need to delete the mimeType in the Embed, so just change it to:
    [Embed(source = '../die.mp3')]public var dieSound:Class;

    More info here: http://flixel.org/forums/index.php?topic=1642.0

    ReplyDelete
  4. Yep, you can't use octet-stream. Basically, you embed things as octet streams if it's a format that Flash doesn't know. That will embed it as raw data, which you are then responsible for interpreting.

    For sounds, you want Flash to actually process it or it won't know that it's an mp3 file, and it won't know how to play it.

    FD shouldn't be including the mimetype bit when you insert an .mp3 file. But computers are mysterious things, and I can't guarantee it'll always get it right. :D

    ReplyDelete