Mixing sounds with haXe, the Memory API, and looping MP3s

Posted on September 13, 2010. Filed under: Uncategorized |


I started working on my own Sound manager, called the SampleTrackManager, for mixing and playing back music and sound effects in flash. I know there are quite a few Sound manager’s out there, but I was inspired by Joe Berkovitz’s standingwave project and the Alchemy work done on standingwave3 to synchronize playback of sounds. I played around with the Flash 10 SampleDataEvent when it first came out, so I figured this would be a good opportunity to make something useful with it. Plus I was kind of annoyed that I couldn’t play 32 Sounds in a for loop and have them synchronize because there’s some latency. 🙂

The goal of the Sound manager was to make it easy to play samples on different tracks so I could operate on them separately while still being able to choreograph them. The first version was in AS3 and while it worked the performance was terrible. Playing a single looping sample was 3 times slowing than playing a looping Sound instance, and while increasing the number of samples written to the SampleDataEvent helped performance it introduced latency. I suspected the all the ByteArray function calls for reading and writing floats in the inner mixing loop was slowing things, down since functions calls in Flash are very slow.

So I created a haXe version and utilized the haxe.Memory API which uses the new Alchemy opcodes. To my surprise I can now mix 64 samples using about the same amount of CPU as playing back 32 Sound instances! Wow!

Once I organize things, I’ll put the SampleTrackManager up on github. I have a hierarchical state machine I want to release as well, but that’s another post.

Looping MP3s
One issue I ran into while working on my test demo, was the infamous gap issue with mp3 playback. I did a little searching and found a solution posted by Scott Schiller for SoundManager2. It turns out that using the lame mp3 encoder’s –nogap options is the key to creating looping mp3s. I created a little bash script that works great!


# Creates a loopable mp3 from a looping wav.
# Example: loopMp3 input.wav output.mp3

mkdir loop_gapless
cp $1 loop_gapless/start.wav
cp $1 loop_gapless/mid.wav
cp $1 loop_gapless/end.wav
cd loop_gapless
lame -b 128 -h --nogap start.wav mid.wav end.wav
cp mid.mp3 ../$2
cd ..
rm -rf loop_gapless


— UPDATE: I’ve posted the code, the mp3 script, and a sample here:


Read Full Post | Make a Comment ( 3 so far )

Working on making isometric depth sorting fast and faster

Posted on December 26, 2009. Filed under: Uncategorized |

I’ve been working on an isometric game with my startup for the past couple of months. And we’re just about to release it to the public. Amongst other duties, I’m currently in charge of the iso engine making it work right (sorting) and run fast (sorting and rendering).

My initial attempts at depth sorting followed the steps of others. I tried to do some calculation to determine a depth ordering based on position and size of the iso object. It wasn’t till recently did I realize this only works on square objects because it can use a center point method.

Unfortunately, our game has rectangular objects. So I was searching around and came across a lot of different methods all of which were wrong in one way or another. Read some suggestions on sorting by unit tiles or splitting up art assets. All of which are too limiting as we had already committed to rectangle objects and had some assets. Finally, I got Jobe Makar’s Actionscript for Multiplayer Games and VirtualWorlds and studied his algorithm for sorting of objects. It’s correct and works great, but it runs very slowly and relies on flash’s display renderer for sorting. In book form, it’s way too slow.

Finally, taking some ideas from different places I created an algorithm that sorts iso objects by comparing them to each other giving an answer of front, back, or side. Then I manage the sorting on my own. With this approach we’re able to sort 200+ objects on the screen every frame. This is good enough for the majority of isometric games you see on facebook. Turns out the Maxhaus project had this algorithm done years ago and Zeh gives a good explanation of it here: http://www.stimuli.com.br/works/maxhaus/ The algorithm looks correct and runs decently but it’s an O(n^2) algorithm. We weren’t be able to achieve lots of tiny objects with this algorithm, but we designed around the issue.

With this algorithm in place I could put sorting to rest and move on. I wasn’t really happy with it, but it was good enough. So I’d continue thinking about the issue a couple hours every weekend. And then one night I had a dream about iso sorting. Over the next couple of weeks I discussed with colleagues to make sure I wasn’t delusional. Now we have a prototype of a much faster sorting algorithm waiting to be integrated into the game. It’s going to enable more objects on the screen and faster rendering times, and a more engaging world for the players. I’ll eventually share the algorithm, but for now it’s a significant competitive advantage for my small company. We have other players in our space with access to significantly more resources, and this is one of our best features so sharing will have to wait till we can turn the game into a success.

The real take away lesson for me was to not give up on the problem. I had a hunch that things could be better and I kept on working at the issue from all kinds of angles and breaking it down step by step.

Read Full Post | Make a Comment ( 3 so far )

StGit – Stacked Git tutorial for managing patches

Posted on June 26, 2009. Filed under: Uncategorized | Tags: , , , , , |

I’ve been using git for the past several months hacking away on a new project by myself for the most part, but a couple days ago I decided to branch to maintain a production, test, and dev version of the code base not to mention versions for different platforms. It reminded me of how at my old job everyone had their config settings in the same file, but they were using subversion.

It always seemed like an error prone way to maintain everyone’s settings. If someone inadvertently updated the file and you pulled the latest changes, you’d have to update your settings or hide them, and pulling changes was a hassle.

So I was thinking about how to keep configuration file changes private in different branches of my project. Luckily Yaakov Nemoy had already written a piece on it. Keeping Private config files Private in Git

Awesome. I wasn’t really familiar with git rebase, so the tutorial was a concrete example of how to use rebase compared to the man page.

But the after going through it, with my own project, I have to echo the sentiment in the comment by Peter Zei. So I decided to checkout Stacked Git which is pretty cool!

So below is a workflow on how to use Stacked Git, stg, to manage changes between your branches. You should already be familiar with git commands before diving in since some of the stg commands have the same names but different behavior than the git commands.


mkdir stg
cd stg
git init
vi README  # insert "init"
git add README
git commit -m "init"

# We've intialized the repo, now let's add our config file.
vi config # insert 'production'
git add config
git commit -m 

# Now let's branch for a development version
stg branch -c dev
# equivalent to : git checkout -b dev ; stg init
# we need to initialize every git branch for use with stg

# Let's create a new patch
stg new conf  # enter message: dev config settings
stg series # shows us our uncommitted patches
# Now modify the config file
vi config # replace production with development
stg status # shows that we modified config
stg refresh # updates our patch
stg show # shows our changes

# Now let's create a new patch, add a file to it and get it back 
# into master without sending along our config changes.
stg new add_code  # message: adding some code
vi Main.as # some code
stg add Main.as # or: git add Main.as 
stg refresh # this completes our patch
stg series 
# this shows our two applied patches 
+ conf
> add_code 
# Before committing we want to pop our conf patch
stg pop conf
stg commit # this turns our add_code stg patch back into a git patch and commits
stg push # pushes conf back on the stg stack

# We'll switch back to our master branch and merge the dev changes
stg branch master
git merge dev
git log -1 # shows the new patch

And there you go. Managing your config files is just a matter of popping and pushing a patch with Stacked Git. If you forget to pop before committing you can run an uncommit for the patches through conf, pop conf, and commit.

stg series
# blank from previous commit
git log # shows conf changes are 3 patches away
stg uncommit -n 3
stg series 
# returns
+ dev-config
+ added-x
> addedY
stg pop dev-config
stg commit
stg push

# Notice that the patch names for conf was changed.  Let's rename it
stg rename dev-config conf
stg series
+ conf 


Here are more links to get you started.

Read Full Post | Make a Comment ( 1 so far )

Wacky Pong

Posted on January 19, 2009. Filed under: Uncategorized |

I’ve been working on a flash, real-time, multi-user system with AMQP. The first app using the system is just pong. Sounds easy, but I haven’t see an flash, real-time pong game on the internet yet. Flash client side, neko for the server with RabbitMQ in the middle for messaging.

Things have been going well so far except for the debugging process. In general I can make do with the trace statement that haXe affords. It’s better than nothing, which is what Actionscript 3 would give me without components. However, debugging the effects of latency and lag compensation has been frustrating. Too bad I’m such a newbie with real-time, internet, game programming. Being forced to use TCP/IP doesn’t help either.

I was about to give up, call it Wacky Pong, and move on to another app, but it dawned on me that I could write a network simulator to gain insight on what is going wrong with the lag compensation. And doing so has given me insights on how to better architect the system.

Another way to gain better insight is to have been debugging tools. HaXe’s ‘trace’ isn’t good enough considering how buggy my code is. So I made a few updates to as3tohaxe and will start to convert AsWing to haXe over the weekends. Having a robust gui framework will be a boon to haXe, so I hope I can get some help with the conversion and testing.

As much fun as haXe is working on as3tohaxe in haskell is a nice change of pace. I might get a copy of Real World Haskell after all.

Read Full Post | Make a Comment ( 2 so far )

hxamqp: AMQP with haxe!

Posted on December 15, 2008. Filed under: Uncategorized | Tags: , , , , , |

It’s been a while since my last post, but the wait has been worthwhile. I’ve been working on converting Ben Hood’s amqp library for as3 with my converter. It’s been an educational experience on a couple of fronts getting more familiar with the issues of conversion from as3 to haxe, AMQP/RabbitMQ, and flash vs neko io issues.

The resulting library, hxampq, is up on github with a couple examples to experiment with.

While working on this I ran into issues with trying to map a flash lib to neko. Flash only has asychronous IO, while Neko is synchronous IO only. In my examples I create a thread to deal with the socket data and pass messages back and with neko’s Thread and Deque API.

In my tests, I ran into a latency issue with RabbitMQ. I was trying to send an empty message from a swf, to rabbit, then read that message from a neko server, send a message back to rabbit on another q, and have the swf read it. The resulting “roundtrip” time was measured over thousands of samples. I was getting terrible times anywhere from 7 to 60ms. I was running the servers on an Ubuntu VM on my local machine. Doing a direct connection from a swf to neko and sending bytes back and forth showed times of 3ms. It turns out that the issue is Linux TCP/IP related. The Nagle algorithm is buffering these tiny packets. The issue could probably be solved by sending a lot more data at once. So after enabling TCP_NODELAY in RabbitMQ (this should be the default now with 1.5.0 and on the repo), I tried sending data from one swf to another swf over RabbitMQ and got 3ms! But sending data to neko is still slow around 30+ms. Looks like I’ll have to tinker with the neko socket code to enable high performance tcp/ip options.

Read Full Post | Make a Comment ( 1 so far )

as3tohaxe google group

Posted on October 28, 2008. Filed under: Uncategorized | Tags: , , , , |

I’ve created a google group to discuss issues, features of as3tohaxe and the general love of haXe http://groups.google.com/group/as3tohaxe

Please feel free to join it and let the group know what you’re converting or running into any issues.

-Don Q.

Update: I’ve uploaded Windows and Mac OSX binaries to the files section of the google group.

Read Full Post | Make a Comment ( None so far )

Scrap Your BoilerPlate and Data.Generics for the Win!

Posted on October 23, 2008. Filed under: Uncategorized | Tags: , , , , |

I just updated as3tohaxe with a pretty significant change to allow transforming and querying of the AST. I was working in the translator code to add the ability to convert variable bindings with Number types a little more intelligently.

I wanted to convert this AS3:

        public function s(s:String = "hi", a:Number = -1.0, b:Number = 1):void{
            var c:Number = 0;
            var d:Number = 10.0;
            var o:Dynamic = {}; 

to this haXe:

        public function s(?s:String = "hi", ?a:Float = -1.0, ?b:Int = 1):Void{
            var c:Int = 0;
            var d:Float = 10.0;
            var o:Dynamic = {}; 

Notice how the Number types are changed to Int or Float depending on the initializer.

So I was about to embark on writing a bunch of tedious, error-prone, boilerplate code to deconstruct the nested and recursive AST nodes. The idea was to perform tests to get down to the bottom of the expression syntax tree to see if there was a float somewhere.

I wanted the code to look something like this pseudo Haskell:

hasFloat e = 
    case e of
        ACond a -> case a of
        .... more nested cases till we get to 
            TokenDouble _ -> True ... 
        otherwise -> False

But I stopped myself after taking a minute to look at the craziness of the AST just for a simple expression for -1.

ACond (CondE (AEUnary (UEMinus ([(TPos "" 8 63,TokenOp "-")],[]) (UEPrimary (PFFull (FPFPrimary (PELit ([(TPos "" 8 64,TokenNum (TokenDouble "1.0"))],[])) []) Nothing)))) Nothing)))


I realized and was hoping someone had dealt with this problem before and found a better way. So I started searching and landed on JP Moresmau’s blog where he talked about issues with nested records. My problem being nested/recursive constructors seemed to be on a similar boat. After more googling I came across “Scrap Your Boilerplate” which looked like a solution amongst others like polyP and Generic Haskell. I don’t know enough about Haskell to make an informed opinion on those, but SYB did the trick. And after more digging I found JP had posted about haskell’s Data.Generics.

Now I can write tests like:

hasFloat = everything (||) (False `mkQ` isFloat)
isFloat (TokenDouble x) = True
isFloat _ = False

which traverses the AST looking for floats.

I wish this were documented in the haskell tutorials. SYB is a lifesaver!

Read Full Post | Make a Comment ( 2 so far )

hxflickr now on github

Posted on October 21, 2008. Filed under: Uncategorized | Tags: , , , , |

Previously, I attempted to convert the AsWing project with as3tohaxe and decided instead to go after a smaller code base, the as3flickrlib. I spent the majority of the time dealing with converting the xml processing which as3tohaxe doesn’t handle (and I’m not sure ever will), but the rest of the codebase went through for the most part without a hitch. So my conversion efforts are now on github.

I’ve uploaded Adobe’s as3flickrlib and an example by Shang Liang converted to haXe as hxflickr. The library hasn’t been fully tested, but you should be able to have fun with it. Enjoy!

Next project is the flare vis kit!

Read Full Post | Make a Comment ( None so far )

Translating AsWing

Posted on October 14, 2008. Filed under: Uncategorized | Tags: , , |

Since the last blog post, as3tohaxe converter now has expression parsing, “as” converted to “cast ()” calls, and a program, as3tohaxe.hs, to run through a directory recursively and convert!

So I gave the converter the AsWing codebase as its first big test and ran into a couple problems.

The parser was bombing on some unidentifiable characters which turned out to be the UTF8 header sequence “\239\187\191” or EF BB BF in hex. At first I just tried removing those characters but couldn’t with vim because the character is “zero width”. So I used a hex editor, 0xED, and the parser ran without issue. So I’ve updated the lexer to handle the header as whitespace.

The second problem I came across was one file taking a particularly long time converting. I think it has to do with one of the statements which has a nested expression.

((((((((("GridLayout[hgap=") + hgap) + ",vgap=") + vgap) + ",rows=") + rows) + ",cols=") + cols) + "]");

I still need to verify this.

Update: The nested expressions were causing the slowdown. I removed redundant work being done by the parser and got a huge speedup.

Read Full Post | Make a Comment ( None so far )

Back from FlashCamp 2008

Posted on October 13, 2008. Filed under: Uncategorized | Tags: , , , |

We all had a terrific time at FlashCamp and got to see all the new features of Flash 10 and CS4 in action. Not only that, we walked away with trial copies, and we’ll be getting licenses too! The team I was on, “kitchen sink”, even won a prize for our efforts!

It was a crazy weekend from project conception to presentation, and we had a blast the whole time with our crackpot ideas. You can tell by the look on our faces. We used Flash 10’s IK for animation, dynamic sound, pixel bender shaders for tracking a light source, deco tool for snow, and along the way learned a ton and saw some really cool inspiring demos.

Here’s a shout out to team “kitchen sink” MT, Dennis, Pedro, Kenny, and James, and the Adobe guys Kuy, Tony, Richard, Justin, and Dom for being so cool and making the weekend a success!

Read Full Post | Make a Comment ( None so far )

« Previous Entries

Liked it here?
Why not try sites on the blogroll...