/* 元祖 つhttp://0xcc.net/blog/archives/000160.html */ package { import flash.display.Sprite; import flash.events.*; import flash.utils.Timer; import flash.text.TextField; import flash.text.TextFormat; import flash.text.TextFieldAutoSize; [SWF(backgroundColor="#000000", frameRate=20)] public class Sort extends Sprite { private const STAGESIZE:int = 300; private const SIZE:int = 50; private const SORTSPEED:int = 100; private var data:Array; private var timer:Timer; private var tf:TextField; private var k:int, l:int; //あんまり使いたくない private var oscs:Vector.<OSC> public function Sort() { oscs = new Vector.<OSC>() for (var j:int = 0; j < 10; j++) { oscs[j] = new SineOSC() oscs[j].frequency = 100 var offset:Number = i*5 oscs[j].generateEnvelop(0, 0, offset, .8, 10 + offset, 0, 50 + offset) //oscs[j].volume = .2// + (j * .03) } tf = new TextField(); tf.y = stage.stageHeight - 50; tf.autoSize = TextFieldAutoSize.LEFT; var format:TextFormat = new TextFormat(); format.font = "_typewriter"; format.color = "0xCCCCCC"; format.size = 23; tf.defaultTextFormat = format; addChild(tf); data = new Array(SIZE); for (var i:int = 0; i < SIZE; i++) { var d:Data = new Data(STAGESIZE / SIZE); d.x = i * STAGESIZE / SIZE; d.y = i * STAGESIZE / SIZE; addChild(d); data[i] = d; } bubbleSort(); } private function random(data:Array):void { for (var i:int = 0; i < 100; i++) { var a:int = Math.floor(Math.random() * data.length); var b:int = Math.floor(Math.random() * data.length); var temp:int = data[a].y; data[a].y = data[b].y; data[b].y = temp; } } private function playSound():void { for (var i:int = 0; i < 10; i++) { oscs[i].frequency = 60 * data[i * 5].y + 40; oscs[i].play() } } private function bubbleSort(event:TimerEvent = null):void { tf.text = "BubbleSort"; random(data); timer = new Timer(SORTSPEED); timer.repeatCount = data.length - 1; timer.addEventListener(TimerEvent.TIMER, _bubbleSort); timer.addEventListener(TimerEvent.TIMER_COMPLETE, selectionSort); timer.start(); } private function _bubbleSort(event:TimerEvent):void { for (var j:int = 0; j < data.length - event.target.currentCount; j++) { if (data[j].y > data[j + 1].y) swap(data[j], data[j + 1]); } playSound() } private function selectionSort(event:TimerEvent = null):void { tf.text = "SelectionSort"; random(data); timer = new Timer(SORTSPEED); timer.repeatCount = data.length - 1; timer.addEventListener(TimerEvent.TIMER, _selectionSort); timer.addEventListener(TimerEvent.TIMER_COMPLETE, insertionSort); timer.start(); } private function _selectionSort(event:TimerEvent):void { var i:int = event.target.currentCount - 1; var min:int = i; for (var j:int = i + 1; j < data.length; j++) { if (data[min].y > data[j].y) min = j; } swap(data[min], data[i]); playSound() } private function swap(a:Data, b:Data):void { var temp:int = a.y; a.y = b.y; b.y = temp; } private function insertionSort(event:TimerEvent = null):void { tf.text = "InsertionSort"; random(data); timer= new Timer(SORTSPEED); timer.repeatCount = data.length - 1; timer.addEventListener(TimerEvent.TIMER, _insertionSort); timer.addEventListener(TimerEvent.TIMER_COMPLETE, shellSort); timer.start(); } private function _insertionSort(event:TimerEvent):void { var i:int = event.target.currentCount; var tmp:int = data[i].y; for (var j:int = i; j > 0 && data[j - 1].y > tmp; j--) { data[j].y = data[j - 1].y; } data[j].y = tmp; playSound() } private function shellSort(event:TimerEvent = null):void { k = data.length / 2; l = k; tf.text = "ShellSort"; random(data); timer = new Timer(SORTSPEED / 2); timer.repeatCount = 999; //適当 timer.addEventListener(TimerEvent.TIMER, _shellSort); timer.start(); } private function _shellSort(event:TimerEvent):void { if (l >= data.length) { k /= 2; l = k; if (k <= 0) { timer.stop(); shakerSort(); return; } } var j:int; var temp:int = data[l].y; for (j = l - k; j >= 0 && data[j].y > temp; j -= k) { data[j + k].y = data[j].y; } data[j + k].y = temp; l++; playSound() } private function shakerSort(event:TimerEvent = null):void { tf.text = "ShakerSort"; random(data); timer = new Timer(SORTSPEED); timer.repeatCount = data.length - 1; timer.addEventListener(TimerEvent.TIMER, _shakerSort); timer.addEventListener(TimerEvent.TIMER_COMPLETE, heapSort); timer.start(); } private function _shakerSort(event:Event):void { var i:int = event.target.currentCount; for (var j:int = 0; j < data.length - i; j++) { if (data[j].y > data[j + 1].y) swap(data[j], data[j + 1]); } for (j = data.length - i; j > 0; j--) { if (data[j].y < data[j - 1].y) swap(data[j], data[j - 1]); } playSound() } private function heapSort(event:TimerEvent):void { tf.text = "HeapSort"; random(data); timer = new Timer(SORTSPEED); timer.repeatCount = (data.length - 2) / 2 + 1; timer.addEventListener(TimerEvent.TIMER, _heapSort); timer.addEventListener(TimerEvent.TIMER_COMPLETE, _heapSort2); timer.start(); } private function _heapSort(event:TimerEvent = null):void { var i:int = event.target.currentCount; _makeHeap((data.length - 2) / 2 - i + 1, data.length - 1); playSound() } private function _heapSort2(event:TimerEvent):void { timer = new Timer(SORTSPEED); timer.repeatCount = data.length - 1; timer.addEventListener(TimerEvent.TIMER, __heapSort2); timer.addEventListener(TimerEvent.TIMER_COMPLETE, gnomeSort); timer.start(); } private function __heapSort2(event:TimerEvent):void { var i:int = event.target.currentCount; swap(data[0], data[data.length - i]); _makeHeap(0, data.length - i - 1); } private function _makeHeap(parent:int, r:int):void { var p:int = data[parent].y; while (true) { var left:int = parent * 2 + 1; if (left > r) break; if (left != r) { if (data[left + 1].y > data[left].y) left++; } if (p >= data[left].y) break; data[parent].y = data[left].y; parent = left; } data[parent].y = p; playSound() } private function gnomeSort(event:TimerEvent = null):void { tf.text = "GnomeSort"; random(data); k = 1, l = 2; timer = new Timer(SORTSPEED / 3); timer.repeatCount = 999; //適当 timer.addEventListener(TimerEvent.TIMER, _gnomeSort); timer.start(); } private function _gnomeSort(event:TimerEvent):void { if (k >= data.length) { timer.stop(); end(); return; } if (data[k - 1].y <= data[k].y) { k = l; l++; } else { swap(data[k - 1], data[k]); k--; if (k == 0) k = 1; } playSound() } private function end(event:TimerEvent = null):void { tf.text = "終わり"; } } } import flash.display.Sprite; class Data extends Sprite { public function Data(size:int) { graphics.beginFill(0xFF33FF); graphics.drawRect(0, 0, size, size); graphics.endFill(); } } import flash.display.Sprite; import flash.events.Event; import flash.events.EventDispatcher; import flash.events.SampleDataEvent; import flash.media.Sound; import flash.utils.ByteArray; class Master extends EventDispatcher { static public const PI2:Number = Math.PI * 2; static public const SAMPLE_RATE:uint = 44100; static public const TIME_PER_BYTE:Number = 1000/44100; static public var LATENCY:uint = 2048 //2048~8192 static private var instance:Master private const _LATENCY:uint = LATENCY private var oscs:Vector.<OSC> private var sound:Sound protected var phase:Number = 0 static public function getInstance():Master { if (instance) { return instance }else { instance = new Master() return instance } } public function Master() { oscs = new Vector.<OSC>() sound = new Sound() sound.addEventListener(SampleDataEvent.SAMPLE_DATA, update) sound.play() } public function addOSC(osc:OSC):OSC { oscs.push(osc) return osc } public function removeOSC(osc:OSC):OSC { var index:int = oscs.indexOf(osc) oscs.splice(index, 1); return osc; } private function update(e:SampleDataEvent):void { dispatchEvent(e) var oscs:Vector.<OSC> = this.oscs var n:int = _LATENCY var data:ByteArray = e.data for each(var osc:OSC in oscs) osc.update() for (var i:int = 0; i < n; i++) { var s:Number = 0; for each(var osc1:OSC in oscs) s += osc1.sample[i]; data.writeFloat(s) data.writeFloat(s) } } } class OSC extends EventDispatcher { protected const PI:Number = Math.PI protected const PI2:Number = Math.PI * 2; protected const LATENCY:int = Master.LATENCY protected const SAMPLE_RATE:uint = Master.SAMPLE_RATE; protected const TIME_PER_BYTE:Number = 1000.0 / SAMPLE_RATE; private var master:Master; private var _listen:Boolean; private var _frequency:Number; protected var _amplifier:Number; protected var envelopTime:Number; protected var envelop:Vector.<Number> protected var _filters:Vector.<SoundFilter> protected var phase:Number = 0; protected var deltPhase:Number; protected var initAmplifier:Number; protected var lastAmplifier:Number; protected var envelopValue:Vector.<Number>; protected var envelopInterval:Vector.<Number>; protected var envelopLength:int protected var _random:Function = Math.random public var volume:Number; public var sample:Vector.<Number>; public var isMute:Boolean public function OSC() { init() } private function init():void { master = Master.getInstance(); _frequency = 440; _listen = true; deltPhase = PI2 * _frequency / SAMPLE_RATE; volume = .2; generateEnvelop(0,1,50,0,100) sample = new Vector.<Number>(LATENCY); _filters = new Vector.<SoundFilter>(); master.addOSC(this) } public function generateEnvelop(init:Number, ...arg):void { initAmplifier = init; envelopValue = new Vector.<Number>() envelopInterval = new Vector.<Number>() var n:int = arg.length >> 1;//int(arg.length / 2) var previousValue:Number = initAmplifier var prevInterval:Number = 0; for (var i:int = 0; i < n; i++) { var ii:int = i << 1 // i*2 envelopInterval[i] = arg[ii + 1]+prevInterval; envelopValue[i] = (arg[ii] - previousValue) / ((arg[ii + 1]/1000)*SAMPLE_RATE); previousValue = arg[ii] prevInterval = envelopInterval[i] } lastAmplifier = previousValue; envelopTime = prevInterval envelopLength = n trace("generateEnvelop") trace(arg) trace(envelopValue) trace(envelopInterval) trace("--------------") } public function update():void { } public function play():void { //listen = true envelopTime = 0 _amplifier = initAmplifier } public function get listen():Boolean { return _listen; } public function set listen(value:Boolean):void { if (_listen == value) return; _listen = value; if (value) master.addOSC(this); else master.removeOSC(this); } public function get frequency():Number { return _frequency; } public function set frequency(value:Number):void { _frequency = value; deltPhase = PI2 * _frequency / SAMPLE_RATE; } public function get amplifier():Number { return _amplifier; } public function get filters():Vector.<SoundFilter> { return _filters; } public function set filters(value:Vector.<SoundFilter>):void { _filters = value; } } class SineOSC extends OSC { override public function update():void { var n:int = LATENCY var m:int = envelopLength-1; for (var i:int = 0; i < n; i++) { phase = (phase + deltPhase) % PI2; envelopTime += TIME_PER_BYTE; for (var j:int = 0; j <= m; j++) { if (envelopTime <= envelopInterval[j]) { _amplifier += envelopValue[j]; break; } else if (envelopTime > envelopInterval[m]) { _amplifier=lastAmplifier break; } }; sample[i] = Math.sin(phase) * _amplifier * volume; } var nn:uint = _filters.length for (var ii:int = 0; ii < nn; ii++) _filters[0].process(sample); } } class SawOSC extends OSC { override public function update():void { var envelopInterval:Vector.<Number> = this.envelopInterval var envelopValue:Vector.<Number> = this.envelopValue var n:int = LATENCY var m:int = envelopLength-1; for (var i:int = 0; i < n; i++) { phase = (phase + deltPhase) % PI2; envelopTime += TIME_PER_BYTE; for (var j:int = 0; j <= m; j++) { if (envelopTime <= envelopInterval[j]) { _amplifier += envelopValue[j]; break; } else if (envelopTime > envelopInterval[m]) { _amplifier = lastAmplifier; break; } }; sample[i] = (-phase / PI + 1) * _amplifier * volume; } var nn:uint = _filters.length for (var ii:int = 0; ii < nn; ii++) _filters[0].process(sample); } } class SquareOSC extends OSC { override public function update():void { var envelopInterval:Vector.<Number> = this.envelopInterval var envelopValue:Vector.<Number> = this.envelopValue var n:int = LATENCY var m:int = envelopLength-1; for (var i:int = 0; i < n; i++) { phase = (phase + deltPhase) % PI2; envelopTime += TIME_PER_BYTE; for (var j:int = 0; j <= m; j++) { if (envelopTime <= envelopInterval[j]) { _amplifier += envelopValue[j]; break; } else if (envelopTime > envelopInterval[m]) { _amplifier = lastAmplifier; break; } }; sample[i] = ((phase > PI)?1: -1) * _amplifier * volume; } var nn:uint = _filters.length for (var ii:int = 0; ii < nn; ii++) _filters[0].process(sample); } } class TriangleOSC extends OSC { override public function update():void { var envelopInterval:Vector.<Number> = this.envelopInterval var envelopValue:Vector.<Number> = this.envelopValue var n:int = LATENCY var m:int = envelopLength-1; for (var i:int = 0; i < n; i++) { phase = (phase + deltPhase) % PI2; envelopTime += TIME_PER_BYTE; for (var j:int = 0; j <= m; j++) { if (envelopTime <= envelopInterval[j]) { _amplifier += envelopValue[j]; break; } else if (envelopTime > envelopInterval[m]) { _amplifier = lastAmplifier; break; } }; var s:Number = (phase / PI - 1) if (s > 0) sample[i] = (s * 2 -1) * _amplifier * volume; else sample[i] = (s * -2 -1) * _amplifier * volume; } var nn:uint = _filters.length for (var ii:int = 0; ii < nn; ii++) _filters[0].process(sample); } } class NoiseOSC extends OSC { override public function update():void { var envelopInterval:Vector.<Number> = this.envelopInterval var envelopValue:Vector.<Number> = this.envelopValue var n:int = LATENCY var m:int = envelopLength-1; for (var i:int = 0; i < n; i++) { phase = (phase + deltPhase) % PI2; envelopTime += TIME_PER_BYTE; for (var j:int = 0; j <= m; j++) { if (envelopTime <= envelopInterval[j]) { _amplifier += envelopValue[j]; break; } else if (envelopTime > envelopInterval[m]) { _amplifier = lastAmplifier; break; } }; sample[i] = (Math.random() * 2 - 1) * _amplifier * volume; } var nn:uint = _filters.length for (var ii:int = 0; ii < nn; ii++) _filters[0].process(sample); } } class Bass extends OSC { public var initFrequency:uint = 300 public var endFrequency:uint = 10 public var length:uint = 2000 override public function play():void { super.play() frequency = initFrequency } override public function update():void { var m:int = envelopLength-1 var n:int = LATENCY for (var i:int = 0; i < n; i++) { this.frequency += (endFrequency - frequency) / length phase = (phase + deltPhase) % PI2; envelopTime += TIME_PER_BYTE; for (var j:int = 0; j <= m; j++) { if (envelopTime <= envelopInterval[j]) { _amplifier += envelopValue[j]; break; } else if (envelopTime > envelopInterval[m]) { _amplifier = lastAmplifier; break; } }; sample[i] = Math.sin(phase) * amplifier * volume; } var nn:uint = _filters.length for (var ii:int = 0; ii < nn; ii++) _filters[0].process(sample); } } class SoundFilter { protected var osc:OSC public function addOSC(osc:OSC):void { this.osc = osc } public function process(sample:Vector.<Number>):void { } } class ResonatFilter extends SoundFilter { private var buf0:Number = 0 ; private var buf1:Number = 0 ; private var cutoff:Number; private var q:Number; private var type:int; static public const LPF:uint = 0; static public const BPF:uint = 1; static public const HPF:uint = 2; public function ResonatFilter(type:int,cutoff:Number=440,q:Number=0.5) { this.type = type; this.cutoff = cutoff this.q = q } override public function process(sample:Vector.<Number>):void { // f and fb calculation var f:Number = 2.0 * Math.sin(Math.PI * cutoff / Master.SAMPLE_RATE); var fb:Number = q + q/(1.0 - f); var n:int = Master.LATENCY; var hp:Number; var bp:Number; for (var i:int = 0; i < n; i++) { hp = sample[i] - buf0; bp = buf0 - buf1; buf0 = buf0 + f * (hp + fb * bp); buf1 = buf1 + f * (buf0 - buf1); sample[i] = (type == 0)?buf1:(type == 1)?bp:hp; } } } 各種ソートアルゴリズムを可聴化