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 )
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(); } } } |




