Arbitrary formula player

by yonatan forked from Math Music Incubator (diff: 358)
you can edit the top textarea, bottom one is for error messages. sorry about the funny syntax, too lazy to hook it up to ESC...
compiler from http://github.com/aemoncannon/las3r
♥3 | Line 141 | Modified 2011-10-10 00:29:28 | MIT License
play

ActionScript3 source code

/**
 * Copyright yonatan ( http://wonderfl.net/user/yonatan )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fS96
 */

// forked from Quasimondo's Math Music Incubator
// forked from Quasimondo's forked from: Math Music
// forked from Saqoosha's Math Music
package {
    import flash.desktop.ClipboardFormats;
    import flash.desktop.Clipboard;
    import com.bit101.components.Component;
    import com.bit101.components.PushButton;
    import com.bit101.components.HSlider;
    import com.bit101.components.VBox;
    import com.bit101.components.TextArea;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.display.*;
    import flash.events.*;
    import flash.utils.*;
    import flash.net.*;
    import flash.system.*;

    [SWF(backgroundColor="0x000000", frameRate="30", width="475", height="475")]
    public class MathMusicIncubator extends Sprite {
        private var _sound:Sound;
        private var _channel:SoundChannel;
        private var _t:Number = -1;
        private var _type:int = -1;
        private var _image:BitmapData;
        private var _px:int = 0;
        private var _py:int = 0;
        private var _control:Component;
        private var _formula:TextArea, _output:TextArea;
        public static var audioGen:Function = function(t:Number):Number { return 0; }
        
        public function MathMusicIncubator() {
            //loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
            _image = new BitmapData(256, 256, false, 0x0);
            var b:Bitmap = addChild(new Bitmap(_image)) as Bitmap;
            b.width = b.height = 475;
            var vbox:VBox = new VBox(this, 5, 5);
            _formula = new TextArea( vbox );
            _formula.textField.addEventListener(Event.CHANGE, _onChange);
            var _copy_btn:PushButton = new PushButton( vbox, 3,3,"Copy to Clipboard",_copyToClipboard );
            _output = new TextArea( vbox );
            _control = vbox;
            _control.scaleX = _control.scaleY = 2;
            var vb2:VBox = new VBox(this, 415, 5);
            function handler(i:int):Function { return function(e:*):void { _formula.text = presets[i]; _onChange(null) }; }
            for(var i:int=0; i<presets.length; i++) (new PushButton(vb2, 0, 0, String(i), handler(i))).setSize(50, 20);
            _sound = new Sound();
            _sound.addEventListener(SampleDataEvent.SAMPLE_DATA, _onSampleData);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, function(e:*):void { _control.visible = vb2.visible = true; });
            stage.addEventListener(Event.MOUSE_LEAVE, function(e:*):void { _control.visible = vb2.visible = false; });
            loadLas3rSwf(initCompiler);
        }
        
        private function _copyToClipboard( event:Event ):void {
            Clipboard.generalClipboard.setData( ClipboardFormats.TEXT_FORMAT, _formula.text);
        }

        private function _play():void {
            _t = 0;
            _px = 0;
            _py = 0;
            _image.fillRect(_image.rect, 0x0);
            if (_channel) _channel.stop();
            _channel = _sound.play();
        }
        
        private function _onSampleData(e:SampleDataEvent):void {
            var i:int, t:Number, tt:int, val:Number;
            _image.lock();
            for (i = 0; i < 8192; i++, _t++) {
                t = (_t / 44100);
                try { val = audioGen(t); } catch(e:*) { _output.text = String(e); if (_channel) _channel.stop(); break; };
                tt = val * 0x7f + 0x80;
                e.data.writeFloat(val);
                e.data.writeFloat(val);
                _image.setPixel(_px, _py, tt << 16 | tt << 8 | tt);
                if (++_px == _image.width) {
                    _px = 0;
                    if (++_py == _image.height) {
                        _py = 0;
                    }
                }
            }
            _image.unlock();
        }

        private function _onChange(e:Event):void {
            if (_channel) _channel.stop();
            repl.rt.evalStr(_formula.text,
                function(fn:*):void { audioGen = fn; _output.text = ""; _play(); },
                null,
                function(v:*):void { _output.text = String(v); });
            _t = 0;
        }

        private function loadLas3rSwf(completeHandler:Function):void {
            Security.loadPolicyFile("http://zozuar.org/wonderfl/crossdomain.xml");
            var loader:Loader;
            var req:URLRequest = new URLRequest("http://zozuar.org/wonderfl/las3r.swf");
            var ctx:LoaderContext = new LoaderContext(true, ApplicationDomain.currentDomain, SecurityDomain.currentDomain);
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
            loader.load(req, ctx);
        }

        private var repl:*;
        private function initCompiler(e:* = null):void {
            _output.text = "ready.";
            var replClass:Class = getDefinitionByName("com.las3r.repl.Repl") as Class;
            repl = new replClass(265, 265, stage);
            repl.visible = false;
            repl.rt.evalStr(prelude, ready);
        }

        private function ready(_:*):void {
            _formula.text = presets[0];
            _onChange(null);
            _play();
        }

        // from http://wonderfl.net/c/hOvH
        private function onUncaughtError(event:UncaughtErrorEvent):void {
            var message:String;
            if (event.error is Error)
                message = Error(event.error).getStackTrace();
            else if (event.error is ErrorEvent)
                message = ErrorEvent(event.error).text;
            else
                message = event.error.toString();
            _output.text = message;
            event.preventDefault(); // ココ重要!
        }

        private var prelude:String = 
        "(def << bit-shl)" +
        "(def >> bit-sar)" +
        "(def >>> bit-shr)" +
        "(def abs (. Math abs))" +
        "(def ceil (. Math ceil))" +
        "(def cos (. Math cos))" +
        "(def exp (. Math exp))" +
        "(def floor (. Math floor))" +
        "(def log (. Math log))" +
        "(def pow (. Math pow))" +
        "(def random (. Math random))" +
        "(def round (. Math round))" +
        "(def sin (. Math sin))" +
        "(def sqrt (. Math sqrt))" +
        "(def tan (. Math tan))";

        private var presets:Array = [
            "(fn [t] (sin (* 6.28 440 t)))",
            "(fn [t] (* t (sin (* 6.28 440 (* t t)))))",
            "(fn [t]\n  (let [n (* 6.28 440 t)]\n    (pow n (sin n))))",
        ]
    }
}

Forked