root/lang/actionscript/flmml/trunk/src/com/txt_nifty/sketch/flmml/MTrack.as @ 14830

Revision 14830, 14.4 kB (checked in by tekisuke, 5 years ago)

lang/actionscript/flmml/: フィルタコマンド実装。

MChannel.as    フィルタ実装。
MEvent.as 終了イベントを追加。
MLPFilter.as MFilterに名前変更。
MML.as         フィルタと終了イベントを追加。
MOscillator.as  高速化。
MSequencer.as 終了処理を追加。
MStatus.as 終了処理を追加。
MTrack.as 終了処理を追加。
MFilter.as LPFとHPFを2種類ずつ追加。

Line 
1package com.txt_nifty.sketch.flmml {
2    import de.popforge.audio.output.*;
3
4    public class MTrack {
5        public static const TEMPO_TRACK:int = 0;
6        public static const FIRST_TRACK:int = 1;
7        private var m_bpm:Number;         // beat per minute
8        private var m_spt:Number;         // samples per tick
9        private var m_ch:MChannel;        // channel (instrument)
10        private var m_needle:Number       // delta time
11        private var m_volume:int;         // default volume    (max:127)
12        private var m_gate:Number;        // default gate time (max:1.0)
13        private var m_events:Array;       //
14        private var m_pointer:int;        // current event no.
15        private var m_delta:int;
16        private var m_isEnd:int;
17        private var m_globalTick:uint;
18        private var m_signalCnt:int;
19        private var m_lfoWidth:Number;
20        public  var m_signalInterval:int;
21
22        public function MTrack() {
23            m_isEnd              = 0;
24            m_ch                 = new MChannel();
25            m_needle             = 0.0;
26            playTempo(120);
27            m_volume             = 100;
28            m_gate               = 15/16;
29            m_events             = new Array();
30            m_pointer = 0;
31            m_delta = 0;
32            m_globalTick = 0;
33            m_signalInterval = 96/4; // (quater note = 96ticks)
34            m_signalCnt = 0;
35            m_lfoWidth = 0.0;
36        }
37
38        public function getNumEvents():int {
39            return m_events.length;
40        }
41
42        public function onAudioBufferComplete(samples:Array, signal:MSignal = null):void {
43            var startCnt:int = m_signalCnt;
44            if (signal != null) signal.reset();
45            var sLen:int = samples.length;
46            // first signal
47            if (m_globalTick == 0 && signal != null) {
48                signal.add(0, 0, 0);
49            }
50            for (var i:int = 0; i < sLen;) {
51                // exec events
52                var exec:int = 0;
53                var eLen:int = m_events.length;
54                var e:MEvent;
55                var delta:Number;
56                do {
57                    exec = 0;
58                    if (m_pointer < eLen) {
59                        e = m_events[m_pointer];
60                        delta = e.getDelta() * m_spt;
61                        if (m_needle >= delta) {
62                            //trace(m_pointer+"/global:"+(int)(m_globalTick/m_spt)+"/status:"+e.getStatus()+"/delta:"+delta+"-"+e.getDelta()+"/noteNo:"+e.getNoteNo());
63                            exec = 1;
64                            switch(e.getStatus()) {
65                            case MStatus.NOTE_ON:
66                                m_ch.noteOn(e.getNoteNo(), e.getVelocity());
67                                break;
68                            case MStatus.NOTE_OFF:
69                                m_ch.noteOff();
70                                break;
71                            case MStatus.NOTE:
72                                m_ch.setNoteNo(e.getNoteNo());
73                                break;
74                            case MStatus.VOLUME:
75                                break;
76                            case MStatus.TEMPO:
77                                playTempo(e.getTempo());
78                                break;
79                            case MStatus.FORM:
80                                m_ch.setForm(e.getForm());
81                                break;
82                            case MStatus.ENVELOPE1_AD:
83                                m_ch.setEnvelope1AD(e.getEnvelopeA(), e.getEnvelopeD());
84                                break;
85                            case MStatus.ENVELOPE1_SR:
86                                m_ch.setEnvelope1SR(e.getEnvelopeS(), e.getEnvelopeR());
87                                break;
88                            case MStatus.ENVELOPE2_AD:
89                                m_ch.setEnvelope2AD(e.getEnvelopeA(), e.getEnvelopeD());
90                                break;
91                            case MStatus.ENVELOPE2_SR:
92                                m_ch.setEnvelope2SR(e.getEnvelopeS(), e.getEnvelopeR());
93                                break;
94                            case MStatus.NOISE_FREQ:
95                                m_ch.setNoiseFreq(e.getNoiseFreq());
96                                break;
97                            case MStatus.PWM:
98                                m_ch.setPWM(e.getPWM());
99                                break;
100                            case MStatus.PAN:
101                                m_ch.setPan(e.getPan());
102                                break;
103                            case MStatus.FORMANT:
104                                m_ch.setFormant(e.getVowel());
105                                break;
106                            case MStatus.DETUNE:
107                                m_ch.setDetune(e.getDetune());
108                                break;
109                            case MStatus.LFO_DPCN:
110                                m_ch.setLFODPCN(e.getLFODepth(), e.getLFOConnect());
111                                break;
112                            case MStatus.LFO_WDFM:
113                                m_lfoWidth = e.getLFOWidth() * m_spt;
114                                m_ch.setLFOWDFM(44010.0 / m_lfoWidth, e.getLFOForm());
115                                break;
116                            case MStatus.LFO_DLTM:
117                                m_ch.setLFODLTM(e.getLFODelay() * m_spt, e.getLFOTime() * m_lfoWidth);
118                                break;
119                            case MStatus.LPF_SWTAMT:
120                                m_ch.setLpfSwtAmt(e.getLPFSwt(), e.getLPFAmt());
121                                break;
122                            case MStatus.LPF_FRQRES:
123                                m_ch.setLpfFrqRes(e.getLPFFrq(), e.getLPFRes());
124                                break;
125                            case MStatus.CLOSE:
126                                m_ch.close();
127                                break;
128                            case MStatus.EOT:
129                                m_isEnd = 1;
130                                break;
131                            case MStatus.NOP:
132                                break;
133                            default:
134                                break;
135                            }
136                            m_needle -= delta;
137                            m_pointer++;
138                        }
139                    }
140                } while(exec);
141
142                // create a short wave
143                var di:int;
144                if (m_pointer < eLen) {
145                    e = m_events[m_pointer];
146                    delta = e.getDelta() * m_spt;
147                    di = Math.ceil(delta - m_needle);
148                    if (i + di >= sLen) di = sLen - i;
149                    m_needle += di;
150                    if (signal == null) m_ch.getSamples(samples, i, di);
151                    i += di;
152                }
153                else {
154                    break;
155                }
156
157                // periodic signal
158                if (signal != null) {
159                    m_signalCnt += di;
160                    var intervalSample:int = int(m_signalInterval * m_spt);
161                    while (m_signalCnt >= intervalSample) {
162                        m_globalTick += m_signalInterval;
163                        signal.add(int((intervalSample - startCnt) * (1000.0/44100.0)), m_globalTick, 0);
164                        m_signalCnt -= intervalSample;
165                        startCnt = 0;
166                    }
167                }
168            }
169            if (signal != null) signal.terminate();
170        }
171
172        public function seek(delta:int):void {
173            m_delta += delta;
174            m_globalTick += delta;
175        }
176
177        public function recDelta(e:MEvent):void {
178            e.setDelta(m_delta);
179            m_delta = 0;
180        }
181
182        public function recNote(noteNo:int, len:int, vel:int, keyon:int = 1, keyoff:int = 1):void {
183            var e0:MEvent = new MEvent();
184            if (keyon) {
185                e0.setNoteOn(noteNo, vel);
186            }
187            else {
188                e0.setNote(noteNo);
189            }
190            recDelta(e0);
191            m_events.push(e0);
192            var e1:MEvent = new MEvent();
193            if (keyoff) {
194                var gate:int = (int)(len * m_gate);
195                seek(gate);
196                e1.setNoteOff(noteNo, vel);
197                recDelta(e1);
198                m_events.push(e1);
199                seek(len - gate);
200            }
201            else {
202                seek(len);
203            }
204        }
205
206        public function recRest(len:int):void {
207            seek(len);
208        }
209
210        public function recVolume(vol:int):void {
211            var e:MEvent = new MEvent();
212            recDelta(e);
213            e.setVolume(vol);
214            m_events.push(e);
215        }
216
217        protected function recGlobal(globalTick:uint, e:MEvent):void {
218            var n:int = m_events.length;
219            var preGlobalTick:uint = 0;
220            var tmpArr:Array = new Array();
221            for(var i:int; i < n; i++) {
222                var en:MEvent = m_events[i];
223                var nextTick:uint = preGlobalTick + en.getDelta();
224                if (nextTick >= globalTick) {
225                    en.setDelta(nextTick - globalTick);
226                    e.setDelta(globalTick - preGlobalTick);
227                    m_events.splice(i, 0, e);
228                    //trace("e(TEMPO"+e.getTempo()+") delta="+(globalTick-preGlobalTick));
229                    return;
230                }
231                preGlobalTick = nextTick;
232            }
233            e.setDelta(globalTick-preGlobalTick);
234            m_events.push(e);
235            //trace("e(TEMPO"+e.getTempo()+") delta="+(globalTick-preGlobalTick));
236        }
237
238        public function recTempo(globalTick:uint, tempo:Number):void {
239            var e:MEvent = new MEvent();
240            e.setTempo(tempo);
241            recGlobal(globalTick, e);
242        }
243
244        public function recEOT():void {
245            var e:MEvent = new MEvent();
246            recDelta(e);
247            e.setEOT();
248            m_events.push(e);
249        }
250
251        public function recGate(gate:Number):void {
252            m_gate = gate;
253        }
254
255        public function recForm(form:int):void {
256            var e:MEvent = new MEvent();
257            recDelta(e);
258            e.setForm(form);
259            m_events.push(e);
260        }
261
262        public function recEnvelope(env:int, attack:int, decay:int, sustain:int, release:int):void {
263            var e:MEvent = new MEvent();
264            recDelta(e);
265            if (env == 1) e.setEnvelope1AD(attack, decay); else e.setEnvelope2AD(attack, decay);
266            m_events.push(e);
267            e = new MEvent();
268            if (env == 1) e.setEnvelope1SR(sustain, release); else e.setEnvelope2SR(sustain, release);
269            m_events.push(e);
270        }
271
272        public function recNoiseFreq(freq:int):void {
273            var e:MEvent = new MEvent();
274            recDelta(e);
275            e.setNoiseFreq(freq);
276            m_events.push(e);
277        }
278
279        public function recPWM(pwm:int):void {
280            var e:MEvent = new MEvent();
281            recDelta(e);
282            e.setPWM(pwm);
283            m_events.push(e);
284        }
285
286        public function recPan(pan:int):void {
287            var e:MEvent = new MEvent();
288            recDelta(e);
289            e.setPan(pan);
290            m_events.push(e);
291        }
292
293        public function recFormant(vowel:int):void {
294            var e:MEvent = new MEvent();
295            recDelta(e);
296            e.setFormant(vowel);
297            m_events.push(e);
298        }
299
300        public function recDetune(d:int):void {
301            var e:MEvent = new MEvent();
302            recDelta(e);
303            e.setDetune(d);
304            m_events.push(e);
305        }
306
307        public function recLFO(depth:int, width:int, form:int, delay:int, time:int):void {
308            var e:MEvent = new MEvent();
309            recDelta(e);
310            e.setLFODPCN(depth, 0);
311            m_events.push(e);
312            e = new MEvent();
313            e.setLFOWDFM(width, form);
314            m_events.push(e);
315            e = new MEvent();
316            e.setLFODLTM(delay, time);
317            m_events.push(e);
318        }
319
320        public function recLPF(swt:int, amt:int, frq:int, res:int):void {
321            var e:MEvent = new MEvent();
322            e.setLPFSWTAMT(swt, amt);
323            m_events.push(e);
324            e = new MEvent();
325            e.setLPFFRQRES(frq, res);
326            m_events.push(e);
327        }
328
329        public function recClose():void {
330            var e:MEvent = new MEvent();
331            e.setClose();
332            m_events.push(e);
333        }
334
335        public function isEnd():int {
336            return m_isEnd;
337        }
338
339        public function getRecGlobalTick():uint {
340            return m_globalTick;
341        }
342
343        public function seekTop():void {
344            m_globalTick = 0;
345        }
346
347        public function conduct(trackArr:Array):void {
348            var ni:int = m_events.length;
349            var nj:int = trackArr.length;
350            var globalTick:uint = 0;
351            var i:int, j:int;
352            var e:MEvent;
353            for(i; i < ni; i++) {
354                e = m_events[i];
355                globalTick += e.getDelta();
356                switch(e.getStatus()) {
357                case MStatus.TEMPO:
358                    for (j = FIRST_TRACK; j < nj; j++) {
359                        trackArr[j].recTempo(globalTick, e.getTempo());
360                    }
361                    break;
362                default:
363                    break;
364                }
365            }
366            var maxGlobalTick:int = 0;
367            for (j = FIRST_TRACK; j < nj; j++) {
368                if (maxGlobalTick < trackArr[j].getRecGlobalTick()) maxGlobalTick = trackArr[j].getRecGlobalTick();
369            }
370            e = new MEvent();
371            e.setEOT();
372            recGlobal(maxGlobalTick, e);
373        }
374
375        private function playTempo(bpm:Number):void {
376            m_bpm = bpm;
377            var tps:Number = m_bpm * 96.0 / 60.0; // ticks per second (quater note = 96ticks)
378            m_spt = 44100.0 / tps;              // samples per tick
379            //trace("spt:"+m_spt)
380        }
381    }
382}
Note: See TracBrowser for help on using the browser.