## InParticular – Three JS WebGL test

So I finally got around to checking out the brillaint Three.js, the 3D JavaScript Engine, by the incredible Mr Doob. It’s really easy to pick up, even for a JavaScript novice like me – and the performance (WebGL in chrome) is absolultey astounding.
Three JS has a few different renderers –

• Canvas Renderer
• DOM Renderer
• SVG Renderer
• Sound Renderer
• WebGL Renderer

In these demos, I’ve been using the Canvas Renderer and the WebGL Renderer.

Here’s a brief wikipedia defintion of each –

### The Canvas Element

The canvas element is part of HTML5 and allows for dynamic, scriptable rendering of 2D shapes and bitmap images. It is a low level, procedural model that updates a bitmap and does not have a built-in scene graph.

### WebGL

“WebGL is a Web-based Graphics Library. It extends the capability of the JavaScript programming language to allow it to generate interactive 3D graphics within any compatible web browser.”

Canvas is nice – but WebGL is fast. Really fast. Here’s a video of my first Three.js experiment – InParticular.

Note – The screncapture software I used caps the video at 22fps – it actually runs faster – usually at around 35 odd FPS and is much smoother than the video appears. I’ve also optimised a little since I recorded the video.

Here’s a few stills i’ve taken from the app –

I really enjoyed using WebGL – but a major drawback is varying browser support and speed. WebGL should be supported by all the latest browsers – although for me, the only browser that ran it at a good framerate was Chrome.

Table from – http://findmebyip.com/litmus

## Try it out for yourself – http://lawriecape.co.uk/threejs

The first version you see in the video is a demo file included with Three.js. Not being overly familiar with JS, I used this as my starting point. I’ve put the demo up for you to see too – it’s the “Original Mr Doob demo version”.
In the demo – canvas_lines.html – white particles are placed in a 3d scene and connected by a line.

I built upon this, to set the particle positions using some basic 3d maths, adding some varibles, a GUI and some colour options.
The basic maths used for positioning the particles is based on a question from stackoverflow.com – Plotting points round a sphere

The forula given was –

x = r * cos(s) * sin(t)
y = r * sin(s) * sin(t)
z = r * cos(t)
here, s is the angle around the z-axis, and t is the height angle, measured ‘down’ from the z-axis.

I gave this a go, but I’m not great with maths. I ended up assigning a variables to the following –

• The initial T-Angle
• The initial S-Angle
• A step variable by which to increase the T-Angle by for each step in the loop
• A step variable by which to increase the S-Angle by for each step in the loop

It’s probably terrible, ActionScript style JS but here’s the loop code I used to lay out the particles –

```for ( var i = 1; i < = _numBalls; i ++ ) {
particle = new THREE.Particle( material );

_tAngle += _tStep;
_sAngle += _sStep;

particle.position.x = _radius * Math.cos(_sAngle) * Math.sin(_tAngle)
particle.position.y = _radius * Math.sin(_sAngle) * Math.sin(_tAngle)

particle.position.normalize();
particle.position.multiplyScalar( Math.random() * 10 + _radius );
particle.scale.x = particle.scale.y = 5;

geometry.vertices.push( new THREE.Vertex( particle.position ) );
lGeometry.vertices.push( new THREE.Vertex( particle.position ) );

}
```

## Right hand side - What's DAT

For a nice, quick interface for altering varibles and calling functions, I used the brilliant DAT.GUI.
It's a brilliant tool that will sit in with other UI frameworks I love using, such as MinimalComps (for Flash) and ControlP5 for Processing).

I also added in some keyboard shorcuts - indicated by a letter in brackets on the GUI menu.

## Pro tips

• A decreases the color variable
• S increases the color variable

## Notes

You have to redraw the scene for changed varibale to take effect.

Randomising the scene clears any current objects.

"Redrawing" draws the scene again over the top of the current scene. So you can try decreasing the radius and color values, then redrawing, to add another copy of the structure inside itself!

The canvas version offers a ghosting effect - deselect "clear canvas" and select "ghosting" to see it in action. It gives the nice smooth, blur images seen in the Flickr Set. For some reason though, it removes the particles. I'd love to get the ghosting to work in the speedy WebGL version - but that's still a work in progress.

The canvas version's image export does not include the solid black background color.

## TIP TOPS - Further development links

Phew! That turned out to be a rather long post - by my standards anyway.
If you get any nice screenshots, I'd love to see them. Or if you have any requests, or optimisation suggestions - get in touch.
Cheers!

## Musical Scales as midi note numbers.

For a couple of audio projects, I needed some nice musical scales, in midi note format (0-127). I couldn’t find a good list online, so had to knock together a quick script to trace some out. Here’s some that I’m using in a current project, and also the AS source to find any other ones you may want.

Using this PDF as a guide – http://8.brm.sk/Scales_Chords.pdf – enter the scale name, and the notes which are active in that scale. For example, the first scale in the image below, the Adonai Malakh (Israel), we would set the code as –

```//Enter scale name -
//Enter the notes in each octave to use - see - http://8.brm.sk/Scales_Chords.pdf
var acceptedArray:Array = [0,1,2,3,5,7,9,10];
```

Which would give us the output –

`var AdonaiMalakh(Israel):Array =[48,49,50,51,53,55,57,58,60,61,62,63,65,67,69,70,72,73,74,75,77,79,81,82,84,85,86,87,89,91,93,94];`

```//Enter scale name -
var scaleName:String="Zirafkend";
//Enter the notes in each octave to use - see - http://8.brm.sk/Scales_Chords.pdf
var acceptedArray:Array = [0,2,3,5,7,8,9,11];

var octaveStep:int=0;
var finalArray:Array = [];

//You can limit the scales to any length - it will retrieve the middle section of the scale.
var limitArray:int = 32;

for(var i:int=0;i<12;i++){
for(var j:int=0;j
And here's some scales. These are chopped to the middle 32 notes in each sequence.
var BiYu:Array =[24,27,31,34,36,39,43,46,48,51,55,58,60,63,67,70,72,75,79,82,84,87,91,94,96,99,103,106,108,111,115,118];
var Blues:Array =[41,42,43,46,48,51,53,54,55,58,60,63,65,66,67,70,72,75,77,78,79,82,84,87,89,90,91,94,96,99,101,102];
var BluesDiminished:Array =[48,49,51,52,54,55,56,58,60,61,63,64,66,67,68,70,72,73,75,76,78,79,80,82,84,85,87,88,90,91,92,94];
var Dorian:Array =[25,27,30,32,34,37,39,42,44,46,49,51,54,56,58,61,63,66,68,70,73,75,78,80,82,85,87,90,92,94,97,99];
var FullMinor:Array =[51,53,55,56,57,58,59,60,62,63,65,67,68,69,70,71,72,74,75,77,79,80,81,82,83,84,86,87,89,91,92,93];
var HarmonicMajor:Array =[44,47,48,50,52,53,55,56,59,60,62,64,65,67,68,71,72,74,76,77,79,80,83,84,86,88,89,91,92,95,96,98];
var Hawaiian:Array =[39,43,45,47,48,50,51,55,57,59,60,62,63,67,69,71,72,74,75,79,81,83,84,86,87,91,93,95,96,98,99,103];
var IonianSharp5:Array =[45,47,48,50,52,53,56,57,59,60,62,64,65,68,69,71,72,74,76,77,80,81,83,84,86,88,89,92,93,95,96,98];
var JazzMinor:Array =[45,47,48,50,51,53,55,57,59,60,62,63,65,67,69,71,72,74,75,77,79,81,83,84,86,87,89,91,93,95,96,98];
var Lydian:Array =[45,47,48,50,52,54,55,57,59,60,62,64,66,67,69,71,72,74,76,78,79,81,83,84,86,88,90,91,93,95,96,98];
var Major:Array =[43,45,48,50,51,52,54,55,57,60,62,63,64,66,67,69,72,74,75,76,78,79,81,84,86,87,88,90,91,93,96,98];
var Mixolydian:Array =[45,46,48,50,52,53,55,57,58,60,62,64,65,67,69,70,72,74,76,77,79,81,82,84,86,88,89,91,93,94,96,98];
var Oriental:Array =[45,46,48,49,52,53,54,57,58,60,61,64,65,66,69,70,72,73,76,77,78,81,82,84,85,88,89,90,93,94,96,97];
var SuperLocrian:Array =[44,46,48,49,51,52,54,56,58,60,61,63,64,66,68,70,72,73,75,76,78,80,82,84,85,87,88,90,92,94,96,97];
var VerdiEnigmaticAscending:Array =[46,47,48,49,52,54,56,58,59,60,61,64,66,68,70,71,72,73,76,78,80,82,83,84,85,88,90,92,94,95,96,97];
var Zirafkend:Array =[48,50,51,53,55,56,57,59,60,62,63,65,67,68,69,71,72,74,75,77,79,80,81,83,84,86,87,89,91,92,93,95];

I've also put the code up on Wonderfl - so you can use it straight from your browser.
```

## Kinect – OpenNI and NITE

After a long battle with various installer packages and drivers, I finally got OpenNI, NITE, and the Kinect working with Flash.
This means that I can now access the skeleton data from users, and make fun things like this –

On the whole, this guide is a good resource for getting everything setup correctly, although I did still have lots of issues.

## Kinect Flash Tests

So this site has been down for a few days whilst I sorted out some issues with the hosting company, and a few emails have been lost/bounced – but everyhting should be sorted now. That’s also why this post is a couple of weeks late.

Anyway, a few weeks ago, I managed to free up some time to try and get our office’s shiny new Kinect working with Flash. We’d seen so many amazing videos of the things people were doing with it, that we thought we’d give it a go. it was a bit of a pain to do, but pretty fun to play with once it was all hooked up properly.

As far as I know, there’s currently 2 ways to go about getting your Kinect to work with Flash, both of which are community projects, as the official Microsoft drivers and SDK are yet to be released. So currently your two options are OpenKinect and OpenNi. I think both can work with Flash, however the following demos are all using OpenKinect. If you’re starting from scratch however, I’d suggest checking out OpenNi, as it allows access to the skeleton data of your players.

Here’s a brief video of some of the experiments I made –

Getting started –

Download and install the kinect drivers – for the camera, microphone and motor of the Kinect.
All available from the AS3Kinect page –
http://www.as3kinect.org/guides/openkinect-win32-wrapper-guide/

If it doesn’t run, follow the comment of Shaun Husain –

I was having trouble getting the binary running on Vista, it was complaining that libusb0.dll wasn’t made for windows or something along those lines, coming up in an alert, to fix it I just downloaded libusbwin32 from here http://sourceforge.net/project… and pulled out the libusb_x86.dll and renamed to replace libusb0.dll in the as3kinect folder and it worked out fine. Thanks for making this happen Juan very cool stuff I’ve recently seen the demo of controlling XBMC so I threw together a Flex project to send the appropriate messages along to XBMC, now going to implement it using as3kinect.
Thanks again,
Shaun

Here’s the AS3-Server app, which has to be running for Kinect to communicate with Flash-

The AS3 Server package also contains a demo Flash file. The camera image received from the Kinect is on the right, and the depth information image on the left. You can set the depth which the Kinect is scanning and even control the tiliting motor on it from the Flash interface.

Basic Kinect Setup –
A basic project template for accessing the Kinect depth data in a Flash application –

This file gets all items between 2 specified depths and works out their central point. (As shown by the red dot).

This air app loads in any other flash swf file, and uses the Kinect depth data to fake the mouse position for the loaded swf. The idea was any mouse controlled game or app, could be loaded in and controlled with the Kinect. It sort of works, but not in the “all purpose” way intended – due to the handling of MouseEvents in Flash. As such, swfs to be loaded into this would have to be designed with these limitations in mind.

Flocking tests –

Items move around the screen based on the depth levels from the camera. Based on Soulwire’s Flocking Experiment.

Drum kit –

This file separates the depth information into 4 sectors. If anything is in the target depth range for that sector, it triggers a drum sample. All 4 sectors work independently, in an attempt to make a functioning drum kit.

Green screen –
An attempt to fake a green-screening effect by masking out the ordinary video feed from the camera based on the info from the depth camera. Unfortunately they don’t quite line up. The effect didn’t really work either.

A basic 3D scene which rotates in 3D space based on where the user is. At the minute uses the same “central point of all objects in depth range” as the basis of the rotation. Switching to OpenNI, I could potentially get access to the user skeleton points and could use that to track the user’s head – so as they move around, the scene appears to move realistically, as if their monitor is a window looking into the 3d space.

Mona Lisa –

Her eyes really do follow you around the room!

Particles –

Based on UnitZeroOne’s brilliant particle tutorial.

Particles flow in line with the camera output and are coloured based on the Kinect’s depth sensor.

Notes –
The current version of the AS3-Server is an early build and is a bit unstable.
If you see this, close and restart the server.

## Update –

Here’s a link to the source for these demos (25mb Zip) – http://dl.dropbox.com/u/5053444/AS3KinectSource.zip

## Cellular Automidi – Audio App

Presenting my latest Flash Music Toy App Thing –

## Cellular AutoMidi!

Cellular AutoMidi is a generative music app, making “music” based on a modified Cellular Automata algorithm.

It’s an AIR app –

Check it out in action in the video below, first using Flash dynamic sounds, then using Flash Midi Server to control a synth –

According to Wikipedia –

A cellular automaton is a discrete model studied in computability theory, mathematics, physics, complexity science, theoretical biology and microstructure modeling. It consists of a regular grid of cells, each in one of a finite number of states, such as “On” and “Off” . For each cell, a set of cells called its neighborhood is defined relative to the specified cell. An initial state (time t=0) is selected by assigning a state for each cell. A new generation is created (advancing t by 1), according to some fixed rule (generally, a mathematical function) that determines the new state of each cell in terms of the current state of the cell and the states of the cells in its neighborhood. For example, the rule might be that the cell is “On” in the next generation if exactly two of the cells in the neighborhood are “On” in the current generation, otherwise the cell is “Off” in the next generation. Typically, the rule for updating the state of cells is the same for each cell and does not change over time, and is applied to the whole grid simultaneously, though exceptions are known.

…..yep! Basically – each cell can be alive or dead. Once in a generation, each cell looks at it’s surrounding cells, and dies if it is lonely or overcrowded. If a dead cell has an optimum amount of neighbors, it will come to life! Each generation, all the cells which have come to life will sound a note. The notes are assigned based on the cell’s y position, and are all in the pentatonic scale.

There’s a few controls at the bottom which change how things work too.

• Start/Stop – Starts/Stops the automation.
• Export – Exports the current pattern to the clipboard. You can send it to friends, or save it for later, then load in with the load button.
• Clear down – Stop and clear the current pattern.
• Law Mode – An error when coding the cell rules gave this other odd mode.
• Skip Audio – Just show the cell animations.
• Sing Dead – Instead of singing the recently revived notes, sing for the recently deceased.
• Note duration – Alter the system speed.

Also, along the top there are banks of preset systems. Click play to start a saved pattern, and click assign to assign the pattern currently displayed to that button. You can also trigger each pattern with the keyboard keys 1-8.

When you press Export, your pattern is automatically copied to the clipboard, so you can save it, or share it with people. Here’s a pattern I made – you can load it by pasting it into the load box, and pressing Load!

1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,2 ,2 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,2 ,1 ,2 ,2 ,1 ,2 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,2 ,1 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,2 ,1 ,2 ,2 ,1 ,2 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,2 ,2 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1

HINT – When drawing patterns, symmetrical patterns seem to evolve nicely.

The app is fully compatible with Flash Midi Server (my Flash to MIDI audio interface app) – it checks to see if it is running when the app is launched. If it’s not, then it uses fancy Flash Player 10 dynamic audio! I’m hoping to roll this out to the Flash Midi Server class soon – so any app which tried to access the midi server and fails, will use the dynamic audio as a backup. I’ll keep you posted!

In case you missed it, you can download the app here – it weighs in at just 79kb including icons! The screenshot images above are 79k! If you don’t have Adobe Air installed, the link will prompt you to download that too.

I’d love to hear what you think of it – and see any patterns you come up with, so please post them in the comments.
Have fun!
Law.