|開発環境|Apache [[Flex]] SDK 4.12.1| ||FlashDevelop 4.6.2.5| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|ActionScript 3/AS3 Project| |プロジェクト名|WaveFormFM2| #table_zebra(project, #fff, #eee) http://www.maroon.dti.ne.jp/lance/flash/waveformfm2.html Main.as #highlight(actionscript){{ package { import flash.display.Graphics; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.events.SampleDataEvent; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundTransform; import flash.text.TextField; import mx.utils.StringUtil; public class Main extends Sprite { private const oplist:Array = [ [ 10, 10, "OP1" ], [ 110, 10, "OP2" ], [ 10, 110, "OP3" ], [ 110, 110, "OP4" ], [ 210, 60, "Output" ], ]; private const algoinp:Array = [ [ 0x0, 0x1, 0x2, 0x4, 0x8 ], [ 0x0, 0x0, 0x3, 0x4, 0x8 ], [ 0x0, 0x0, 0x2, 0x5, 0x8 ], [ 0x0, 0x1, 0x0, 0x6, 0x8 ], [ 0x0, 0x1, 0x0, 0x4, 0xa ], [ 0x0, 0x1, 0x1, 0x1, 0xe ], [ 0x0, 0x1, 0x0, 0x0, 0xe ], [ 0x0, 0x0, 0x0, 0x0, 0xf ], ]; private const PI2:Number = Math.PI * 2; private const SR:int = 44100; // sampling rate private const BGCOLOR:uint = 0xffffc0; private const WIDTH:int = 500; private const HEIGHT:int = 50; private var freq:Number = 440; // 周波数 private var wavesplist:Array = new Array; private var playtf:TextField; private var play:Boolean = false; private var masktflist:Array = new Array; private var masklist:Array = new Array; private var multflist:Array = new Array; private var mullist:Array = new Array; private var algoSprite:Sprite = new Sprite; private var algotflist:Array = new Array; private var algorithm:int = 0; private var whlist:Array = new Array(5); // wave height private var sound:Sound = new Sound; private var soundChannel:SoundChannel = null; public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point initWaveForm(); initPlay(); initOpMask(); //OP1 Feedback initMultiple(); initAlgorithm(); drawWaveForm(); drawPlay(); drawMask(); for (var r:int = 0; r < 4; r++) { drawMultiple(r); } drawAlgorithm(); sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData); } private function initWaveForm():void { for (var r:int = 0; r < 5; r++) { var tf:TextField = new TextField; tf.x = 10; tf.y = 10 + (HEIGHT * 2 + 10) * r; tf.width = 100; tf.height = HEIGHT * 2; tf.border = true; tf.selectable = false; tf.text = oplist[r][2]; addChild(tf); var sp:Sprite = new Sprite; sp.x = 120; sp.y = tf.y; addChild(sp); wavesplist[r] = sp; } } private function initPlay():void { var tf:TextField = new TextField; tf.x = 10; tf.y = 600; tf.width = 100; tf.height = 50; tf.text = "Play"; tf.border = true; tf.selectable = false; tf.background = true; tf.name = "p"; tf.addEventListener(MouseEvent.CLICK, onClick); addChild(tf); playtf = tf; } private function initOpMask():void { var tf:TextField = new TextField; tf.x = 120; tf.y = 570; tf.text = "Op. mask:"; addChild(tf); for (var r:int = 0; r < 4; r++) { tf = new TextField; tf.x = 120; tf.y = 600 + 30 * r; tf.width = 40; tf.height = 20; tf.text = oplist[r][2]; tf.border = true; tf.selectable = false; tf.background = true; tf.name = StringUtil.substitute("o {0}", r); tf.addEventListener(MouseEvent.CLICK, onClick); addChild(tf); masktflist.push(tf); masklist.push(true); } } private function initMultiple():void { var tf:TextField = new TextField; tf.x = 200; tf.y = 570; tf.text = "Multiple:"; addChild(tf); for (var r:int = 0; r < 4; r++) { var y:Number = 600 + 30 * r; multflist[r] = new Array; mullist[r] = 1; for (var i:int = 0; i < 16; i++) { tf = new TextField; tf.x = 200 + 30 * i; tf.y = y; tf.width = 30; tf.height = 20; tf.text = i.toString(); tf.border = true; tf.selectable = false; tf.background = true; tf.name = StringUtil.substitute("m {0} {1}", r, i); tf.addEventListener(MouseEvent.CLICK, onClick); addChild(tf); multflist[r][i] = tf; } } } private function initAlgorithm():void { var tf:TextField = new TextField; tf.x = 640; tf.y = 10; tf.text = "Algorithm:"; addChild(tf); for (var r:int = 0; r < 8; r++) { tf = new TextField; tf.x = 640; tf.y = 40 + 30 * r; tf.width = 30; tf.height = 20; tf.text = r.toString(); tf.border = true; tf.selectable = false; tf.background = true; tf.name = StringUtil.substitute("a {0}", r); tf.addEventListener(MouseEvent.CLICK, onClick); addChild(tf); algotflist.push(tf); } algoSprite.x = 680; algoSprite.y = 40; addChild(algoSprite); for (r = 0; r < oplist.length; r++) { tf = new TextField; tf.x = oplist[r][0]; tf.y = oplist[r][1]; tf.width = 50; tf.height = 20; tf.text = oplist[r][2]; tf.border = true; tf.selectable = false; tf.background = true; algoSprite.addChild(tf); } } private function drawWaveForm():void { var aawf:Array = new Array; for (var op:int = 0; op < 5; op++) { aawf[op] = new Array(WIDTH); } // 波形の生成 for (var i:int = 0; i < WIDTH; i++) { sampling(i / SR); for (op = 0; op < 5; op++) { aawf[op][i] = whlist[op]; } } for (op = 0; op < 5; op++) { var g:Graphics = wavesplist[op].graphics; g.clear(); g.beginFill(BGCOLOR); g.drawRect(0, 0, WIDTH, HEIGHT * 2); g.endFill(); g.lineStyle(1); g.moveTo(WIDTH, HEIGHT); g.lineTo(0, HEIGHT); g.lineStyle(1, 0xff0000); var awf:Array = aawf[op]; for (i = 0; i < WIDTH; i++) { g.lineTo(i, HEIGHT - HEIGHT * awf[i]); } } } private function drawPlay():void { playtf.backgroundColor = switchColor(play); } private function drawMask():void { for (var r:int = 0; r < 4; r++) { masktflist[r].backgroundColor = switchColor(masklist[r]); } } private function drawMultiple(r:int):void { for (var i:int = 0; i < 16; i++) { multflist[r][i].backgroundColor = switchColor(i == mullist[r]); } } private function drawAlgorithm():void { for (var r:int = 0; r < 8; r++) { algotflist[r].backgroundColor = switchColor(r == algorithm); } var g:Graphics = algoSprite.graphics; g.clear(); g.beginFill(BGCOLOR); g.drawRect(0, 0, 300, 150); g.endFill(); g.lineStyle(1, 0x0000ff); for (var to:int = 0; to < 5; to++) // target op { var inp:int = algoinp[algorithm][to]; for (var io:int = 0; io < 4; io++) // input op { if (inp & (1 << io)) { g.moveTo(oplist[io][0] + 25, oplist[io][1] + 10); g.lineTo(oplist[to][0] + 25, oplist[to][1] + 10); } } } } private function switchColor(b:Boolean):uint { return b ? 0xffc080 : 0xeeeeee; } private function onClick(e:MouseEvent):void { var arg:Array = e.target.name.split(" "); var r:int; switch (arg[0]) { case "a": algorithm = parseInt(arg[1]); drawAlgorithm(); break; case "m": r = parseInt(arg[1]); var i:int = parseInt(arg[2]); mullist[r] = i; drawMultiple(r); break; case "o": r = parseInt(arg[1]); masklist[r] = !masklist[r]; drawMask(); break; case "p": switchPlay(); drawPlay(); return; default: return; } drawWaveForm(); } private function switchPlay():void { if (play) { if (soundChannel != null) { soundChannel.stop(); soundChannel = null; } play = false; } else { var st:SoundTransform = new SoundTransform; st.volume = 0.2; soundChannel = sound.play(0, 0, st); play = true; } } private function onSampleData(e:SampleDataEvent):void { for (var i:int = 0; i < 4096; i++) { var wh:Number = sampling((e.position + i) / SR); e.data.writeFloat(wh); e.data.writeFloat(wh); } } private function sampling(t:Number):Number { var wh:Number; // OP1-4 for (var op:int = 0; op < 4; op++) { if (masklist[op] == false) { whlist[op] = 0; continue; } wh = 0; var inp:int = algoinp[algorithm][op]; for (var io:int = 0; io < 4; io++) // input op { if (inp & (1 << io)) { wh += whlist[io]; } } var mul:Number = mullist[op]; if (mul == 0) mul = 0.5; whlist[op] = Math.sin(PI2 * mul * freq * t + wh); } // Output / Mixer wh = 0; var count:int = 0; inp = algoinp[algorithm][4]; for (io = 0; io < 4; io++) { if (inp & (1 << io)) { wh += whlist[io]; count++; } } whlist[4] = wh / count; return whlist[4]; } } } }}