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

flash on 2013-1-19

Get Adobe Flash player
by quilime 19 Jan 2013
    Embed
/**
 * Copyright quilime ( http://wonderfl.net/user/quilime )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/Ahva
 */

package
{
    import flash.display.*;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.SampleDataEvent;
    import flash.media.Sound;
    import flash.utils.ByteArray;
    import flash.utils.Timer;
    
    [SWF(backgroundColor='#ffffff')]
    public class Main extends Sprite {
        private var 
            sound:Sound = new Sound;
            
        public function Main() {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.HIGH;
            
            var control:Control = new Control(this);
            
            sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
            sound.play();
        }
        
        private function onSampleData(event:SampleDataEvent):void {
            var outBuffer:ByteArray = new ByteArray;

            var synthBuffer:ByteArray  = _synth_.generateBytes( BUFFER_SIZE );
            var delayBuffer:ByteArray  = _delayEffect_.generateBytes( synthBuffer, BUFFER_SIZE );
            var reverbBuffer:ByteArray = _reverbEffect_.generateBytes( delayBuffer, BUFFER_SIZE );
            
            outBuffer = reverbBuffer;
                        
            event.data.writeBytes( outBuffer );
        }
    }    
}


import com.bit101.components.CheckBox;
import com.bit101.components.IndicatorLight;
import com.bit101.components.Knob;
import com.bit101.components.Label;
import com.bit101.components.NumericStepper;
import com.bit101.components.PushButton;
import com.bit101.components.RadioButton;
import com.bit101.components.Style;
import com.bit101.components.WheelMenu;

import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.geom.Point;
import flash.utils.ByteArray;

const SAMPLE_RATE :int = 44100; // 22050;
const BUFFER_SIZE :int = 2048; // seaquence is at 3072 (?);    

// globals
var 
    _bpm_:Number = 60;


class AudioGenerator {
    public var 
        buffer:ByteArray;
    // generate a byteArray
    public function generateBytes( _bufferSize:Number ):ByteArray {
        buffer = new ByteArray();
        var sample:Number = 0;
        for (var i:int = 0; i < _bufferSize; ++i) {
            sample = 0;
            buffer.writeFloat( sample ); // left
            buffer.writeFloat( sample ); // right
        }
        return buffer;
    }
}
class TestSynth extends AudioGenerator {
    private var 
        timer:Oscillator = new Oscillator,
        osc:Oscillator = new Oscillator,
        osc2:Oscillator = new Oscillator,
        filter:Filter = new Filter,
        env:Envelope = new Envelope,
        currentCount:Number = 0,
        envBuff:Number = 0,
        tone:Number = 0;
    public var
        mode:int = 0;
    override public function generateBytes( _bufferSize:Number ):ByteArray {
        buffer = new ByteArray();
        var sample:Number = 0;
        for (var i:int = 0; i < _bufferSize; ++i) {
            switch (mode) {
                case -1 :
                    // test tone
                    sample = osc.sinewave(440);
                    break;                
                case 0 :
                    break;
                case 1 :
                    // annoying siren
                    currentCount = timer.phasor(_bpm_ / 60 / 2, 1, 2);
                    sample = osc.triangle(currentCount * 300);
                    break;
                case 2 :
                    // fun w/filters
                    currentCount = timer.phasor(_bpm_ / 60 / 2, 1, 9);
                    if (currentCount < 5) {
                        sample = osc.square(currentCount * 100);
                    }
                    else if (currentCount >=5 ){
                        sample = osc.saw(currentCount * 50);
                    }                    
                    sample = filter.lores(sample, osc2.phasor(0.25, 20, 2000), 50);
                    break;
                case 3 :
                    // single tone
                    var adsrEnv:Array = [   0,     0, 
                                            1.0,   10,  
                                            1.0,   250, 
                                            0,       50    ];
                    
                    //[ 1.0, 5, 1.0, 100, 1.0, 0, 0, 100 ];
                    if (int(timer.phasor(_bpm_ / 60)) != 0) {                        
                        env.trigger(0, adsrEnv[0]);
                    }
                    envBuff = env.line(8, adsrEnv); //our ADSR env has 8 value/time pairs.
                    sample = osc.sinewave(440 * 2) * envBuff;
                    break;
                case 4 :
                    // some nice tones
                    var adsrEnv2:Array = [  0,     0, 
                                            1.0,   10,  
                                            1.0,   250, 
                                            0,       50    ];
                    if (int(timer.phasor(_bpm_ / 60)) != 0) {                        
                        env.trigger(0, adsrEnv2[0]);
                        tone = Math.floor(Math.random() * 20 - 5);
                    }
                    envBuff = env.line(8, adsrEnv2); //our ADSR env has 4 value/time pairs.
                    sample = osc.sinewave(440  / 4     * tone) * envBuff;
                    break;
                default: 
                    break;
            }
            
            // turn it down a hair just in case
            sample *= 0.75;
            
            buffer.writeFloat(sample); // left
            buffer.writeFloat(sample); // right
        }
        return buffer;
    }    
}
var _synth_:TestSynth = new TestSynth;


class Effect {
    public var 
        bypass:Boolean = true,
        buffer:ByteArray;
    // passthrough by default
    public function generateBytes( _buffer:ByteArray, _bufferSize:int ):ByteArray {
        buffer = new ByteArray();
        var length:int = _buffer.length;
        _buffer.position = 0
        while (_buffer.position < length) {
            var sample_l:Number = _buffer.readFloat(); // left
            var sample_r:Number = _buffer.readFloat(); // right    
            buffer.writeFloat(sample_l); // left
            buffer.writeFloat(sample_r); // right            
        }
        return buffer;
    }
}

class ReverbEffect extends Effect {
    //----------------------------------------------------------------------------------------------------
    //  SiOPM effect stereo reverb
    //  Copyright (c) 2009 keim All rights reserved.
    //  Modified for generic use 2013-18-01 Gabriel Dunne
    //  Distributed under BSD-style license (see org.si.license.txt).
    //----------------------------------------------------------------------------------------------------

    static private const DELAY_BUFFER_BITS:int = 13;
    static private const DELAY_BUFFER_FILTER:int = (1<<DELAY_BUFFER_BITS)-1;
    
    private var _delayBufferL:Vector.<Number>, _delayBufferR:Vector.<Number>;
    private var _pointerRead0:int, _pointerRead1:int, _pointerRead2:int;
    private var _pointerWrite:int;
    private var _feedback0:Number, _feedback1:Number, _feedback2:Number;
    private var _wet:Number;
    
    private var
        filter_l:Filter = new Filter,
        filter_r:Filter = new Filter;
    
    // constructor
    //------------------------------------------------------------
    public function ReverbEffect(delay1:Number = 0.7, delay2:Number = 0.4, feedback:Number = 0.8, wet:Number = 0.3) {
        _delayBufferL = new Vector.<Number>(1<<DELAY_BUFFER_BITS);
        _delayBufferR = new Vector.<Number>(1<<DELAY_BUFFER_BITS);
        setParameters(delay1, delay2, feedback, wet);
        prepareProcess();        
    }
    // operation
    //------------------------------------------------------------
    /** set parameters
     *  @param delay1 long delay(0-1).
     *  @param delay2 short delay(0-1).
     *  @param feedback feedback decay(-1-1). Negative value to invert phase.
     *  @param wet mixing level(0-1).
     */
    public function setParameters(delay1:Number=0.7, delay2:Number=0.4, feedback:Number=0.8, wet:Number=0.3) : void
    {
        if (delay1<0.01) delay1=0.01;
        else if (delay1>0.99) delay1=0.99;
        if (delay2<0.01) delay2=0.01;
        else if (delay2>0.99) delay2=0.99;
        _pointerWrite = (_pointerRead0 + DELAY_BUFFER_FILTER) & DELAY_BUFFER_FILTER;
        _pointerRead1 = (_pointerRead0 + DELAY_BUFFER_FILTER*(1-delay1)) & DELAY_BUFFER_FILTER;
        _pointerRead2 = (_pointerRead0 + DELAY_BUFFER_FILTER*(1-delay2)) & DELAY_BUFFER_FILTER;
        if (feedback>0.99) feedback=0.99;
        else if (feedback<-0.99) feedback=-0.99;
        _feedback0 = feedback*0.2;
        _feedback1 = feedback*0.3;
        _feedback2 = feedback*0.5;
        _wet = wet;
    }
    public function prepareProcess() : int
    {
        var i:int, imax:int = 1<<DELAY_BUFFER_BITS;
        for (i=0; i<imax; i++) _delayBufferL[i] = _delayBufferR[i] = 0;
        return 2;
    }
    override public function generateBytes( _buffer:ByteArray, _bufferSize:int ):ByteArray {
        buffer = new ByteArray();
        var length:int = _buffer.length;
        _buffer.position = 0;
        while (_buffer.position < length) {
            var 
                n:Number, m:Number, 
                dry:Number = 1 - _wet;
            
            var sample_l:Number = _buffer.readFloat(); // left
            var sample_r:Number = _buffer.readFloat(); // right
            
            if (!bypass) {                        
            
            // left
            n  = _delayBufferL[_pointerRead0] * _feedback0;
            n += _delayBufferL[_pointerRead1] * _feedback1;
            n += _delayBufferL[_pointerRead2] * _feedback2;
            _delayBufferL[_pointerWrite] = sample_l - n;
            sample_l *= dry;
            sample_l += n * _wet;

            // right
            n  = _delayBufferR[_pointerRead0] * _feedback0;
            n += _delayBufferR[_pointerRead1] * _feedback1;
            n += _delayBufferR[_pointerRead2] * _feedback2;
            _delayBufferR[_pointerWrite] = sample_r - n;
            sample_r *= dry;
            sample_r += n * _wet;
            
            _pointerWrite = (_pointerWrite + 1) & DELAY_BUFFER_FILTER;
            _pointerRead0 = (_pointerRead0 + 1) & DELAY_BUFFER_FILTER;
            _pointerRead1 = (_pointerRead1 + 1) & DELAY_BUFFER_FILTER;
            _pointerRead2 = (_pointerRead2 + 1) & DELAY_BUFFER_FILTER;
            
            //sample_l += filter_l.lores(sample_l, 740, 1);
            //sample_r += filter_r.lores(sample_r, 740, 1);
            }
            
            buffer.writeFloat(sample_l); // left
            buffer.writeFloat(sample_r); // right            
        }
        return buffer;
    }    
}
var _reverbEffect_:ReverbEffect = new ReverbEffect;


class DelayEffect extends Effect {
    private var 
        delay:DelayLine = new DelayLine,
        delay_l:DelayLine = new DelayLine,
        delay_r:DelayLine = new DelayLine,
        delay_time_mult:Number = 0.5,
        delay_mix:Number = 0.75,
        delay_feedback:Number = 0.65;
    function DelayEffect():void{
        setParameters();
    }
    public function setParameters(_delay_mix:Number = 0.75, _delay_feedback:Number = 0.65, _delay_time_mult:Number = 0.5) : void {
        delay_mix = _delay_mix,
        delay_feedback = _delay_feedback; 
        delay_time_mult = _delay_time_mult;
    }        
    override public function generateBytes( _buffer:ByteArray, _bufferSize:int ):ByteArray {
        buffer = new ByteArray();
        var length:int = _buffer.length;
        _buffer.position = 0;
        while (_buffer.position < length) {
            var sample_l:Number = _buffer.readFloat(); // left
            var sample_r:Number = _buffer.readFloat(); // right                    
            if (!bypass) {            
                sample_l = sample_l + (delay.dl(sample_l, BUFFER_SIZE * 16 * delay_time_mult, delay_feedback) * delay_mix);
                sample_r = sample_r + (delay.dl(sample_r, BUFFER_SIZE * 16 * delay_time_mult, delay_feedback) * delay_mix);            
            }  
            buffer.writeFloat(sample_l); // left
            buffer.writeFloat(sample_r); // right            
        }
        return buffer;
    }
}
var _delayEffect_:DelayEffect = new DelayEffect;





class DelayLine  {
    private var 
        frequency:Number = 0,
        phase:int = 0,
        output:Number = 0,
        memory:Vector.<Number> = new Vector.<Number>(88200);
    public function dl(input:Number, size:int, feedback:Number):Number {
        if ( phase >= size ) {
            phase = 0;
        }
        phase += 1;
        memory[phase] = (memory[phase] * feedback) + (input * feedback) * 0.5;
        return memory[phase];
    } 
}


class Oscillator {
    public var 
        frequency:Number = 0,
        phase:Number = 0,
        startphase:Number = 0,
        endphase:Number = 0,
        output:Number = 0,
        position:Number = 0;
        
    // phasor
    // returns a value that oscillates along a linear ramp between two values at a specific frequency    
    public function phasor(frequency:Number, startphase:Number = 0, endphase:Number = 1.0):Number {
        if (phase < startphase) {
            phase = startphase;
        }
        if ( phase >= endphase ) {
            phase = startphase;
        }
        phase += (endphase - startphase) / (SAMPLE_RATE / frequency);
        return phase;
    }
    
    // sinewave
    public function sinewave(frequency:Number):Number {
        phase = (position++) / SAMPLE_RATE * Math.PI * 2;
        return Math.sin(phase * frequency);        
    }
    
    // saw
    // (phasor between -1 and 1)
    public function saw(frequency:Number):Number {
        return phasor(frequency, -1, 1);
    }    
    
    // triangle 
    public function triangle(frequency:Number):Number {
        if ( phase >= 1.0 ) {
            phase -= 1.0;    
        }
        phase +=  1.0 / ( SAMPLE_RATE / frequency );
        output = phase <= 0.5 ? (phase - 0.25) * 4: ((1.0-phase) - 0.25) * 4;
        return output;
    }
    
    // square
    public function square(frequency:Number):Number {
        if (phase < 0.5) {
            output = -1;    
        }
        if (phase > 0.5) {
            output = 1;
        } 
        if ( phase >= 1.0 ) {
            phase -= 1.0;    
        }
        phase += 1.0 / (SAMPLE_RATE / frequency);
        return(output);
    }    
    
    // noise (white)
    public function noise():Number {
        return Math.random() * 2 - 1;
    }
} 


class Filter {
    public var 
        gain:Number = 0,
        input:Number = 0,
        output:Number = 0,
        inputs:Array = new Array(),
        outputs:Array = new Array(),
        cutoff:Number = 0,
        cutoff1:Number = 0,
        resonance:Number = 0,
        x:Number = 0, // speed
        y:Number = 0, // position
        z:Number = 0, // pole
        c:Number = 0; // filter coefficient
    
    // lores filter
    // from Maximilian
    // takes an audio input, a frequency and a resonance factor (1-100)
    // cuttof is freq in hz. res is between 1 and whatever. Watch out!
    public function lores(input:Number, cutoff1:Number, resonance:Number):Number {
        cutoff = cutoff1 * 0.5;
        if (cutoff < 10) {
            cutoff = 10;    
        }
        if (cutoff > (SAMPLE_RATE * 0.5)) {
            cutoff = (SAMPLE_RATE * 0.5);    
        }
        if (resonance < 1.) {
            resonance = 1.;    
        }
        z = Math.cos(Math.PI * 2 * cutoff / SAMPLE_RATE);
        c = 2 - 2 * z;
        var r:Number = (Math.sqrt( 2.0 ) * Math.sqrt(-Math.pow((z - 1.0), 3.0)) + resonance * (z - 1))/(resonance *(z - 1));
        x = x + (input - y) * c;
        y = y + x;
        x = x * r;
        output = y;
        return output;
    }
    // hires filter
    // from Maximilian
    public function hires(input:Number, cutoff1:Number, resonance:Number):Number {
        cutoff = cutoff1 * 0.5;
        if (cutoff < 10) {
            cutoff = 10;    
        }
        if (cutoff > SAMPLE_RATE * 0.5) {
            cutoff = SAMPLE_RATE * 0.5;
        }
        if (resonance < 1.0) {
            resonance = 1.0;
        }
        z = Math.cos( Math.PI * 2 * cutoff / SAMPLE_RATE);
        c = 2 - 2 * z;
        var r:Number = (Math.sqrt(2.0) * Math.sqrt(-Math.pow((z - 1.0), 3.0)) + resonance * (z - 1)) / (resonance * (z - 1));
        x = x + (input-y) * c;
        y = y + x;
        x = x * r;
        output = input - y;
        return output;
    }
}


class Envelope {
    public var 
        input:Number = 0,
        period:Number = 0,
        amplitude:Number = 0,
        triggered:int = 0,
        startval:Number = 0,
        currentval:Number = 0,
        nextval:Number = 0,
        isPlaying:int = 0,
        valindex:int = 0;
    public function trigger(index:int, amp:Number):void {
        isPlaying = 1;
        valindex = index;
        amplitude = amp;
    }
    // envelope line
    // from Maximilian
    // numberofsegments: number of time/value pairs
    // segments: envelope array holding time/value pairs
    public function line(numberofsegments:int, segments:Array):Number {
        // This is a basic multi-segment ramp generator that you can use for more or less anything.
        if (isPlaying == 1) {
            period = 2. / (segments[valindex + 1] * 0.004);
            nextval = segments[valindex + 2];
            currentval = segments[valindex];
            if (currentval - amplitude > 0.0000001 && valindex < numberofsegments) {
                amplitude += ((currentval - startval) / (SAMPLE_RATE/period));
            } else if (currentval - amplitude < -0.0000001 && valindex < numberofsegments) {
                amplitude -= (((currentval - startval) * (-1)) / (SAMPLE_RATE / period));
            } else if (valindex > numberofsegments - 1) {
                valindex = numberofsegments - 2;
            } else {
                valindex = valindex + 2;
                startval = currentval;
            }
            return amplitude;
        }
        else {
            return 0;
        }
    }
}


// control
class Control extends Sprite {
    
    private var 
        bpmKnob:Knob,
        delayLabel:Label, delayTimeKnob:Knob, delayMixKnob:Knob, delayFeedbackKnob:Knob,
        reverbLabel:Label, reverbWetKnob:Knob, reverbFeedbackKnob:Knob;
        
        
        
    private var eqt:Vector.<Number> = new Vector.<Number>(101), moving:Boolean;
    private var rvbt:Vector.<Number> = new Vector.<Number>(101);
    function Control(parent:DisplayObjectContainer) {
        super();
        
        //    for (var i:int=0; i<101; i++) eqt[i] = Math.pow(2, i*0.04-2);
//        low = _newKnob(280, "EQ Low", 0, 100,  50, _updateEQ);
//        mid = _newKnob(320, "Middle", 0, 100,  50, _updateEQ);
//        high =_newKnob(360, "High",   0, 100,  50, _updateEQ);
//        lowVal  = new Label(this, 276, 38, "1.00");
//        midVal  = new Label(this, 316, 38, "1.00");
//        highVal = new Label(this, 356, 38, "1.00");
        
        //Style.setStyle(Style.DARK);
        
        
        bpmKnob = _newKnob(20, 0, "bpm", 1, 999, 60, function(e:Event):void {
            bpmKnob.value = int(bpmKnob.value);
            _bpm_ = bpmKnob.value;
        });
        bpmKnob.labelPrecision = 0;
        
        
        var synthSelectLabel:Label = new Label(this, 100, 0, "synth selector");
        var synthSelector:NumericStepper = new NumericStepper(this, 100, 20, function(e:Event):void {
            _synth_.mode= synthSelector.value;
        });
        synthSelector.value = 0;
        synthSelector.minimum = -1;
        synthSelector.maximum = 4;
        
        
        var delayPos:Point = new Point(100, 100);
        var delayCheck:CheckBox = new CheckBox(this, delayPos.x, delayPos.y + 4, "delay", function(e:Event):void {
            if (delayCheck.selected) {
                _delayEffect_.bypass = false; 
            } else {
                _delayEffect_.bypass = true;
            }
        });
        delayTimeKnob     = _newKnob(delayPos.x + 50,  delayPos.y, "time",     0, 1, 0.5,  _updateDelay);
        delayFeedbackKnob = _newKnob(delayPos.x + 100, delayPos.y, "feedback", 0, 1, 0.65, _updateDelay);
        delayMixKnob      = _newKnob(delayPos.x + 150, delayPos.y, "mix",      0, 1, 0.65, _updateDelay);
        function _updateDelay(e:Event):void {
            _delayEffect_.setParameters(delayMixKnob.value, delayFeedbackKnob.value, delayTimeKnob.value);
        }            
        
        
        var reverbPos:Point = new Point(100, 200);
        var reverbCheck:CheckBox = new CheckBox(this, reverbPos.x, reverbPos.y + 4, "reverb", function(e:Event):void {
            if (reverbCheck.selected) {
                _reverbEffect_.bypass = false; 
            } else {
                _reverbEffect_.bypass = true;
                _reverbEffect_.prepareProcess();
            }
        });        
        reverbWetKnob      = _newKnob(reverbPos.x + 50,  reverbPos.y, "dry/wet",   0, 1, 0.3, _updateReverb);
        reverbFeedbackKnob = _newKnob(reverbPos.x + 100, reverbPos.y, "feedback",  0, 1, 0.8, _updateReverb);
        function _updateReverb(e:Event):void {
            _reverbEffect_.setParameters(0.7, 0.4, reverbFeedbackKnob.value, reverbWetKnob.value);
        }        
        
        parent.addChild(this);
    }
    public function set bpm(bpm:Number) : void { 
        bpmKnob.value = int(bpm); 
    }
    
    //private function _newCheckbox(x:Number, y:Number, lable:String, 
    private function _newKnob(x:Number, y:Number, label:String, min:Number, max:Number, val:Number, onChange:Function) : Knob {
        var knob:Knob = new Knob(this, x, y, label, onChange);
        knob.radius = 12;
        knob.labelPrecision = 2;
        knob.minimum = min;
        knob.maximum = max;
        knob.value = val;
        //knob.showValue = false;
        return knob;
    }
    private function _updateEQ(e:Event) : void {
//        var l:Number = eqt[int(low.value)], 
//            m:Number = eqt[int(mid.value)], 
//            h:Number = eqt[int(high.value)];
//        //eq.setParameters(l, m, h);
//        lowVal.text = l.toFixed(2);
//        midVal.text = m.toFixed(2);
//        highVal.text = h.toFixed(2);
    }
}


// UTIL
class Util {
    public static function clamp(value:Number, min:Number, max:Number):Number {
        return value < min ? min : (value > max ? max : value);
    }
}