// forked from keim_at_Si's ((♪)) package { import flash.utils.ByteArray; import flash.display.*; import flash.events.*; import flash.filters.*; import flash.media.*; import flash.text.*; import flash.geom.*; import flash.utils.setTimeout; [SWF(width="465", height="465", backgroundColor="#ffffff", frameRate=30)] public class MySound extends Sprite { private var module:TinySiOPM=new TinySiOPM(2048), sound:Sound=new Sound(), channel:SoundChannel; private var bshc:String = "80008000800080008000"; private var tone:Array = [672,4,0,20,-48]; private var pointer:int, frame:int, frameCounter:int, note:int, bound:int, autoNum:int, wave:int, beat:int; private var shape:Shape=new Shape(), mat:Matrix=new Matrix(), pos:Number, scl:Number; private var container:Sprite; public function MySound() { super(); container = new Sprite(); makeCircle(container.graphics); addChild(container); container.x = stage.stageWidth /2 - container.width/2; container.y = stage.stageHeight /2 - container.height/2; pointer=0; frame=3; frameCounter=0; note=0; bound=0; autoNum=1; wave=2; pos=500; scl=1; beat=0; animationFrame = 0; sound.addEventListener('sampleData', _onStream); channel = sound.play(); container.addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function _onStream(e:SampleDataEvent) : void { //4回に1回 if (frameCounter >= frame) { frameCounter = 0; var v:int = parseInt(bshc.charAt(pointer), 16); var _pitch:int = tone[0]; var _velocity:int = (v<<tone[1]); var _tone:int = tone[2]; var _decay:int = tone[3]; var _sweep:int = tone[4]; if (v) { module.noteOn(_pitch, _velocity, _tone, _decay, _sweep); } pointer = (pointer + 1) & 15; var latency:Number = e.position/44.1 - channel.position; if(pointer%4==0)playSound(latency); } frameCounter++; module.buffer(e.data); //2048ずつ書き込む } private function playSound(latency:Number):void { setTimeout(resetPosition, latency); } private function resetPosition():void { container.scaleX = 1; container.scaleY = 1; } private function makeCircle(g:Graphics):void { g.beginFill(0x000000, 0.8); g.drawCircle(0,0,20); g.endFill(); } private var animationFrame:Number; private function onEnterFrame(event:Event):void { container.scaleX += 0.1; container.scaleY += 0.1; } } } import flash.utils.ByteArray; class TinySiOPM { private var _t:Note, _o:Vector.<Number>, _s:int; private var _p:Vector.<int> = new Vector.<int>(2048, true); // pitchTable[128*16] private var _l:Vector.<Number> = new Vector.<Number>(6144, true); // logTable[12*256*2] function TinySiOPM(bufferSize:int=2048) { var i:int, j:int, p:Number, v:Number, t:Vector.<int>; for (i=0, p=0; i<192; i++, p+=0.00520833333) // pitch table for(v=Math.pow(2, p)*12441.464342886, j=i; j<2048; v*=2, j+=192) _p[j] = int(v); for (i=0; i<32; i++) _p[i] = (i+1)<<6; // pitch=0-31 for white noize for (i=0, p=0.0078125; i<256; i+=2, p+=0.0078125) // log table for(v=Math.pow(2, 13-p)*0.0001220703125, j=i; j<3328; v*=0.5, j+=256) _l[j+1] = -(_l[j] = v); for (i=3328; i<6144; i++) _l[i] = 0; var famtri:Array = [0,1,2,3,4,5,6,7,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-8,-7,-6,-5,-4,-3,-2,-1]; for (t=Note.table(10), i=0, p=0; i<1024; i++, p+=0.00613592315) t[i] = _log(Math.sin(p)); // sin=0 for (t=Note.table(10), i=0, p=0.75; i<1024; i++, p-=0.00146484375) t[i] = _log(p); // saw=1 for (t=Note.table(5), i=0; i<32; i++) t[i] = _log(famtri[i]*0.0625); // famtri=2 for (t=Note.table(15), i=0; i<32768; i++) t[i] = _log(Math.random()-0.5); // wnoize=3 for (i=0; i<8; i++) for (t=Note.table(4), j=0; j<16; j++) t[j] = (j<=i) ? 192 : 193; // pulse=4-11 _s=bufferSize; _t=new Note(); _o=new Vector.<Number>(_s, true); for(i=0; i<_s; i++) _o[i]=0; } private function _log(n:Number) : int { return (n<0) ? ((n<-0.00390625) ? (((int(Math.log(-n) * -184.66496523 + 0.5) + 1) << 1) + 1) : 2047) : ((n> 0.00390625) ? (( int(Math.log( n) * -184.66496523 + 0.5) + 1) << 1) : 2046); } public function buffer(data:ByteArray) : void { var n:Note, rep:int, i:int, imax:int, dph:int, lout:int, v:int; for (imax=1024; imax<=_s; imax+=1024) for (n=_t.next; n!=_t; n=n.step()) for (dph=_p[n.pitch], i=imax-1024; i<imax; n.ph=(n.ph+dph)&0x3ffffff, i++) { lout=n.wave[n.ph>>n.shift]+n.gain; _o[i]+=_l[lout]; } for (i=0; i<_s; i++) { data.writeFloat(_o[i]); data.writeFloat(_o[i]); _o[i]=0; } } public function noteOn(pitch:int, velocity:int=64, tone:int=0, decay:int=4, sweep:int=0) : Note { return Note.alloc().reset(pitch, _log(velocity*0.0078125), tone, (decay<<2), sweep).into(_t); } } class Note { public var prev:Note, next:Note, ph:int, pitch:int, gain:int, sweep:int, decay:int, wave:Vector.<int>, shift:int; static private var _w:Array=[], _s:Array=[], _fl:Note = new Note(); function Note() { prev = next = this; } public function free() : Note { var r:Note=prev; r.next=next; next.prev=r; into(_fl); return r; } public function into(n:Note) : Note { prev=n.prev; next=n; prev.next=this; next.prev=this; return this; } public function step() : Note { gain+=decay; pitch+=sweep; pitch&=2047; return (gain>3328)?(free().next):next; } public function reset(p:int, g:int, t:int, d:int, s:int) : Note { ph=0; pitch=p; gain=g; sweep=s; decay=d<<1; wave=_w[t]; shift=_s[t]; return this; } static public function table(b:int) : Vector.<int> { var t:Vector.<int>=new Vector.<int>(1<<b, true); _w.push(t); _s.push(26-b); return t; } static public function alloc() : Note { if (_fl.prev==_fl) { return new Note(); } var r:Note=_fl.prev; _fl.prev=r.prev; _fl.prev.next=_fl; return r; } } Minimal beat forked from: ((♪))