3D sound visualization using pv3D and computespectrum

I wrote a relatively simple example of how you can analyze the soundspectrum and then use the output to animate papervision3D objects. I’m not such a fan of ENTER_FRAME  listeners, so you’ll find the code that handles the animation in the tick function of the timer which updates every 100 ms. To get this code to work you’ll need the Tweenlite classes.

Click here to launch ( may take a while to load the mp3 file )

pv3D_sound

And here’s source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package
{
	import com.greensock.TweenLite;
 
	import flash.display.BlendMode;
	import flash.display.Sprite;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.media.Sound;
	import flash.media.SoundMixer;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	import flash.utils.Timer;
 
	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;
 
	[ SWF( width='1024', height='768', backgroundColor='#000000', frameRate='25' ) ]
 
	public class PV3D_SPECTRUM extends BasicView
	{
		private var bytes : ByteArray;
		private var tmr : Timer;
		private var a : Number = 0;
		private var cubes : Array;
		private var container : DisplayObject3D;
		private var pivot : Sprite;
 
		private var easeOut:Number = 0.4; // Higher = faster ease-out
		private var reachX:Number = 0.7; //  Higher =  smaller reach
		private var reachY:Number = 0.7; //  Higher =  smaller reach
 
		public function PV3D_SPECTRUM()
		{
			stage.quality = StageQuality.MEDIUM;
 
			init();
		}
 
		private function init() : void
		{
			var spacing : uint = 600;
			var dim : uint = 3;
			var c : uint = ( dim * spacing * 0.5 );
			var snd : Sound = new Sound();
 
			// Set camera properties
			camera.x = 2000;
			camera.y = 500;
			camera.z = 500;
 
			camera.zoom = 5;
			camera.focus = 100;
			camera.sort = false;
 
			// Set pivot point
			pivot = new Sprite();
			pivot.x = 400;
			pivot.y = 250;
 
			// Make container for cubes
			container = new DisplayObject3D();
			scene.addChild( container );
 
			snd.load( new URLRequest( "3.mp3" ) );
			snd.play();
 
			bytes = new ByteArray();
			cubes = new Array();
 
			for (var i:uint = 0; i < dim; i++)
			{
				for (var j:uint = 0; j < dim; j++)
				{
					for (var k:uint = 0; k < dim; k++)
					{
						var size : uint = Math.random() * 100 + 150;
						var cube : Cube = new Cube(
								new MaterialsList( { all:new ColorMaterial( 0xFFFFFF * Math.random() ) } ),
								size,
								size,
								size,
								1,
								1,
								1 );
 
						container.addChild( cube );
 
						cube.x = i * spacing - c;
						cube.y = j * spacing - c;
						cube.z = k * spacing - c;
 
						cube.useOwnContainer = true;
						cube.alpha = 0.8;
						cube.blendMode = BlendMode.ADD;
 
						cubes.push( cube );
					}
				}
			}
 
			startRendering();
 
			tmr = new Timer( 100 );
			tmr.addEventListener( TimerEvent.TIMER, tick );
			tmr.start();
		}
 
		private function tick(e:TimerEvent):void
		{
			var temp : Array = new Array();
 
			SoundMixer.computeSpectrum( bytes, true, 0 );
 
			for ( var j:int = 0; j < 256; j+= Math.floor( 256 / cubes.length ) )
			{
				temp.push( ( bytes.readFloat() * 1.5 ) + 1 );
			}
 
			for ( var i:uint = 0; i < cubes.length; i++ )
			{
				TweenLite.to( cubes[i], 0.1, { scaleY:temp[i], scaleZ:temp[i], scaleX:temp[i] } );
				cubes[i].alpha = temp[i] - 0.9;
			}
		}
 
		override protected function onRenderTick( event:Event = null ) : void
		{
			container.yaw( 1 );
			container.pitch( 1 ); 
 
			this.camera.x += ( ( - pivot.mouseX * 5 ) - this.camera.x ) / 35;
			this.camera.y += ( ( - pivot.mouseY * 5 ) - this.camera.y ) / 35;
 
			super.onRenderTick();
		}
	}
}
  • Share/Bookmark

3 Comments to “3D sound visualization using pv3D and computespectrum”

  1. [...] [...]

  2. [...] [...]

  3. Wilson Silva 29 April 2011 at 3:00 pm #

    I like your website. I wish you had more posts…


Leave a Reply