root/lang/actionscript/flmml/trunk/src/com/txt_nifty/sketch/flmml/MML.as @ 34284

Revision 34284, 32.1 kB (checked in by arche, 4 years ago)

休符のみのトラックの次トラックがずれる現象と&のついたノートで終わるトラックの次トラックの先頭ノートが無視される現象の修正

Line 
1package com.txt_nifty.sketch.flmml {
2    import flash.events.EventDispatcher;
3    import flash.utils.*;
4   
5    import mx.utils.StringUtil;
6
7    public class MML extends EventDispatcher {
8        protected var m_sequencer:MSequencer;
9        protected var m_tracks:Array;
10        protected var m_string:String;
11        protected var m_trackNo:int;
12        protected var m_octave:int;
13        protected var m_relativeDir:Boolean; //
14        protected var m_velocity:int;        // default velocity
15        protected var m_velDetail:Boolean;
16        protected var m_length:int;          // default length
17        protected var m_tempo:int;
18        protected var m_letter:int;
19        protected var m_keyoff:int;
20        protected var m_gate:int;
21        protected var m_maxGate:int;
22        protected var m_form:int;
23        protected var m_noteShift:int;
24        protected var m_warning:String;
25        protected var m_maxPipe:int;
26        protected static var MAX_PIPE:int = 3;
27
28        public function MML() {
29            m_sequencer = new MSequencer();
30            var self:MML = this;
31            m_sequencer.addEventListener(MMLEvent.COMPLETE, function(e:MMLEvent):void {
32                    m_sequencer.stop();
33                    self.dispatchEvent(new MMLEvent(MMLEvent.COMPLETE));
34                });
35            m_sequencer.addEventListener(MMLEvent.BUFFERING, function(e:MMLEvent):void {
36                    self.dispatchEvent(new MMLEvent(MMLEvent.BUFFERING, false, false, 0, 0, e.progress));
37                });
38        }
39
40        public function set onSignal(func:Function):void {
41            // ex) function func(globalTick:uint, event:int):void {}
42            m_sequencer.onSignal = func;
43        }
44
45        public function setSignalInterval(interval:int):void {
46            m_sequencer.setSignalInterval(interval);
47        }
48
49        public function getWarnings():String {
50            return m_warning;
51        }
52
53        protected function warning(warnId:int, str:String):void {
54            m_warning += MWarning.getString(warnId, str) +"\n";
55        }
56
57        protected function len2tick(len:int):int {
58            if (len == 0) return m_length;
59            return 384/len;
60        }
61
62        protected function note(noteNo:int):void {
63            //trace("note"+noteNo);
64            noteNo += m_noteShift + getKeySig();
65            var len:int;
66            len = getUInt(0);
67            var tick:int = len2tick(len);
68            tick = getDot(tick);
69            var keyon:int = (m_keyoff == 0) ? 0 : 1;
70            m_keyoff = 1;
71            if (getChar() == '&') { // tie
72                next();
73                m_keyoff = 0;
74            }
75            m_tracks[m_trackNo].recNote(noteNo + m_octave*12, tick, m_velocity, keyon, m_keyoff);
76        }
77
78        protected function rest():void {
79            //trace("rest");
80            var len:int;
81            len = getUInt(0);
82            var tick:int = len2tick(len);
83            tick = getDot(tick);
84            m_tracks[m_trackNo].recRest(tick);
85        }
86
87        protected function atmark():void {
88            var c:String = getChar();
89            var o:int = 1, a:int = 0, d:int = 64, s:int = 32, r:int = 0;
90            switch(c) {
91            case 'v': // Volume
92                m_velDetail = true;
93                next();
94                m_velocity = getUInt(m_velocity);
95                if (m_velocity > 127) m_velocity = 127;
96                break;
97            case 'x': // Expression
98                next();
99                o = getUInt(127);
100                if (o > 127) o = 127;
101                m_tracks[m_trackNo].recExpression(o);
102                break;
103            case 'e': // Envelope
104                next();
105                o = getUInt(o);
106                if (getChar() == ',') next();
107                a = getUInt(a);
108                if (getChar() == ',') next();
109                d = getUInt(d);
110                if (getChar() == ',') next();
111                s = getUInt(s);
112                if (getChar() == ',') next();
113                r = getUInt(r);
114                //trace("A"+a+",D"+d+",S"+s+",R"+r);
115                m_tracks[m_trackNo].recEnvelope(o, a, d, s, r);
116                break;
117            case 'n': // Noise frequency
118                next();
119                o = getUInt(0);
120                if (o < 0 || o > 127) o = 0;
121                m_tracks[m_trackNo].recNoiseFreq(o);
122                break;
123            case 'w': // pulse Width modulation
124                next();
125                o = getUInt(50);
126                if (o < 1) o = 1;
127                if (o > 99) o = 99;
128                m_tracks[m_trackNo].recPWM(o);
129                break;
130            case 'p': // Pan
131                next();
132                o = getUInt(64);
133                if (o < 1) o = 1;
134                if (o > 127) o = 127;
135                m_tracks[m_trackNo].recPan(o);
136                break;
137            case '\'': // formant filter
138                next();
139                o = m_string.indexOf('\'', m_letter);
140                if (o >= 0) {
141                    var vstr:String = m_string.substring(m_letter, o);
142                    var vowel:int = 0;
143                    switch(vstr) {
144                    case 'a': vowel = MFormant.VOWEL_A; break;
145                    case 'e': vowel = MFormant.VOWEL_E; break;
146                    case 'i': vowel = MFormant.VOWEL_I; break;
147                    case 'o': vowel = MFormant.VOWEL_O; break;
148                    case 'u': vowel = MFormant.VOWEL_U; break;
149                    default: vowel = -1; break;
150                    }
151                    m_tracks[m_trackNo].recFormant(vowel);
152                    m_letter = o + 1;
153                }
154                break;
155            case 'd': // Detune
156                next();
157                o = getSInt(0);
158                m_tracks[m_trackNo].recDetune(o);
159                break;
160            case 'l': // Low frequency oscillator (LFO)
161                {
162                    var dp:int = 0, wd:int = 0, fm:int = 1, sf:int = 0, rv:int = 1, dl:int = 0, tm:int = 0, cn:int = 0;
163                    next();
164                    dp = getUInt(dp);
165                    if (getChar() == ',') next();
166                    wd = getUInt(wd);
167                    if (getChar() == ',') {
168                        next();
169                        if (getChar() == '-') { rv = -1; next(); }
170                        fm = (getUInt(fm) + 1) * rv;
171                    if (getChar() == '-') {
172                        next();
173                        sf = getUInt(0);
174                    }
175                        if (getChar() == ',') {
176                            next();
177                            dl = getUInt(dl);
178                            if (getChar() == ',') {
179                                next();
180                                tm = getUInt(tm);
181                            }
182                        }
183                    }
184                    //trace("DePth"+dp+",WiDth"+wd+",ForM"+fm+",DeLay"+dl+",TiMe"+tm);
185                    m_tracks[m_trackNo].recLFO(dp, wd, fm, sf, dl, tm);
186                }
187                break;
188            case 'f': // Filter
189                {
190                    var swt:int = 0, amt:int = 0, frq:int = 0, res:int = 0;
191                    next();
192                    swt = getSInt(swt);
193                    if (getChar() == ',') {
194                        next();
195                        amt = getSInt(amt);
196                        if (getChar() == ',') {
197                            next();
198                            frq = getUInt(frq);
199                            if (getChar() == ',') {
200                                next();
201                                res = getUInt(res);
202                            }
203                        }
204                    }
205                    m_tracks[m_trackNo].recLPF(swt, amt, frq, res);
206                }
207                break;
208            case 'q': // gate time 2
209                next();
210                m_tracks[m_trackNo].recGate2(getUInt(2) * 2); // '*2' according to TSSCP
211                break;
212                case 'i': // Input
213                {
214                    var sens:int = 0;
215                    next();
216                    sens = getUInt(sens);
217                    if (getChar() == ',') {
218                        next();
219                        a = getUInt(a);
220                        if (a > m_maxPipe) a = m_maxPipe;
221                    }
222                    m_tracks[m_trackNo].recInput(sens, a);
223                }
224                // @i[n],[m]   m:pipe no
225                // if (n == 0) off
226                // else sensitivity = n (max:8)
227                break;
228            case 'o': // Output
229                {
230                    var mode:int = 0;
231                    next();
232                    mode = getUInt(mode);
233                    if (getChar() == ',') {
234                        next();
235                        a = getUInt(a);
236                        if (a > m_maxPipe) {
237                            m_maxPipe = a;
238                            if (m_maxPipe >= MAX_PIPE) m_maxPipe = a = MAX_PIPE;
239                        }
240                    }
241                    m_tracks[m_trackNo].recOutput(mode, a);
242                }
243                // @o[n],[m]   m:pipe no
244                // if (n == 0) off
245                // if (n == 1) overwrite
246                // if (n == 2) add
247                break;
248            default:
249                m_form = getUInt(m_form);
250                a = 0;
251                if (getChar() == '-') {
252                    next();
253                    a = getUInt(0);
254                }
255                m_tracks[m_trackNo].recForm(m_form, a);
256                break;
257            }
258        }
259
260        protected function firstLetter():void {
261            var c:String = getCharNext();
262            var c0:String;
263            var i:int;
264            switch(c) {
265            case "c": note(0);  break;
266            case "d": note(2);  break;
267            case "e": note(4);  break;
268            case "f": note(5);  break;
269            case "g": note(7);  break;
270            case "a": note(9);  break;
271            case "b": note(11); break;
272            case "r": rest(); break;
273            case "o": // Octave
274                m_octave = getUInt(m_octave);
275                if (m_octave < -2) m_octave = -2;
276                if (m_octave >  8) m_octave =  8;
277                break;
278            case "v": // Volume
279                m_velDetail = false;
280                m_velocity = getUInt((m_velocity-7)/8) * 8 + 7;
281                if (m_velocity < 0)   m_velocity = 0;
282                if (m_velocity > 127) m_velocity = 127;
283                break;
284            case "(": // vol up
285                m_velocity += (m_velDetail) ? 1 : 8;
286                if (m_velocity > 127) m_velocity = 127;
287                break;
288            case ")": // vol down
289                m_velocity -= (m_velDetail) ? 1 : 8;
290                if (m_velocity < 0) m_velocity = 0;
291                break;
292            case "l": // Length
293                m_length = len2tick(getUInt(0));
294                m_length = getDot(m_length);
295                break;
296            case "t": // Tempo
297                m_tempo = getUInt(m_tempo);
298                if (m_tempo == 0) m_tempo = 1;
299                m_tracks[MTrack.TEMPO_TRACK].recTempo(m_tracks[m_trackNo].getRecGlobalTick(), m_tempo);
300                break;
301            case "q": // gate time (rate)
302                m_gate = getUInt(m_gate);
303                m_tracks[m_trackNo].recGate(m_gate / m_maxGate);
304                break;
305            case "<" : // octave shift
306                if (m_relativeDir) m_octave++; else m_octave--;
307                break;
308            case ">": // octave shift
309                if (m_relativeDir) m_octave--; else m_octave++;
310                break;
311            case ";": // end of track
312                m_keyoff = 1;
313                if (m_tracks[m_trackNo].getNumEvents() > 0) {
314                        m_trackNo++;
315                }
316                m_tracks[m_trackNo] = createTrack();
317                break;
318            case "@":
319                atmark();
320                break;
321            case "x":
322                m_tracks[m_trackNo].recVolMode(getUInt(1));
323                break;
324            case "n":
325                c0 = getChar();
326                if (c0 == "s") { // Note Shift
327                    next();
328                    m_noteShift = getSInt(m_noteShift);
329                }
330                else
331                    warning(MWarning.UNKNOWN_COMMAND, c + c0);
332                break;
333            default:
334                {
335                    var cc:int = c.charCodeAt(0);
336                    if (cc < 128)
337                        warning(MWarning.UNKNOWN_COMMAND, c);
338                }
339                break;
340            }
341        }
342
343        protected function getCharNext():String {
344            return (m_letter < m_string.length) ? m_string.charAt(m_letter++) : '';
345        }
346
347        protected function getChar():String {
348            return (m_letter < m_string.length) ? m_string.charAt(m_letter) : '';
349        }
350
351        protected function next(i:int = 1):void {
352            m_letter += 1;
353        }
354
355        protected function getKeySig():int {
356            var k:int = 0;
357            var f:int = 1;
358            while(f) {
359                var c:String = getChar();
360                switch(c) {
361                case "+": case "#": k++; next(); break;
362                case "-":           k--; next(); break;
363                default: f = 0; break;
364                }
365            }
366            return k;
367        }
368
369        protected function getUInt(def:int):int {
370            var ret:int = 0;
371            var l:int = m_letter;
372            var f:int = 1;
373            while(f) {
374                var c:String = getChar();
375                switch(c) {
376                case '0': ret = ret * 10 + 0; next(); break;
377                case '1': ret = ret * 10 + 1; next(); break;
378                case '2': ret = ret * 10 + 2; next(); break;
379                case '3': ret = ret * 10 + 3; next(); break;
380                case '4': ret = ret * 10 + 4; next(); break;
381                case '5': ret = ret * 10 + 5; next(); break;
382                case '6': ret = ret * 10 + 6; next(); break;
383                case '7': ret = ret * 10 + 7; next(); break;
384                case '8': ret = ret * 10 + 8; next(); break;
385                case '9': ret = ret * 10 + 9; next(); break;
386                default: f = 0; break;
387                }
388            }
389            return (m_letter == l) ? def : ret;
390        }
391
392        protected function getSInt(def:int):int {
393            var c:String = getChar();
394            var s:int = 1;
395            if      (c == '-') { s = -1; next(); }
396            else if (c == '+') next();
397            return getUInt(def) * s;
398        }
399
400        protected function getDot(tick:int):int {
401            var c:String = getChar();
402            var intick:int = tick;
403            while(c == '.') {
404                next();
405                intick /= 2;
406                tick += intick;
407                c = getChar();
408            }
409            return tick;
410        }
411
412        public function createTrack():MTrack {
413            m_octave = 4;
414            m_velocity = 100;
415            m_noteShift = 0;
416            return new MTrack();
417        }
418
419        protected function begin():void {
420            m_letter = 0;
421        }
422
423        protected function process():void {
424            begin();
425            while(m_letter < m_string.length) {
426                firstLetter();
427            }
428        }
429
430        protected function processRepeat():void {
431            m_string = m_string.toLowerCase();
432            begin();
433            var repeat:Array = new Array();
434            var origin:Array = new Array();
435            var start:Array = new Array();
436            var last:Array = new Array();
437            var nest:int = -1;
438            while(m_letter < m_string.length) {
439                var c:String = getCharNext();
440                switch(c) {
441                case '/':
442                    if (getChar() == ':') {
443                        next();
444                        origin[++nest] = m_letter - 2;
445                        repeat[nest] = getUInt(2);
446                        start[nest] = m_letter;
447                        last[nest] = -1;
448                    }
449                    else if (nest >= 0) {
450                        last[nest] = m_letter - 1;
451                        m_string = m_string.substring(0, m_letter-1) + m_string.substring(m_letter);
452                        m_letter--;
453                    }
454                    else {
455                    }
456                    break;
457                case ':':
458                    if (getChar() == '/' && nest >= 0) {
459                        next();
460                        var contents:String = m_string.substring(start[nest], m_letter - 2);
461                        var newstr:String = m_string.substring(0, origin[nest]);
462                        for (var i:int = 0; i < repeat[nest]; i++) {
463                            if (i < repeat[nest]-1 || last[nest] < 0) newstr += contents;
464                            else newstr += m_string.substring(start[nest], last[nest]);
465                        }
466                        var l:int = newstr.length;
467                        newstr += m_string.substring(m_letter);
468                        m_string = newstr;
469                        m_letter = l;
470                        nest--;
471                    }
472                    break;
473                default:
474                    break;
475                }
476            }
477            if (nest >= 0) warning(MWarning.UNCLOSED_REPEAT, "");
478        }
479
480        protected function getIndex(idArr:Array, id:String):int {
481            for(var i:int = 0; i < idArr.length; i++)
482                if (((String)(idArr[i])) == id) return i;
483            return -1;
484        }
485
486        protected function replaceMacro(macroTable:Array):Boolean {
487            for each(var macro:Object in macroTable){
488                if(m_string.substr(m_letter, macro.id.length) == macro.id){
489                    var start:int = m_letter, last:int = m_letter + macro.id.length, code:String = macro.code;
490                    m_letter += macro.id.length;
491                    var c:String = getCharNext();
492                    while(StringUtil.isWhitespace(c) || c == ' '){
493                        c = getCharNext();
494                    }
495                    var args:Array = new Array();
496                    if(c == "{"){
497                        c = getCharNext();
498                        while(c != "}" && c != ""){
499                            if(c == "$"){
500                                replaceMacro(macroTable);
501                            }
502                            c = getCharNext();
503                        }
504                        last = m_letter;
505                        args = m_string.substring(start + macro.id.length + 1, last - 1).split(",");
506                    }
507                    // 引数への置換
508                    for(var i:int = 0; i < code.length; i++){
509                        for(var j:int = 0; j < args.length; j++){
510                                if(j >= macro.args.length){
511                                break;
512                                }
513                                if(code.substr(i, macro.args[j].id.length + 1) == ("%" + macro.args[j].id)){
514                                code = code.substring(0, i) + code.substring(i).replace("%" + macro.args[j].id, args[macro.args[j].index]);
515                                i += args[macro.args[j].index].length - 1;
516                                break;
517                                }
518                        }
519                    }
520                    m_string = m_string.substring(0, start - 1) + code + m_string.substring(last);
521                    m_letter = start - 1;
522                    //trace(m_string.substring(m_letter));
523                    return true;
524                }
525            }
526            return false;
527        }
528
529        protected function processMacro():void {
530            var i:int;
531            // OCTAVE REVERSE
532            var exp:RegExp = /^#OCTAVE\s+REVERSE\s*$/m;
533            if (m_string.match(exp)) {
534                m_string = m_string.replace(exp, "");
535                m_relativeDir = false;
536            }
537            // GB WAVE (ex. "#WAV10 0,0123456789abcdeffedcba9876543210")
538            {
539                exp = /^#WAV10\s.*$/gm;
540                var matched:Array = m_string.match(exp);
541                if (matched) {
542                    for(i = 0; i < matched.length; i++) {
543                        m_string = m_string.replace(exp, "");
544                        //trace(matched[i]);
545                        var wav:Array = matched[i].split(" ");
546                        var wavs:String = "";
547                        for(var j:int = 1; j < wav.length; j++) wavs += wav[j];
548                        var arg:Array = wavs.split(",");
549                        var waveNo:int = parseInt(arg[0]);
550                        if (waveNo < 0) waveNo = 0;
551                        if (waveNo >= MOscGbWave.MAX_WAVE) waveNo = MOscGbWave.MAX_WAVE-1;
552                        //trace(waveNo+":",arg[1].toLowerCase());
553                        MOscGbWave.setWave(waveNo,
554                                           (arg[1].toLowerCase()+"00000000000000000000000000000000").substr(0, 32));
555                    }
556                }
557                        //2009.05.10 OffGao ADD START addDPCM
558            // DPCM WAVE (ex. "#WAV9 0,0123456789abcdeffedcba9876543210")
559                exp = /^#WAV9\s.*$/gm;
560                matched = m_string.match(exp);
561                if (matched) {
562                    for(i = 0; i < matched.length; i++) {
563                        m_string = m_string.replace(exp, "");
564                        //trace(matched[i]);
565                        wav = matched[i].split(" ");
566                        wavs = "";
567                        for(j = 1; j < wav.length; j++) wavs += wav[j];
568                        arg = wavs.split(",");
569                        waveNo = parseInt(arg[0]);
570                        if (waveNo < 0) waveNo = 0;
571                        if (waveNo >= MOscFcDpcm.MAX_WAVE) waveNo = MOscFcDpcm.MAX_WAVE-1;
572                        var intVol:int = parseInt(arg[1]);
573                        if (intVol < 0) intVol = 0;
574                        if (intVol > 127)intVol = 127;
575                        var loopFg:int = parseInt(arg[2]);
576                        if (loopFg < 0) loopFg = 0;
577                        if (loopFg > 1) loopFg = 1;
578                        /*
579                        var length:int = -1;
580                        if (arg.length >= 5){
581                            length = parseInt(arg[4]);
582                            if (length < 1) length = 1;
583                            if (length > 0xff) length = 0xff;
584                        }
585                        MOscFcDpcm.setWave(waveNo,intVol,loopFg,arg[3],length);
586                        */
587                        MOscFcDpcm.setWave(waveNo,intVol,loopFg,arg[3]);
588                    }
589                }
590            }
591                        //2009.05.10 OffGao ADD END addDPCM
592            // macro
593            begin();
594            var top:Boolean = true;
595            var macroTable:Array = new Array();
596            while(m_letter < m_string.length) {
597                var c:String = getCharNext();
598                switch(c) {
599                    case '$':
600                        if(top){
601                            var last:int = m_string.indexOf(";", m_letter);
602                            if(last > m_letter){
603                                var nameEnd:int = m_string.indexOf("=", m_letter);
604                                if(nameEnd > m_letter && nameEnd < last){
605                                    var start:int = m_letter;
606                                    var argspos:int = m_string.indexOf("{");
607                                    if(argspos < 0 || argspos >= nameEnd){
608                                        argspos = nameEnd;
609                                    }
610                                    var regexResult:Array = m_string.substring(start, argspos).match("[a-zA-Z_][a-zA-Z_0-9#\+\(\)]*");
611                                        if(regexResult != null){
612                                            var id:String = regexResult[0];
613                                            if(id.length > 0){
614                                                var args:Array = new Array();
615                                                if(argspos < nameEnd){
616                                                    var argstr:String = m_string.substring(argspos + 1, m_string.indexOf("}", argspos));
617                                                    args = argstr.split(",");
618                                                    for(i = 0; i < args.length; i++){
619                                                        var argid:Array = args[i].match("[a-zA-Z_][a-zA-Z_0-9#\+\(\)]*");
620                                                        args[i] = { id: (argid != null ? argid[0] : ""), index: i };
621                                                    }
622                                                    args.sort(function (a:Object, b:Object):int {
623                                                        if(a.id.length > b.id.length)  return -1;
624                                                        if(a.id.length == b.id.length) return  0;
625                                                        return 1;
626                                                    });
627                                                }
628                                                m_letter = nameEnd + 1;
629                                                c = getCharNext();
630                                                while(m_letter < last){
631                                                    if(c == "$"){
632                                                        if(!replaceMacro(macroTable)){
633                                                        if(m_string.substr(m_letter, id.length) == id){
634                                                            m_letter--;
635                                                            m_string = remove(m_string, m_letter, m_letter + id.length);
636                                                            warning(MWarning.RECURSIVE_MACRO, id);
637                                                        }
638                                                    }
639                                                        last = m_string.indexOf(";", m_letter);
640                                                    }
641                                                    c = getCharNext();
642                                                }
643                                                var pos:int = 0;
644                                                for(; pos < macroTable.length; pos++){
645                                                 if(macroTable[pos].id == id){
646                                                     macroTable.splice(pos, 1);
647                                                     pos--;
648                                                     continue;
649                                                 }
650                                                        if(macroTable[pos].id.length < id.length){
651                                                                break;
652                                                        }
653                                                }
654                                                macroTable.splice(pos, 0, { id: id, code: m_string.substring(nameEnd + 1, last), args: args });
655                                                m_string = remove(m_string, start - 1, last);
656                                                m_letter = start - 1;
657                                            }
658                                    }
659                                }else{
660                                    // macro use
661                                    replaceMacro(macroTable);
662                                    top = false;
663                                 }
664                            }else{
665                                // macro use
666                                replaceMacro(macroTable);
667                                top = false;
668                            }
669                        }else{
670                            // macro use
671                            replaceMacro(macroTable);
672                            top = false;
673                        }
674                        break;
675                    case ';':
676                        top = true;
677                        break;
678                    default:
679                        if(!StringUtil.isWhitespace(c) && c != ' '){
680                            top = false;
681                        }
682                        break;
683                }
684            }
685        }
686
687        protected function processComment(str:String):void {
688            m_string = str;
689            begin();
690            var commentStart:int = -1;
691            while(m_letter < m_string.length) {
692                var c:String = getCharNext();
693                switch(c) {
694                case '/':
695                    if (getChar() == '*') {
696                        if (commentStart < 0) commentStart = m_letter - 1;
697                        next();
698                    }
699                    break;
700                case '*':
701                    if (getChar() == '/') {
702                        if (commentStart >= 0) {
703                            m_string = remove(m_string, commentStart, m_letter);
704                            m_letter = commentStart;
705                            commentStart = -1;
706                        }
707                        else {
708                            warning(MWarning.UNOPENED_COMMENT, "");
709                        }
710                    }
711                    break;
712                default:
713                    break;
714                }
715            }
716            if (commentStart >= 0) warning(MWarning.UNCLOSED_COMMENT, "");
717        }
718
719        static public function removeWhitespace(str:String):String {
720            return str.replace(new RegExp("[  \n\r\t\f]+","g"),"");
721        }
722
723        static public function remove(str:String, start:int, end:int):String {
724            return str.substring(0, start) + str.substring(end+1);
725        }
726
727        public function play(str:String):void {
728            if (m_sequencer.isPaused()) {
729                m_sequencer.play();
730                return;
731            }
732            m_sequencer.disconnectAll();
733            m_tracks = new Array();
734            m_tracks[0] = createTrack();
735            m_tracks[1] = createTrack();
736            m_warning = new String();
737
738            m_trackNo = MTrack.FIRST_TRACK;
739            m_octave = 4;
740            m_relativeDir = true;
741            m_velocity = 100;
742            m_velDetail = true;
743            m_length = len2tick(4);
744            m_tempo  = 120;
745            m_keyoff = 1;
746            m_gate = 15;
747            m_maxGate = 16;
748            m_form = MOscillator.PULSE;
749            m_noteShift = 0;
750            m_maxPipe = 0;
751
752            processComment(str);
753            //trace(m_string+"\n\n");
754            processMacro();
755            //trace(m_string);
756            m_string = removeWhitespace(m_string);
757            processRepeat();
758            //trace(m_string);
759            process();
760
761            // omit
762            if (m_tracks[m_tracks.length-1].getNumEvents() == 0) m_tracks.pop();
763
764            // conduct
765            m_tracks[MTrack.TEMPO_TRACK].conduct(m_tracks);
766
767            // post process
768            for(var i:int = MTrack.TEMPO_TRACK; i < m_tracks.length; i++) {
769                if (i > MTrack.TEMPO_TRACK) {
770                    m_tracks[i].recRestMSec(2000);
771                    m_tracks[i].recClose();
772                }
773                m_sequencer.connect(m_tracks[i]);
774            }
775
776            // initialize modules
777            m_sequencer.createPipes(m_maxPipe+1);
778
779            // dispatch event
780            dispatchEvent(new MMLEvent(MMLEvent.COMPILE_COMPLETE, false, false, 0, 0));
781
782            // play start
783            m_sequencer.play();
784        }
785
786        public function stop():void {
787            m_sequencer.stop();
788        }
789
790        public function pause():void {
791            m_sequencer.pause();
792        }
793
794        public function resume():void {
795            m_sequencer.play();
796        }
797
798        public function setMasterVolume(vol:int):void {
799            m_sequencer.setMasterVolume(vol);
800        }
801
802        public function getGlobalTick():uint {
803            return m_sequencer.getGlobalTick();
804        }
805
806        public function isPlaying():Boolean {
807            return m_sequencer.isPlaying();
808        }
809
810        public function isPaused():Boolean {
811            return m_sequencer.isPaused();
812        }
813
814        public function getTotalMSec():uint {
815            return m_tracks[MTrack.TEMPO_TRACK].getTotalMSec();
816        }
817        public function getTotalTimeStr():String {
818            return m_tracks[MTrack.TEMPO_TRACK].getTotalTimeStr();
819        }
820        public function getNowMSec():uint {
821            return m_sequencer.getNowMSec();
822        }
823        public function getNowTimeStr():String {
824            return m_sequencer.getNowTimeStr();
825        }
826    }
827}
Note: See TracBrowser for help on using the browser.