In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

ff: Sound Sphere

Impact
Get Adobe Flash player
by saharan 23 Oct 2012
/**
 * Copyright saharan ( http://wonderfl.net/user/saharan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ipbb
 */

// forked from bkzen's Sound Sphere
package  
{
    import flash.display.Graphics;
    import alternativ7.engine3d.alternativa3d;
    import alternativ7.engine3d.core.Camera3D;
    import alternativ7.engine3d.core.Object3DContainer;
    import alternativ7.engine3d.core.Vertex;
    import alternativ7.engine3d.core.View;
    import alternativ7.engine3d.materials.FillMaterial;
    import alternativ7.engine3d.primitives.Sphere;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundLoaderContext;
    import flash.media.SoundMixer;
    import flash.media.SoundTransform;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;
    import flash.utils.getTimer;
    
    /**
     * sound by AlainMikuni
     * Alternativa3D を使って何か作ってみたかった。
     * @author jc at bk-zen.com
     */
    [SWF (backgroundColor = "0x000000", frameRate = "30", width = "465", height = "465")]
    public class SoundSphere extends Sprite 
    {
        private const radius: int = 200;
        private const radius2: int = radius * 2;
        private var rootContainer:Object3DContainer = new Object3DContainer();
        private var camera:Camera3D;
        private var sphere: Sphere;
        private var length: uint;
        private var startIndex:uint;
        private var vertices:Vector.<Vertex>;
        private var maxVertices:Vector.<Vertex>;
        private var minVertices:Vector.<Vertex>;
        private var sound:Sound;
        private var bytes: ByteArray = new ByteArray();
        
        public function SoundSphere() 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // stage 初期化
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
            // カメラを作成
            camera = new Camera3D();
            camera.rotationX = Math.PI;
            camera.view = new View(stage.stageWidth, stage.stageHeight);
            addChild(camera.view);
            addChild(camera.diagram); // for debug
            
            var s: int = 16;
            sphere = new Sphere(radius, s, s);
            var mat: FillMaterial = new FillMaterial(0xFF0000, 0.5, 0, 0xFF7777);
            sphere.setMaterialToAllFaces(mat);
            
            // 3D オブジェクトを追加
            rootContainer.addChild(camera);
            rootContainer.addChild(sphere);
            
            // 必要なものをあらかじめ持っておく。
            vertices =  sphere.vertices;
            length = vertices.length;
            // 拡大縮小を行うために大き目の Sphere を作って、それを適応させる感じで。
            var dummy: Sphere = new Sphere(radius + 400, s, s);
            maxVertices = dummy.vertices;
            dummy = sphere.clone() as Sphere;
            minVertices = dummy.vertices;
            
            stage.addEventListener(Event.RESIZE, onResize);
            soundInit();
            onResize();
        }
        
        /**
         * リサイズハンドラ
         * @param    e
         */
        private function onResize(e:Event = null):void 
        {
            camera.view.width  = stage.stageWidth;
            camera.view.height = stage.stageHeight;
            var g:Graphics = graphics;
            g.clear();
            g.beginFill(0);
            g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
        }
        
        /**
         * サウンド準備
         */
        private function soundInit():void 
        {
            var url: String = "http://www.takasumi-nagai.com/soundfiles/sound007.mp3";
            //var url: String = "http://www.takasumi-nagai.com/soundfiles/sound004.mp3";
            sound = new Sound();
            sound.addEventListener(Event.COMPLETE, onCompLoadSound);
            sound.load(new URLRequest(url), new SoundLoaderContext(10, true));
        }
        
        /**
         * サウンド読み込み完了。再生
         * @param    e
         */
        private function onCompLoadSound(e:Event):void 
        {
            sound.removeEventListener(Event.COMPLETE, onCompLoadSound);
            var channel: SoundChannel = sound.play(0, 10, new SoundTransform(0.5));
            addEventListener(Event.ENTER_FRAME, loop);
        }
        
        
        private function loop(e:Event):void 
        {
            bytes.length = 0;
            SoundMixer.computeSpectrum(bytes, true);
            
            // カメラを動かしたり球を回転させたり。
            var t: uint = getTimer();
            sphere.rotationX = - t / 1700;
            sphere.rotationY = - t / 1300;
            camera.z = 1200 + 500 * Math.sin(t / 800);
            
            // 上のほうが音が出やすいので上に集中させる
            var i: uint = 0, v: Vertex, maxV: Vertex, minV: Vertex, p: Number, 
                n: uint = bytes.length >> 6;
                
            var sum:Number = 0;
            // 4つ飛ばしにしておく。
            for (; i < length; i += 4) 
            {
                v = vertices[i], maxV = maxVertices[i], minV = minVertices[i];
                // z 座標を周波数とする
                bytes.position = n * (minV.z + radius) / radius2 << 2;
                p  = bytes.readFloat();
                bytes.position += 256;
                p += bytes.readFloat();
                sum += p * p * 8;
                // apply some smoothing
                v.x = (minV.x + maxV.x * p + v.x) * 0.5;
                v.y = (minV.y + maxV.y * p + v.y) * 0.5;
                v.z = (minV.z + maxV.z * p + v.z) * 0.5;
            }
            var scale:Number = 1 / (1 + sum / 0x200);
            for (i = 0; i < length; i++) 
            {
                if(i % 4 == 0) continue;
                v = vertices[i], minV = minVertices[i];
                // scaling
                v.x = minV.x * scale;
                v.y = minV.y * scale;
                v.z = minV.z * scale;
            }
            
            // add effect
            sum += 32;
            if(sum > 0xFF) sum = 0xFF;
            sphere.setMaterialToAllFaces(new FillMaterial(sum << 16, 0.5, 0, 0xFF7F7F));
            
            // 裏側も描画する
            sphere.calculateFacesNormals();
            camera.render();
        }
    }
}