forked from: forked from: Andre Michelle's Karplus-Strong Guitar

by yonatan forked from forked from: Andre Michelle's Karplus-Strong Guitar (diff: 43)


Very simple Karplus-Strong example for FFK09 '10 Hot Minutes' in cologne.

An advancement, more guitar-like implementation can be found here:
http://lab.andre-michelle.com/karplus-strong-guitar

@author Andre Michelle
♥0 | Line 83 | Modified 2012-07-16 11:14:46 | 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/fi2N
 */

// forked from yonatan's forked from: Andre Michelle's Karplus-Strong Guitar
// forked from shaktool's Andre Michelle's Karplus-Strong Guitar
package  
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.SampleDataEvent;
    import flash.media.Sound;
    import flash.utils.*;
    import com.bit101.components.*;

    /**
    * <PLUGGED STRING>
    * 
    * Very simple Karplus-Strong example for FFK09 '10 Hot Minutes' in cologne.
    * 
    * An advancement, more guitar-like implementation can be found here:
    * http://lab.andre-michelle.com/karplus-strong-guitar
    * 
    * @author Andre Michelle
    */
    [SWF(width='320',height='240',frameRate='255',backgroundColor='0xFFFFFF')]
    public class KarplusStrong extends Sprite 
    {
        private const NUM_SAMPLES: int = 3072; // 3072 seems the best numSamples to provide with respect to performance and low latency
        
        private var _sound: Sound;
        
        private var _periodN: int;
        private var _period: Vector.<Number>;
        private var _period2: Vector.<Number>;
        private var _periodIndex: int;
        private var _sampleCount: int;
        private var _t0:HUISlider;
        private var _t1:HUISlider;
        private var _t2:HUISlider;
        private var _t3:HUISlider;
        
        private var _current: Number;
        
        public function KarplusStrong()
        {
            _t0 = new HUISlider(this, 0, 0);
            _t0.minimum = 0;
            _t0.maximum = 1;
            _t0.value = 0.5;
            _t1 = new HUISlider(this, 0, 20);
            _t1.minimum = 0;
            _t1.maximum = 1;
            _t1.value = 0.5;
            _t2 = new HUISlider(this, 0, 40);
            _t2.minimum = 0;
            _t2.maximum = 1;
            _t2.value = 0.5;
            _t3 = new HUISlider(this, 0, 60);
            _t3.minimum = 0;
            _t3.maximum = 1;
            _t3.value = 0.5;
            
            _periodN = 44100 / 110; // length = sampleRate / targetFrequency (ignoring fractional)
            _period = new Vector.<Number>( _periodN, true );
            _period2 = new Vector.<Number>( _periodN, true );
            _periodIndex = 0;
            
            _current = 0.0;
            
            _sound = new Sound();
            _sound.addEventListener( SampleDataEvent.SAMPLE_DATA, sampleData );
            
            setTimeout( _sound.play, 500 ); // delay start to avoid glitches
        }
        
        private var b0:Number = 0, b1:Number = 0, b2:Number = 0, b3:Number = 0, b4:Number = 0, b5:Number = 0, b6:Number = 0;
        private function sampleData(event: SampleDataEvent): void
        {
            var t0:Number = _t0.value;
            var t1:Number = _t1.value;//1-t0;//t0-1;
            var t2:Number = _t2.value;
            var t3:Number = _t3.value;//1-t0;//t0-1;
            var damper0:Number = 1/(t0+t1) - 0.01;
            var damper1:Number = 1/(t2+t3) - 0.01;
            for( var i: int = 0 ; i < NUM_SAMPLES ; ++i )
            {
                if( _periodIndex == _periodN ) // wrap around delay-line
                {
                    _periodIndex = 0;
                }

                // var att:Number = _sampleCount%40000 < 10000 ? 1 : 0;
                var att:Number = 0.33 * Math.pow(Math.sin(_sampleCount/40000), 2);
                var white:Number = Math.random()*2-1;
                // var gaussian:Number = (Math.random()+Math.random()+Math.random())*0.666666-1;
                var noise:Number =  white;
                _period[ _periodIndex ] += att < 0 ? 0 : noise * att;
                
                _current = _current * t0 + _period[ _periodIndex] * t1;
                _current *= damper0;
                
                _period[ _periodIndex ] = _current; // write feedback

                _current = _current * t2 + _period2[ _periodIndex] * t3;
                _current *= damper1;
                
                _period2[ _periodIndex ] = _current; // write feedback
                
                // write amplitude to event > output
                event.data.writeFloat( _current );
                event.data.writeFloat( _current );
                
                ++_periodIndex;
                ++_sampleCount;
            }
        }
    }
}