Joy Division EQ

screen

I just love the cover art for the Joy Division album Unknown Pleasures and I have had this idea for a while to try to create something interactive based on the main illustration. So here is my first attempt: The "Joy Division Equalizer". For now it is just a rough sketch and the code is very very quick and dirty, but I think it looks kinda' cool. Click here to check it out.

Here is the dirrrrrrty source: (Written & Compiled in Flex Builder 3)

 
package
{
	import flash.display.Graphics;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.media.Sound;
	import flash.media.SoundMixer;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
 
	[SWF(backgroundColor="0x000000", width="1440", height="900")]
	public class JoyDivisionEQ extends Sprite
	{
		private var _numLines:int = 60;
		private var _numSegments:int = 40;
		private var _spectrumStartSegment:int = 10;
		private var _spectrumEndSegment:int = 30;
		private var _maxSpectrumHeight:Number = 120;
		private var _rect:Rectangle = new Rectangle(0, 0, 400, 500);
		private var _noiseOffset:Number = 3;
		private var _sound:Sound;
		private var _stretchFactor:Number = 2;
 
		private var _wrapper:Sprite;
 
		public function JoyDivisionEQ()
		{
			init();
		}
 
		private function init ():void
		{
			setStageProps();
			createWrapper();
			playSong();
			draw();
 
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(Event.RESIZE, stageResizeHandler);
		}
 
		private function setStageProps ():void
		{
			stage.frameRate = 30;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
		}
 
		private function enterFrameHandler (e:Event):void
		{
			draw();
		}
 
		private function playSong ():void
		{
			_sound = new Sound(new URLRequest("shadowplay.mp3"));
			_sound.play(0, 100);
		}
 
		private function createWrapper ():void
		{
			_wrapper = new Sprite();
			_wrapper.x = (stage.stageWidth - _rect.width)/2;
			_wrapper.y = (stage.stageHeight - _rect.height)/2;
			this.addChild(_wrapper);
		}
 
		private function draw ():void
		{
			var xSpacing:Number = _rect.width/_numSegments;
			var ySpacing:Number = _rect.height/_numLines;
 
			var ba:ByteArray = new ByteArray();
			SoundMixer.computeSpectrum(ba, true, _stretchFactor);
 
			var g:Graphics = _wrapper.graphics;
			g.clear();
 
			for (var i:int = 0; i < _numLines; i++)
			{
				var y:Number = ySpacing*i;
				g.moveTo(0, y);
				g.lineStyle(1, 0xFFFFFF);
				g.beginFill(0);
 
				var start:int = _spectrumStartSegment - 2 + (4*Math.random())
				var end:int = _spectrumEndSegment - 2 + (4*Math.random())
				var length:Number = end - start;
 
				var prevY:Number;
 
				for (var j:int = 1; j <  _numSegments-1; j++)
				{
					if (ba.position == 200*_stretchFactor)
					{
						ba.position = 20*_stretchFactor;
					}
 
					var _y:Number = y;
 
					if (j >= start && j<= end)
					{
						var k:Number = j - start;
						var ratio:Number = (k/length);
						if (ratio > 0.5)
						{
							ratio = 1-ratio;
						}
						var amp:Number = _maxSpectrumHeight*ratio;
 
						if (j % 1 == 0)
						{
							var num:Number;
							_y = y - Math.abs((ba.readFloat()*amp));
						}
						else
						{
							_y = prevY + 10 - (10*Math.random());
						}
					}
 
					_y = _y - (_noiseOffset/2) + ((_noiseOffset/2)*Math.random());
					g.lineTo(xSpacing*j, _y);
					prevY = _y;
				}
 
				g.lineTo(xSpacing*(j+1), y);
				g.lineStyle();
				g.lineTo(0, y);
				g.endFill();
			}
 
		}
 
		private function stageResizeHandler (e:Event):void
		{
			_wrapper.x = (stage.stageWidth - _rect.width)/2;
			_wrapper.y = (stage.stageHeight - _rect.height)/2;
		}
	}
}