各種ソートアルゴリズムを可聴化
元祖 つhttp://0xcc.net/blog/archives/000160.html
/*
元祖 つ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;
}
}
}