forked from: Lissajous

by fukt
drag down and tune me!
♥0 | Line 177 | Modified 2009-10-22 08:49:33 | MIT License
play

ActionScript3 source code

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

// forked from tdpt's Lissajous
//
// drag down and tune me!
//
package {

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.SampleDataEvent;
    import flash.geom.ColorTransform;
    import flash.media.Sound;
    import flash.media.SoundChannel;

    [SWF(backgroundColor="0x000000", frameRate="24", width="465", height="465")]
    public class Lissajous extends Sprite {

        private const _step : Number = 0.01;

        private var _bitmap : BitmapData;
        private var _delay : ColorTransform;
        private var _lastPosition : Number;

        private var _freqX : Number = 440;
        private var _freqY : Number = 480.03;

        private var _oscX : Oscillator;
        private var _oscY : Oscillator;

        private var _mousePress : Boolean = false;

        private var _lastFreqY : Number;
        private var _lastMouseY : Number;

        private var _channel : SoundChannel;

        public function Lissajous() {

            var sp : Sprite = new Sprite();
            var g : Graphics = sp.graphics;
            g.clear();
            g.beginFill(0x000000);
            g.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            g.endFill();
            addChild(sp);
            
            _bitmap = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000);
            addChild(new Bitmap(_bitmap) );
            
            _delay = new ColorTransform(1, 1, 1, 1, -8, -32, -16);

            _oscX = new Oscillator();
            _oscY = new Oscillator();

            var sound : Sound = new Sound();
            sound.addEventListener(SampleDataEvent.SAMPLE_DATA, sound_sampleDataHandler);
            _channel = sound.play();
            _lastPosition = _channel.position;

            addEventListener(Event.ENTER_FRAME, enterFrameHandler);    
            stage.addEventListener(MouseEvent.MOUSE_DOWN, stage_mouseDownHandler);
        }

        private function sound_sampleDataHandler(event : SampleDataEvent) : void {

            for (var i : int = 0; i < 5120; i++) {

                _oscX.frequency = _freqX;
                _oscY.frequency = _freqY;

                var value : Number = (_oscX.getValue(event.position + i)
                            + _oscY.getValue(event.position + i) ) * 0.1;
                event.data.writeFloat(value);
                event.data.writeFloat(value);
            }
        }

        private function enterFrameHandler(event : Event) : void {

            _bitmap.lock();

            _bitmap.colorTransform(_bitmap.rect, _delay);

            var w : int = stage.stageWidth / 2;
            var h : int = stage.stageHeight / 2;
            var position : Number = _channel.position;
            
            for (var i : Number = _lastPosition; i < position; i += _step) {
                var x : Number = _oscX.getValue(Fs * i * 0.1) * w + w;
                var y : Number = _oscY.getValue(Fs * i * 0.08) * h + h;
                _bitmap.setPixel32(x, y, 0xffffffff);
            }

            _lastPosition = position;

            _bitmap.unlock();
            
        }
        
        private function stage_mouseDownHandler(event : MouseEvent) : void {
            if (_mousePress) return;
            _mousePress = true;
            stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
            stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
            stage.addEventListener(Event.MOUSE_LEAVE, stage_mouseLeaveHandler);

            _lastFreqY = _freqY;
            _lastMouseY = mouseY;
        }

        private function stage_mouseMoveHandler(event : MouseEvent) : void {
            if (!_mousePress) return;
            _freqY = _lastFreqY * Math.pow(2, (_lastMouseY - mouseY) / 12 * 0.001);
        }

        private function stage_mouseUpHandler(event : MouseEvent) : void {
            mouseRelease();
        }

        private function stage_mouseLeaveHandler(event : Event) : void {
            mouseRelease();
        }
        
        private function mouseRelease() : void {
            if (!_mousePress) return;
            _mousePress = false;
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
            stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
            stage.removeEventListener(Event.MOUSE_LEAVE, stage_mouseLeaveHandler);
        }
    }
}


// sampling rate (fixed)
const Fs : Number = 44100;

class OscillatorWaveForm {
    public static const SAW : String = "saw";
    public static const SQUARE : String = "square";
    public static const SIN : String = "sin";
    public static const TRIANGLE : String = "triangle";
}

class Oscillator {

    private static const _RPS : Number = 2 * Math.PI / Fs;
    private static const _PI : Number = Math.PI;
    private static const _2PI : Number = 2 * Math.PI;

    private var _offset : int;
    private var _frequency : Number;
    private var _lastFrequency : Number;
    private var _waveForm : String;
    private var _valid : Boolean;

    private var _waveFunc : Function;
    
    public function Oscillator() {
        _offset = 0;
        _frequency = 440;
        _lastFrequency = frequency;
        _waveForm = OscillatorWaveForm.SIN;
        _valid = false;
    }

    public function get waveForm() : String {
        return _waveForm;
    }
    
    public function set waveForm(value : String) : void {
        if (_waveForm == value) return;
        _waveForm = value;
        _valid = false;
    }

    public function get frequency() : Number { 
        return _frequency;
    }    

    public function set frequency(value : Number) : void { 
        _frequency = value;
    }

    public function getValue(position : int) : Number {
        
        if (!_valid) {
            validate();
            _valid = true;
        }

        if (_lastFrequency != _frequency) {
            // smoothing
            _offset = (_offset + position) * _lastFrequency / _frequency - position;
            _lastFrequency = _frequency;
        }

        return _waveFunc( (_offset + position) * _RPS * _frequency);
    }
    
    private function validate() : void {

        switch(_waveForm) {

        case OscillatorWaveForm.SAW :
            _waveFunc = saw;
            break;

        case OscillatorWaveForm.SQUARE :
            _waveFunc = square;
            break;

        case OscillatorWaveForm.TRIANGLE :
            _waveFunc = triangle;
            break;

        case OscillatorWaveForm.SIN :
            _waveFunc = Math.sin;
            break;

        default :
            throw new Error(_waveForm);
        }
    }

    private static function square(t : Number) : Number {
        t = t % _2PI;
        return (t < _PI)? 1 : -1;
    }

    private static function saw(t : Number) : Number {
        t = t % _2PI;
        return t / _PI - 1;
    }

    private static function triangle(t : Number) : Number {
        t = t % _2PI;
        return (t < _PI)? 2 * t / _PI - 1 : 3 - 2 * t / _PI;
    }
}