開発環境 Apache Flex SDK 4.12.1
FlashDevelop 4.6.2.5
実行環境 Microsoft Windows 8.1 (64bit)
プロジェクトの種類 ActionScript 3/AS3 Project
プロジェクト名 WaveFormFM2


Main.as
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];
        }
 
    }
 
}
 
最終更新:2014年06月30日 21:36