package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.SampleDataEvent; import flash.media.Sound; import flash.utils.setTimeout; /** * * * 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.; private var _periodIndex: int; private var _current: Number; private var _feedNoise: Boolean; public function KarplusStrong() { _periodN = 44100 / 220; // length = sampleRate / targetFrequency (ignoring fractional) _period = new Vector.( _periodN, true ); _periodIndex = 0; _feedNoise = true; _current = 0.0; _sound = new Sound(); _sound.addEventListener( SampleDataEvent.SAMPLE_DATA, sampleData ); stage.addEventListener( MouseEvent.MOUSE_DOWN, function ( event: MouseEvent ): void { _feedNoise = true; } ); setTimeout( _sound.play, 500 ); // delay start to avoid glitches } private function sampleData(event: SampleDataEvent): void { for( var i: int = 0 ; i < NUM_SAMPLES ; ++i ) { if( _periodIndex == _periodN ) // wrap around delay-line { _periodIndex = 0; _feedNoise = false; } if( _feedNoise ) { _period[ _periodIndex ] += Math.random() - Math.random(); // feed noise between -1 and +1 } _current += ( _period[ _periodIndex ] - _current ) * .5; // 1 pole lowpass (removing energie from the system) _period[ _periodIndex ] = _current; // write feedback // write amplitude to event > output event.data.writeFloat( _current ); event.data.writeFloat( _current ); ++_periodIndex; } } } }