root/lang/actionscript/flmml/trunk/src/com/txt_nifty/sketch/flmml/MSequencer.as @ 25651

Revision 25651, 6.3 kB (checked in by tekisuke, 5 years ago)

lang/actionscript/flmml/: 終了時のstop()を外側から呼ぶ形に変更(MSequencer)
ファミコン音源の準備。
変数phaseをfloatからintに変更。

Line 
1package com.txt_nifty.sketch.flmml {
2    import flash.events.EventDispatcher;
3    import flash.events.SampleDataEvent;
4    import flash.media.Sound;
5    import flash.media.SoundChannel;
6    import flash.utils.*;
7    import __AS3__.vec.Vector;
8
9    public class MSequencer extends EventDispatcher {
10        public var onSignal:Function = null;
11        public static const BUFFER_SIZE:int         = 8192;
12        public static const RATE44100:int           = 44100;
13
14        protected static const STATUS_STOP:int      = 0;
15        protected static const STATUS_PAUSE:int     = 1;
16        protected static const STATUS_BUFFERING:int = 2;
17        protected static const STATUS_PLAY:int      = 3;
18        protected static const STATUS_LAST1:int     = 4;
19        protected static const STATUS_LAST2:int     = 5;
20        protected var m_sound:Sound;
21        protected var m_soundChannel:SoundChannel;
22        protected var m_buffer:Vector.<Number>;
23        protected var m_trackArr:Array;
24        protected var m_volume:int;              // master volume (max:127)
25        protected var m_signalArr:Array;
26        protected var m_signalPtr:int;
27        protected var m_globalTick:uint;
28        protected var m_status:int;
29        protected var m_signalInterval:int;
30        protected var m_wc:int;
31        protected var m_wt:int;
32
33        public function MSequencer() {
34            MChannel.boot(MSequencer.BUFFER_SIZE);
35            MOscillator.boot();
36            MEnvelope.boot();
37            m_trackArr = new Array();
38            m_volume = 100;
39            m_signalArr = new Array(3);
40            for(var i:int = 0; i < m_signalArr.length; i++) {
41                m_signalArr[i] = new MSignal(i);
42                m_signalArr[i].setFunction(onSignalHandler);
43            }
44            m_signalPtr = 0;
45            m_buffer = new Vector.<Number>(MSequencer.BUFFER_SIZE*2);
46            m_buffer.fixed = true;
47            m_sound = new Sound();
48            m_soundChannel = new SoundChannel();
49            m_status = STATUS_STOP;
50            m_signalInterval = 96;
51            m_sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
52            m_wc = m_wt = 0;
53        }
54
55        public function play():void {
56            if (m_status != STATUS_PAUSE) {
57                stop();
58                m_globalTick = 0;
59                for (var i:int = 0; i < m_trackArr.length; i++) {
60                    m_trackArr[i].seekTop();
61                }
62            }
63            m_status = STATUS_PLAY;
64            m_soundChannel = m_sound.play();
65        }
66
67        public function stop():void {
68            if (m_soundChannel) m_soundChannel.stop();
69            m_status = STATUS_STOP;
70        }
71
72        public function pause():void {
73            if (m_soundChannel) m_soundChannel.stop();
74            m_status = STATUS_PAUSE;
75        }
76
77        public function setMasterVolume(vol:int):void {
78            m_volume = vol;
79        }
80
81        public function isPlaying():Boolean {
82            return (m_status == STATUS_PLAY);
83        }
84
85        public function isPaused():Boolean {
86            return (m_status == STATUS_PAUSE);
87        }
88
89        public function disconnectAll():void {
90            while(m_trackArr.pop());
91            m_status = STATUS_STOP;
92        }
93
94        public function connect(track:MTrack):void {
95            track.m_signalInterval = m_signalInterval;
96            m_trackArr.push(track);
97        }
98
99        public function getGlobalTick():uint {
100            return m_globalTick;
101        }
102
103        public function setSignalInterval(interval:int):void {
104            m_signalInterval = interval;
105        }
106
107        protected function onSignalHandler(globalTick:uint, event:int):void {
108            m_globalTick = globalTick;
109            if (onSignal != null) onSignal(globalTick, event);
110        }
111
112        private function onSampleData(e:SampleDataEvent):void {
113            try {
114                if (m_status < STATUS_BUFFERING) return;
115                if (m_status == STATUS_LAST2) {
116                    dispatchEvent(new MMLEvent(MMLEvent.COMPLETE));
117                    return;
118                }
119                if (m_status == STATUS_LAST1) m_status++;
120                var starttime:Date = new Date();
121                var amplitude:Number;
122                var i:int;
123                var sLen:int = MSequencer.BUFFER_SIZE;
124                for(i = 0; i < sLen; i++) {
125                    m_buffer[i] = m_buffer[i+sLen] = 0.0;
126                }
127                var signal:MSignal = m_signalArr[m_signalPtr];
128                var nt:int = m_trackArr.length;
129                if (nt > 0) {
130                    var track:MTrack = m_trackArr[MTrack.TEMPO_TRACK];
131                    track.onSampleData(m_buffer, signal);
132                    for(i = MTrack.FIRST_TRACK; i < nt; i++) {
133                        track = m_trackArr[i];
134                        track.onSampleData(m_buffer);
135                    }
136                }
137                var mvol:Number = m_volume * (0.25 / 127.0);
138                for(i = 0; i < sLen; i++) {
139                    e.data.writeFloat(m_buffer[i]      * mvol);
140                    e.data.writeFloat(m_buffer[i+sLen] * mvol);
141                }
142
143                m_signalArr[(m_signalPtr + m_signalArr.length-1) % m_signalArr.length].start();
144                if (m_status < STATUS_PLAY) {
145                    m_status++;
146                }
147                m_signalPtr = (++m_signalPtr) % m_signalArr.length;
148
149                // end of sequence
150                if (m_status == STATUS_PLAY) {
151                    var n:int = 0;
152                    for (i = 0; i < m_trackArr.length; i++) {
153                        if (m_trackArr[i].isEnd()) n++;
154                    }
155                    if (n >= m_trackArr.length) {
156                        m_status = STATUS_LAST1;
157                    }
158                }
159
160                var endtime:Date = new Date();
161                m_wt += endtime.getTime() - starttime.getTime();
162                if (!((++m_wc) & 7)) { trace(m_wt); m_wt = 0; }
163            }
164            catch (e:Error) {
165                dispatchEvent(new MMLEvent(MMLEvent.COMPLETE));
166            }
167        }
168
169        public function createPipes(num:int):void {
170            MChannel.createPipes(num);
171        }
172    }
173}
Note: See TracBrowser for help on using the browser.