Papervision3D Sound Spectrum

Saturday, December 6th, 2008 | examples, requests

This example is a remake of something Andy Zupko did about a year and a half ago. I just updated it to work with the latest version of Papervision3D and organized some of the code.

The song is by an indie group called Wolf Parade.

The .swf is about 4 megs (it has an embedded .mp3), so be patient while it downloads.

Click to change the layout.

source

You won’t be able to just copy and paste this. You will need the layout classes included in the source download.

package
{
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.media.Sound;
	import flash.media.SoundMixer;
	import flash.utils.ByteArray;
 
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.materials.utils.MaterialsList;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Cube;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.BitmapViewport3D;
 
	[SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")]
	public class Papervision3DSoundSpectrum extends BasicView
	{
		[Embed(source="assets/WolfParade-CallItARitual.mp3")]
		private var soundAsset:Class;	
 
		private const HEIGHT:int = 800;
		private const blur:BlurFilter = new BlurFilter(3, 3, 2);
		private const alphaTrans:ColorTransform = new ColorTransform(1, 1, 1, 1, 4, 5, 3, -10);
 
		private var point:Point = new Point();
		private var bytes:ByteArray = new ByteArray();
		private var sound:Sound;
		private var gradient:Array;
 
		private var bitmapViewport:BitmapViewport3D;
 
		public var layout:ILayout;
		public var circleLayout:CircleLayout;
		public var lineLayout:LineLayout;
		public var squareLayout:SquareLayout;
 
		public var cubes:Array = [];
		public static const CHANNELS:int = 40;
 
		public function Papervision3DSoundSpectrum()
		{
			sound = new soundAsset() as Sound;
			sound.play();
 
			//we'll need a bitmapViewport to access bitmapData
			bitmapViewport = new BitmapViewport3D();
			//allow the blurring
			bitmapViewport.fillBeforeRender = false;
			addChild(bitmapViewport);
 
			camera.extra = {goPosition: DisplayObject3D.ZERO, goTarget: DisplayObject3D.ZERO};
			camera.x = 0, camera.y = 300, camera.z = 500; 
			camera.zoom = 10;
 
			gradient = createColors();
			createCubes();
 
			startRendering();
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onClick);
 
			circleLayout = new CircleLayout(this);
			lineLayout = new LineLayout(this);
			squareLayout = new SquareLayout(this);
 
			layout = circleLayout;
			layout.setAndAssignNext();
		}
 
		private function createColors(): Array
		{
			var gradient: Array = new Array();
 
			var shape:Shape = new Shape();
			var bitmapData:BitmapData = new BitmapData( 256, 1, true, 0 );
 
			var colors:Array = [0xff0000, 0xff0000, 0xffff00, 0x00ff00, 0x00ffff];
			var alphas:Array = [100, 100, 100, 100, 100];
			var ratios:Array = [0, 16, 128, 192, 255];
 
			var matrix:Matrix = new Matrix();
 
			matrix.createGradientBox(CHANNELS, 1, 0, 0, 0 );
 
			shape.graphics.beginGradientFill('linear', colors, alphas, ratios, matrix);
			shape.graphics.drawRect(0, 0, CHANNELS, 1);
			shape.graphics.endFill();
 
			bitmapData.draw(shape);
 
			for(var i:int = 0; i < CHANNELS; i++)
			{
				gradient[i] = bitmapData.getPixel32(i, 0);
			}
 
			return gradient;
		}
 
		private function createCubes():void
		{
			var cubeMaterial:ColorMaterial;
 
			var angleOffset:Number = Math.PI*2/CHANNELS;
			var radius:Number = 400;
			var angle:Number = 180;
 
			var cubeX:Number, cubeZ:Number;
			var cube:Cube;
 
			for(var i:int =0;i<CHANNELS;i++)
			{
				cubeMaterial = new ColorMaterial(gradient[i]);
				cubeMaterial.lineColor = 0x222222;
				cubeMaterial.lineAlpha = 1;
				cubeX = Math.cos(angle)*radius;
				cubeZ = Math.sin(angle)*radius;
 
				var materialsList:MaterialsList = new MaterialsList();
				materialsList.addMaterial(cubeMaterial, "all");
 
				cube = new Cube(materialsList, 50, 50, HEIGHT);
 
				cubes[i] = cube;		
				cubes[i].rotationY = 90;
				scene.addChild(cube);
			}
		}
 
		private function onClick(e:MouseEvent):void
		{
			layout.setAndAssignNext();
		}
 
		override protected function onRenderTick(event:Event = null):void
		{
			SoundMixer.computeSpectrum(bytes, true, 2);
			var channelModulo:int = int(256/CHANNELS);
 
			var average:Number = 0;
			var temp:Number = 0;
			var currentChannel:Number = 0;
 
			for(var i:int =1;i<=256;i++)
			{
				temp = bytes.readFloat();
				average += temp;
 
				if(i%channelModulo == 0)
				{
					//set the cur channel to this!
					if(currentChannel < cubes.length)
					{
						average /=channelModulo;
						if(average > cubes[currentChannel].scaleY)
						{
							cubes[currentChannel].scaleY = average;
						}
						else
						{
							cubes[currentChannel].scaleY -= 0.04;
							if(cubes[currentChannel].scaleY <= 0)
							{
								cubes[currentChannel].scaleY = 0;
							}
						}
						cubes[currentChannel].x += (cubes[currentChannel].extra.goX - cubes[currentChannel].x)/32;
						cubes[currentChannel].y = cubes[currentChannel].scaleY*HEIGHT/2;
						cubes[currentChannel].z += (cubes[currentChannel].extra.goZ - cubes[currentChannel].z)/32;
					}
 
					currentChannel++;
					average = 0;
				}
			}
 
			camera.orbit(bitmapViewport.containerSprite.mouseY, bitmapViewport.containerSprite.mouseX);
 
			renderer.renderScene(scene, camera, bitmapViewport);
			bitmapViewport.bitmapData.applyFilter(bitmapViewport.bitmapData, bitmapViewport.bitmapData.rect, point, blur);
			bitmapViewport.bitmapData.colorTransform(bitmapViewport.bitmapData.rect, alphaTrans);
		}
	}
}

Tags: , ,

  • John Lindquist
    The camera.extra stuff was leftover from the original source before I updated it. So yeah, it's not actually doing anything in this example.

    But my answer still stands. "extra" is just an object where you can store properties to get later. It's not necessarily good OOP practice to just have freely editable untyped objects like that floating around, but it comes in handy for quick demos.
  • Tunied
    Hi,
    thanks for answer my qustion.but i still can'y understand what's the extra

    as far as i know

    "extra" just like "goto" born in long time ago,sicen began to use oop(java、c++、as3...etc)
    is not use anymore. did i right?

    and i annotate the code just like this:

    //camera.extra = {goPosition: DisplayObject3D.ZERO, goTarget: DisplayObject3D.ZERO};

    the demo still run good.

    so,what is
    camera.extra = {goPosition: DisplayObject3D.ZERO, goTarget: DisplayObject3D.ZERO};
    use for?

    thanks a lot!
  • John Lindquist
    "extra" is just an object where you can store whatever you want.
  • Tunied
    Thanks the code

    you know,it's cool.

    but i got a little confuse about this code

    camera.extra = {goPosition: DisplayObject3D.ZERO, goTarget: DisplayObject3D.ZERO};

    camera.extra whta's that?
blog comments powered by Disqus

Search

Recommended Books

Speaking at FITC Toronto

Recent Comments

 

December 2008
M T W T F S S
« Nov   Jan »
1234567
891011121314
15161718192021
22232425262728
293031  

Preferred Video Tutorial Resolution

  • 1024x768 (53%, 85 Votes)
  • 1280x1024 (15%, 24 Votes)
  • 1920x1080 (15%, 24 Votes)
  • 800x600 (13%, 20 Votes)
  • 480x320 (4%, 6 Votes)
  • 640x480 (0%, 2 Votes)

Total Voters: 160

Loading ... Loading ...