root/as3/SiOPM/trunk/src/org/si/sion/SiONDriver.as

リビジョン 4597, 77.6 kB (コミッタ: keim, コミット時期: 10 ヶ月 前)

--

Line 
1 //----------------------------------------------------------------------------------------------------
2 // SiON driver
3 //  Copyright (c) 2008 keim All rights reserved.
4 //  Distributed under BSD-style license (see org.si.license.txt).
5 //----------------------------------------------------------------------------------------------------
6
7
8 package org.si.sion {
9     import flash.errors.*;
10     import flash.events.*;
11     import flash.media.*;
12     import flash.display.Sprite;
13     import flash.utils.getTimer;
14     import flash.utils.ByteArray;
15     import org.si.utils.SLLint;
16     import org.si.utils.SLLNumber;
17     import org.si.sion.events.*;
18     import org.si.sion.sequencer.base._sion_sequencer_internal;
19     import org.si.sion.sequencer.base.MMLSequence;
20     import org.si.sion.sequencer.base.MMLEvent;
21     import org.si.sion.sequencer.SiMMLSequencer;
22     import org.si.sion.sequencer.SiMMLTrack;
23     import org.si.sion.sequencer.SiMMLEnvelopTable;
24     import org.si.sion.sequencer.SiMMLTable;
25     import org.si.sion.sequencer.SiMMLVoice;
26     import org.si.sion.module.ISiOPMWaveInterface;
27     import org.si.sion.module.SiOPMTable;
28     import org.si.sion.module.SiOPMModule;
29     import org.si.sion.module.SiOPMChannelParam;
30     import org.si.sion.module.SiOPMWaveTable;
31     import org.si.sion.module.SiOPMWavePCMTable;
32     import org.si.sion.module.SiOPMWavePCMData;
33     import org.si.sion.module.SiOPMWaveSamplerTable;
34     import org.si.sion.module.SiOPMWaveSamplerData;
35     import org.si.sion.effector.SiEffectModule;
36     import org.si.sion.effector.SiEffectBase;
37     import org.si.sion.utils.soundloader.SoundLoader;
38     import org.si.sion.utils.SiONUtil;
39     import org.si.sion.utils.Fader;
40     import org.si.sion.namespaces._sion_internal;
41    
42    
43     // Dispatching events
44     /** @eventType org.si.sion.events.SiONEvent.QUEUE_PROGRESS */
45     [Event(name="queueProgress",   type="org.si.sion.events.SiONEvent")]
46     /** @eventType org.si.sion.events.SiONEvent.QUEUE_COMPLETE */
47     [Event(name="queueComplete",   type="org.si.sion.events.SiONEvent")]
48     /** @eventType org.si.sion.events.SiONEvent.QUEUE_CANCEL */
49     [Event(name="queueCancel",     type="org.si.sion.events.SiONEvent")]
50     /** @eventType org.si.sion.events.SiONEvent.STREAM */
51     [Event(name="stream",          type="org.si.sion.events.SiONEvent")]
52     /** @eventType org.si.sion.events.SiONEvent.STREAM_START */
53     [Event(name="streamStart",     type="org.si.sion.events.SiONEvent")]
54     /** @eventType org.si.sion.events.SiONEvent.STREAM_STOP */
55     [Event(name="streamStop",      type="org.si.sion.events.SiONEvent")]
56     /** @eventType org.si.sion.events.SiONEvent.FINISH_SEQUENCE */
57     [Event(name="finishSequence",  type="org.si.sion.events.SiONEvent")]
58     /** @eventType org.si.sion.events.SiONEvent.FADE_PROGRESS */
59     [Event(name="fadeProgress",    type="org.si.sion.events.SiONEvent")]
60     /** @eventType org.si.sion.events.SiONEvent.FADE_IN_COMPLETE */
61     [Event(name="fadeInComplete",  type="org.si.sion.events.SiONEvent")]
62     /** @eventType org.si.sion.events.SiONEvent.FADE_OUT_COMPLETE */
63     [Event(name="fadeOutComplete", type="org.si.sion.events.SiONEvent")]
64     /** @eventType org.si.sion.events.SiONTrackEvent.NOTE_ON_STREAM */
65     [Event(name="noteOnStream",    type="org.si.sion.events.SiONTrackEvent")]
66     /** @eventType org.si.sion.events.SiONTrackEvent.NOTE_OFF_STREAM */
67     [Event(name="noteOffStream",   type="org.si.sion.events.SiONTrackEvent")]
68     /** @eventType org.si.sion.events.SiONTrackEvent.NOTE_ON_FRAME */
69     [Event(name="noteOnFrame",     type="org.si.sion.events.SiONTrackEvent")]
70     /** @eventType org.si.sion.events.SiONTrackEvent.NOTE_OFF_FRAME */
71     [Event(name="noteOffFrame",    type="org.si.sion.events.SiONTrackEvent")]
72     /** @eventType org.si.sion.events.SiONTrackEvent.BEAT */
73     [Event(name="beat",            type="org.si.sion.events.SiONTrackEvent")]
74     /** @eventType org.si.sion.events.SiONTrackEvent.CHANGE_BPM */
75     [Event(name="changeBPM",       type="org.si.sion.events.SiONTrackEvent")]
76    
77    
78     /** SiONDriver class provides the driver of SiON's digital signal processor emulator. SiON's all basic operations are provided as SiONDriver's properties, methods and events. You can create only one SiONDriver instance in one SWF file, and the error appears when you try to create plural SiONDrivers.<br/>
79      * @see SiONData
80      * @see SiONVoice
81      * @see org.si.sion.events.SiONEvent
82      * @see org.si.sion.events.SiONTrackEvent
83      * @see org.si.sion.module.SiOPMModule
84      * @see org.si.sion.sequencer.SiMMLSequencer
85      * @see org.si.sion.effector.SiEffectModule
86 @example 1) The simplest sample. Create new instance and call play with MML string.<br/>
87 <listing version="3.0">
88 // create driver instance.
89 var driver:SiONDriver = new SiONDriver();
90 // call play() with mml string whenever you want to play sound.
91 driver.play("t100 l8 [ ccggaag4 ffeeddc4 | [ggffeed4]2 ]2");
92 </listing>
93      */
94     public class SiONDriver extends Sprite implements ISiOPMWaveInterface
95     {
96     // namespace
97     //----------------------------------------
98         use namespace _sion_internal;
99        
100        
101        
102        
103     // constants
104     //----------------------------------------
105         /** version number */
106         static public const VERSION:String = "0.6.4.1";
107        
108        
109         /** note-on exception mode "ignore", SiON does not consider about track ID's conflict in noteOn() method (default). */
110         static public const NEM_IGNORE:int = 0;
111         /** note-on exception mode "reject", Reject new note when the track IDs are conflicted. */
112         static public const NEM_REJECT:int = 1;
113         /** note-on exception mode "overwrite", Overwrite current note when the track IDs are conflicted. */
114         static public const NEM_OVERWRITE:int = 2;
115         /** note-on exception mode "shift", Shift the sound timing to next quantize when the track IDs are conflicted. */
116         static public const NEM_SHIFT:int = 3;
117        
118         static private const NEM_MAX:int = 4;
119        
120        
121         // event listener type
122         private const NO_LISTEN:int = 0;
123         private const LISTEN_QUEUE:int = 1;
124         private const LISTEN_PROCESS:int = 2;
125        
126         // time avaraging sample count
127         private const TIME_AVARAGING_COUNT:int = 8;
128        
129        
130        
131        
132     // valiables
133     //----------------------------------------
134         /** SiOPM digital signal processor module instance.  */
135         public var module:SiOPMModule;
136        
137         /** Effector module instance. */
138         public var effector:SiEffectModule;
139        
140         /** Sequencer module instance. */
141         public var sequencer:SiMMLSequencer;
142        
143        
144         // private:
145         //----- general
146         private var _data:SiONData;         // data to compile or process
147         private var _tempData:SiONData;     // temporary data
148         private var _mmlString:String;      // mml string of previous compiling
149         //----- sound related
150         private var _sound:Sound;                   // sound stream instance
151         private var _soundChannel:SoundChannel;     // sound channel instance
152         private var _soundTransform:SoundTransform; // sound transform
153         private var _fader:Fader;                   // sound fader
154         //----- SiOPM DSP module related
155         private var _channelCount:int;          // module output channels (1 or 2)
156         private var _sampleRate:Number;         // module output frequency ratio (44100 or 22050)
157         private var _bitRate:int;               // module output bitrate
158         private var _bufferLength:int;          // module and streaming buffer size (8192, 4096 or 2048)
159         private var _debugMode:Boolean;         // true; throw Error, false; throw ErrorEvent
160         private var _dispatchStreamEvent:Boolean; // dispatch steam event
161         private var _dispatchFadingEvent:Boolean; // dispatch fading event
162         private var _inStreaming:Boolean;         // in streaming
163         private var _preserveStop:Boolean;        // preserve stop after streaming
164         private var _suspendStreaming:Boolean;      // suspend streaming
165         private var _suspendWhileLoading:Boolean;   // suspend starting steam while loading
166         private var _loadingSoundList:Array;        // loading sound list
167         private var _isFinishSeqDispatched:Boolean; // FINISH_SEQUENCE event already dispacthed
168         //----- operation related
169         private var _autoStop:Boolean;          // auto stop when the sequence finished
170         private var _noteOnExceptionMode:int;   // track id exception mode
171         private var _isPaused:Boolean;          // flag to pause
172         private var _position:Number;           // start position [ms]
173         private var _masterVolume:Number;       // master volume
174         private var _faderVolume:Number;        // fader volume
175         //----- background sound
176         private var _backgroundSound:Sound;      // background Sound
177         private var _backgroundLevel:Number;     // background Sound mixing level
178         private var _backgroundBuffer:ByteArray; // buffer for background Sound
179         private var _backgroundLoop:Boolean;     // looping flag of background Sound
180         //----- queue
181         private var _queueInterval:int;         // interupting interval to execute queued jobs
182         private var _queueLength:int;           // queue length to execute
183         private var _jobProgress:Number;        // progression of current job
184         private var _currentJob:int;            // current job 0=no job, 1=compile, 2=render
185         private var _jobQueue:Vector.<SiONDriverJob> = null;   // compiling/rendering jobs queue
186         private var _trackEventQueue:Vector.<SiONTrackEvent>;  // SiONTrackEvents queue
187         //----- timer interruption
188         private var _timerSequence:MMLSequence;     // global sequence
189         private var _timerIntervalEvent:MMLEvent;   // MMLEvent.GLOBAL_WAIT event
190         private var _timerCallback:Function;        // callback function
191         //----- rendering
192         private var _renderBuffer:Vector.<Number>;  // rendering buffer
193         private var _renderBufferChannelCount:int;  // rendering buffer channel count
194         private var _renderBufferIndex:int;         // rendering buffer writing index
195         private var _renderBufferSizeMax:int;       // maximum value of rendering buffer size
196         //----- timers
197         private var _timeCompile:int;           // previous compiling time.
198         private var _timeRender:int;            // previous rendering time.
199         private var _timeProcess:int;           // averge processing time in 1sec.
200         private var _timeProcessTotal:int;      // total processing time in last 8 bufferings.
201         private var _timeProcessData:SLLint;    // processing time data of last 8 bufferings.
202         private var _timeProcessAveRatio:Number;// number to averaging _timeProcessTotal
203         private var _timePrevStream:int;        // previous streaming time.
204         private var _latency:Number;            // streaming latency [ms]
205         private var _prevFrameTime:int;         // previous frame time
206         private var _frameRate:int;             // frame rate
207         //----- listeners management
208         private var _eventListenerPrior:int;    // event listeners priority
209         private var _listenEvent:int;           // current lintening event
210        
211         // mutex instance
212         static private var _mutex:SiONDriver = null;     // unique instance
213        
214        
215        
216        
217     // properties
218     //----------------------------------------
219         /** Instance of unique SiONDriver. null when new SiONDriver is not created yet. */
220         static public function get mutex() : SiONDriver { return _mutex; }
221        
222        
223         // data
224         /** MML string (this property is only available during compiling). */
225         public function get mmlString() : String { return _mmlString; }
226        
227         /** Data to compile, render and process. */
228         public function get data() : SiONData { return _data; }
229        
230         /** flash.media.Sound instance to stream SiON's sound. */
231         public function get sound() : Sound { return _sound; }
232        
233         /** flash.media.SoundChannel instance of SiON's sound stream (this property is only available during streaming). */
234         public function get soundChannel() : SoundChannel { return _soundChannel; }
235
236         /** Fader to control fade-in/out. You can check activity by "fader.isActive". */
237         public function get fader() : Fader { return _fader; }
238        
239        
240         // paramteters
241         /** The number of sound tracks (this property is only available during streaming). */
242         public function get trackCount() : int { return sequencer.tracks.length; }
243        
244         /** Streaming buffer length. */
245         public function get bufferLength() : int { return _bufferLength; }
246         /** Sample rate (44100 is only available in current version). */
247         public function get sampleRate() : Number { return _sampleRate; }
248         /** bit rate, the value of 0 means the wave is represented as float value[-1 - +1]. */
249         public function get bitRate() : Number { return _bitRate; }
250        
251         /** Sound volume. */
252         public function get volume() : Number { return _masterVolume; }
253         public function set volume(v:Number) : void {
254             _masterVolume = v;
255             _soundTransform.volume = _masterVolume * _faderVolume;
256             if (_soundChannel) _soundChannel.soundTransform = _soundTransform;
257         }
258        
259         /** Sound panning. */
260         public function get pan() : Number { return _soundTransform.pan; }
261         public function set pan(p:Number) : void {
262             _soundTransform.pan = p;
263             if (_soundChannel) _soundChannel.soundTransform = _soundTransform;
264         }
265        
266        
267         // measured times
268         /** previous compiling time [ms]. */
269         public function get compileTime() : int { return _timeCompile; }
270        
271         /** previous rendering time [ms]. */
272         public function get renderTime() : int { return _timeRender; }
273        
274         /** average processing time in 1sec [ms]. */
275         public function get processTime() : int { return _timeProcess; }
276        
277         /** progression of current compiling/rendering (0=start -> 1=finish). */
278         public function get jobProgress() : Number { return _jobProgress; }
279        
280         /** progression of all queued jobs (0=start -> 1=finish). */
281         public function get jobQueueProgress() : Number {
282             if (_queueLength == 0) return 1;
283             return (_queueLength - _jobQueue.length - 1 + _jobProgress) / _queueLength;
284         }
285        
286         /** compiling/rendering jobs queue length. */
287         public function get jobQueueLength() : int { return _jobQueue.length; }
288        
289         /** streaming latency [ms]. */
290         public function get latency() : Number { return _latency; }
291        
292        
293         // flags
294         /** Is job executing ? */
295         public function get isJobExecuting() : Boolean { return (_jobProgress>0 && _jobProgress<1); }
296        
297         /** Is streaming ? */
298         public function get isPlaying() : Boolean { return (_soundChannel != null); }
299        
300         /** Is paused ? */
301         public function get isPaused() : Boolean { return _isPaused; }
302        
303        
304         // operation
305         /** Get playing position[ms] of current data, or Set initial position of playing data. @default 0 */
306         public function get position() : Number {
307             return sequencer.processedSampleCount * 1000 / _sampleRate;
308         }
309         public function set position(pos:Number) : void {
310             _position = pos;
311             if (sequencer.isReadyToProcess) {
312                 sequencer._resetAllTracks();
313                 sequencer.dummyProcess(_position * _sampleRate * 0.001);
314             }
315         }
316        
317         /** The maximum limit of sound tracks. @default 128 */
318         public function get maxTrackCount() : int { return sequencer._maxTrackCount; }
319         public function set maxTrackCount(max:int) : void { sequencer._maxTrackCount = max; }
320        
321         /** Beat par minute value of SiON's play. @default 120 */
322         public function get bpm() : Number {
323             return (sequencer.isReadyToProcess) ? sequencer.bpm : sequencer.setting.defaultBPM;
324         }
325         public function set bpm(t:Number) : void {
326             sequencer.setting.defaultBPM = t;
327             if (sequencer.isReadyToProcess) {
328                 if (!sequencer.isEnableChangeBPM) throw errorCannotChangeBPM();
329                 sequencer.bpm = t;
330             }
331         }
332        
333         /** Auto stop when the sequence finished or fade-outed. @default false */
334         public function get autoStop() : Boolean { return _autoStop; }
335         public function set autoStop(mode:Boolean) : void { _autoStop = mode; }
336        
337         /** pause while loading sound @default true */
338         public function get pauseWhileLoading() : Boolean { return _suspendWhileLoading; }
339         public function set pauseWhileLoading(b:Boolean) : void { _suspendWhileLoading = b; }
340        
341         /** Debug mode, true; throw Error / false; throw ErrorEvent when error appears inside. @default false */
342         public function get debugMode() : Boolean { return _debugMode; }
343         public function set debugMode(mode:Boolean) : void { _debugMode = mode; }
344        
345         /** Note on exception mode, this mode is refered when the noteOn() sound's track IDs are conflicted at the same moment. This value have to be SiONDriver.NEM_*. @default NEM_IGNORE.
346          *  @see #NEM_IGNORE
347          *  @see #NEM_REJECT
348          *  @see #NEM_OVERWRITE
349          *  @see #NEM_SHIFT
350          */
351         public function get noteOnExceptionMode() : int { return _noteOnExceptionMode; }
352         public function set noteOnExceptionMode(mode:int) : void { _noteOnExceptionMode = (0<mode && mode<NEM_MAX) ? mode : 0; }
353        
354        
355        
356        
357     // constructor
358     //----------------------------------------
359         /** Create driver to manage the synthesizer, sequencer and effector. Only one SiONDriver instance can be created.
360          *  @param bufferLength Buffer size of sound stream. The value of 8192, 4096 or 2048 is available.
361          *  @param channel Channel count. 1(monoral) or 2(stereo) is available.
362          *  @param sampleRate Sampling ratio of wave. 44100 is only available in current version.
363          *  @param bitRate Bit ratio of wave. 0 means float value [-1 to 1].
364          */
365         function SiONDriver(bufferLength:int=2048, channelCount:int=2, sampleRate:int=44100, bitRate:int=0)
366         {
367             // check mutex
368             if (_mutex != null) throw errorPluralDrivers();
369            
370             // check parameters
371             if (bufferLength != 2048 && bufferLength != 4096 && bufferLength != 8192) throw errorParamNotAvailable("stream buffer", bufferLength);
372             if (channelCount != 1 && channelCount != 2) throw errorParamNotAvailable("channel count", channelCount);
373             if (sampleRate != 44100) throw errorParamNotAvailable("sampling rate", sampleRate);
374            
375             // initialize tables
376             var dummy:*;
377             dummy = SiOPMTable.instance; //initialize(3580000, 1789772.5, 44100) sampleRate;
378             dummy = SiMMLTable.instance; //initialize();
379            
380             // allocation
381             _jobQueue = new Vector.<SiONDriverJob>();
382             module = new SiOPMModule();
383             effector = new SiEffectModule(module);
384             sequencer = new SiMMLSequencer(module, _callbackEventTriggerOn, _callbackEventTriggerOff, _callbackTempoChanged);
385             _sound = new Sound();
386             _soundTransform = new SoundTransform();
387             _fader = new Fader();
388             _timerSequence = new MMLSequence();
389             _loadingSoundList = [];
390
391             // initialize
392             _tempData = null;
393             _channelCount = channelCount;
394             _sampleRate = sampleRate; // sampleRate; 44100 is only in current version.
395             _bitRate = bitRate;
396             _bufferLength = bufferLength;
397             _listenEvent = NO_LISTEN;
398             _dispatchStreamEvent = false;
399             _dispatchFadingEvent = false;
400             _preserveStop = false;
401             _inStreaming = false;
402             _suspendStreaming = false;
403             _suspendWhileLoading = true;
404             _autoStop = false;
405             _noteOnExceptionMode = NEM_IGNORE;
406             _debugMode = false;
407             _isFinishSeqDispatched = false;
408             _timerCallback = null;
409             _timerSequence.initialize();
410             _timerSequence.appendNewEvent(MMLEvent.REPEAT_ALL, 0);
411             _timerSequence.appendNewEvent(MMLEvent.TIMER, 0);
412             _timerIntervalEvent = _timerSequence.appendNewEvent(MMLEvent.GLOBAL_WAIT, 0, 0);
413            
414             _backgroundSound = null;
415             _backgroundLevel = 1;
416             _backgroundBuffer = null;
417             _backgroundLoop = false;
418            
419             _position = 0;
420             _masterVolume = 1;
421             _faderVolume = 1;
422             _soundTransform.pan = 0;
423             _soundTransform.volume = _masterVolume * _faderVolume;
424            
425             _eventListenerPrior = 1;
426             _trackEventQueue = new Vector.<SiONTrackEvent>();
427            
428             _queueInterval = 500;
429             _jobProgress = 0;
430             _currentJob = 0;
431             _queueLength = 0;
432            
433             _timeCompile = 0;
434             _timeProcessTotal = 0;
435             _timeProcessData = SLLint.allocRing(TIME_AVARAGING_COUNT);
436             _timeProcessAveRatio = _sampleRate / (_bufferLength * TIME_AVARAGING_COUNT);
437             _timePrevStream = 0;
438             _latency = 0;
439             _prevFrameTime = 0;
440             _frameRate = 1;
441            
442             _mmlString    = null;
443             _data         = null;
444             _soundChannel = null;
445            
446             // register sound streaming function
447             _sound.addEventListener("sampleData", _streaming);
448            
449             // set mutex
450             _mutex = this;
451         }
452        
453        
454        
455        
456     // interfaces for data preparation
457     //----------------------------------------
458         /** Compile MML string to SiONData.
459          *  @param mml MML string to compile.
460          *  @param data SiONData to compile. The SiONDriver creates new SiONData instance when this argument is null.
461          *  @return Compiled data.
462          */
463         public function compile(mml:String, data:SiONData=null) : SiONData
464         {
465             try {
466                 // stop sound
467                 stop();
468                
469                 // compile immediately
470                 var t:int = getTimer();
471                 _prepareCompile(mml, data);
472                 _jobProgress = sequencer.compile(0);
473                 _timeCompile = getTimer() - t;
474                 _mmlString = null;
475             } catch(e:Error) {
476                 // error
477                 if (_debugMode) throw e;
478                 else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
479             }
480            
481             return _data;
482         }
483        
484        
485         /** Push queue job to compile MML string. Start compiling after calling startQueue.<br/>
486          *  @param mml MML string to compile.
487          *  @param data SiONData to compile.
488          *  @return Queue length.
489          *  @see #startQueue()
490          */
491         public function compileQueue(mml:String, data:SiONData) : int
492         {
493             if (mml == null || data == null) return _jobQueue.length;
494             return _jobQueue.push(new SiONDriverJob(mml, null, data, 2, false));
495         }
496        
497        
498        
499        
500     // interfaces for sound rendering
501     //----------------------------------------
502         /** Render wave data from MML string or SiONData. This method may take long time, please consider the using renderQueue() instead.
503          *  @param data SiONData or mml String to play.
504          *  @param renderBuffer Rendering target. null to create new buffer. The length of this argument limits the rendering length (except for 0).
505          *  @param renderBufferChannelCount Channel count of renderBuffer. 2 for stereo and 1 for monoral.
506          *  @param resetEffector reset all effectors before play data.
507          *  @return rendered wave data as Vector.&lt;Number&gt;.
508          */
509         public function render(data:*, renderBuffer:Vector.<Number>=null, renderBufferChannelCount:int=2, resetEffector:Boolean=true) : Vector.<Number>
510         {
511             try {
512                 // stop sound
513                 stop();
514                
515                 // rendering immediately
516                 var t:int = getTimer();
517                 _prepareRender(data, renderBuffer, renderBufferChannelCount, resetEffector);
518                 while(true) { if (_rendering()) break; }
519                 _timeRender = getTimer() - t;
520             } catch (e:Error) {
521                 // error
522                 _removeAllEventListners();
523                 if (_debugMode) throw e;
524                 else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
525             }
526            
527             return _renderBuffer;
528         }
529        
530        
531         /** Push queue job to render sound. Start rendering after calling startQueue.<br/>
532          *  @param data SiONData or mml String to render.
533          *  @param renderBuffer Rendering target. The length of renderBuffer limits rendering length except for 0.
534          *  @param renderBufferChannelCount Channel count of renderBuffer. 2 for stereo and 1 for monoral.
535          *  @return Queue length.
536          *  @see #startQueue()
537          */
538         public function renderQueue(data:*, renderBuffer:Vector.<Number>, renderBufferChannelCount:int=2, resetEffector:Boolean=false) : int
539         {
540             if (data == null || renderBuffer == null) return _jobQueue.length;
541            
542             if (data is String) {
543                 var compiled:SiONData = new SiONData();
544                 _jobQueue.push(new SiONDriverJob(data as String, null, compiled, 2, false));
545                 return _jobQueue.push(new SiONDriverJob(null, renderBuffer, compiled, renderBufferChannelCount, resetEffector));
546             } else
547             if (data is SiONData) {
548                 return _jobQueue.push(new SiONDriverJob(null, renderBuffer, data as SiONData, renderBufferChannelCount, resetEffector));
549             }
550            
551             var e:Error = errorDataIncorrect();
552             if (_debugMode) throw e;
553             else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
554             return _jobQueue.length;
555         }
556        
557        
558        
559        
560     // interfaces for jobs queue
561     //----------------------------------------
562         /** Execute all elements queued by compileQueue() and renderQueue().
563          *  After calling this function, the SiONEvent.QUEUE_PROGRESS, SiONEvent.QUEUE_COMPLETE and ErrorEvent.ERROR events will be dispatched.<br/>
564          *  The SiONEvent.QUEUE_PROGRESS is dispatched when it's executing queued job.<br/>
565          *  The SiONEvent.QUEUE_COMPLETE is dispatched when finish all queued jobs.<br/>
566          *  The ErrorEvent.ERROR is dispatched when some error appears during the compile.<br/>
567          *  @param interval Interupting interval
568          *  @return Queue length.
569          *  @see #compileQueue()
570          *  @see #renderQueue()
571          */
572         public function startQueue(interval:int=500) : int
573         {
574             try {
575                 stop();
576                 _queueLength = _jobQueue.length;
577                 if (_jobQueue.length > 0) {
578                     _queueInterval = interval;
579                     _executeNextJob();
580                     _queue_addAllEventListners();
581                 }
582             } catch (e:Error) {
583                 // error
584                 _removeAllEventListners();
585                 _cancelAllJobs();
586                 if (_debugMode) throw e;
587                 else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
588             }
589             return _queueLength;
590         }
591                
592        
593         /** Listen loading status of flash.media.Sound instance.
594          *  When SiONDriver.pauseWhileLoading is true, SiONDriver starts streaming after all Sound instances passed by this function are loaded.
595          *  @param sound Sound or SoundLoader instance to listern
596          *  @param prior listening priority
597          *  @see #pauseWhileLoading()
598          *  @see #clearLoadingSoundList()
599          */
600         public function listenSoundLoadingStatus(sound:*, prior:int=-99999) : void
601         {
602             if (!sound is Sound && !sound is SoundLoader) throw errorCannotListenLoading();
603             if (_loadingSoundList.indexOf(sound) != -1) return;
604             if (sound is Sound) {
605                 if (sound.bytesTotal == 0 || sound.bytesLoaded != sound.bytesTotal) {
606                     _loadingSoundList.push(sound);
607                     sound.addEventListener(Event.COMPLETE,        _onSoundEvent, false, prior);
608                     sound.addEventListener(IOErrorEvent.IO_ERROR, _onSoundEvent, false, prior);
609                 }
610             } else { // sound is SoundLoader
611                 if (sound.loadingFileCount > 0) {
612                     _loadingSoundList.push(sound);
613                     sound.addEventListener(Event.COMPLETE,   _onSoundEvent, false, prior);
614                     sound.addEventListener(ErrorEvent.ERROR, _onSoundEvent, false, prior);
615                 }
616             }
617         }
618        
619        
620         /** Clear all listening sound list registerd by SiONDriver.listenLoadingStatus().
621          */
622         public function clearSoundLoadingList() : void
623         {
624             _loadingSoundList.length = 0;
625         }
626        
627        
628         /** Set Sound Reference Table refered from #SAMPLER and #PCMWAVE commands.
629          */
630         public function setSoudReferenceTable(soundReferenceTable:* = null) : void
631         {
632             SiOPMTable.instance.soundReference = soundReferenceTable || {};
633         }
634        
635        
636        
637     // interfaces for sound streaming
638     //----------------------------------------
639         /** Play SiONData or MML string.
640          *  @param data SiONData or mml String to play. You can pass null when resume after pause or streaming without any data.
641          *  @param resetEffector reset all effectors before play data.
642          *  @return SoundChannel instance to play data. This instance is same as soundChannel property.
643          *  @see #soundChannel
644          */
645         public function play(data:*=null, resetEffector:Boolean=true) : SoundChannel
646         {
647             try {
648                 if (_isPaused) {
649                     _isPaused = false;
650                 } else {
651                     // stop sound
652                     stop();
653                    
654                     // preparation
655                     _prepareProcess(data, resetEffector);
656
657                     // initialize
658                     _timeProcessTotal = 0;
659                     for (var i:int=0; i<TIME_AVARAGING_COUNT; i++) {
660                         _timeProcessData.i = 0;
661                         _timeProcessData = _timeProcessData.next;
662                     }
663                     _isPaused = false;
664                     _isFinishSeqDispatched = (data == null);
665                    
666                     // start streaming
667                     _suspendStreaming = true;
668                     _soundChannel = _sound.play();
669                     _soundChannel.soundTransform = _soundTransform;
670                     _process_addAllEventListners();
671                 }
672             } catch(e:Error) {
673                 // error
674                 if (_debugMode) throw e;
675                 else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
676             }
677            
678             return _soundChannel;
679         }
680        
681        
682         /** Stop sound. */
683         public function stop() : void
684         {
685             if (_soundChannel) {
686                 if (_inStreaming) {
687                     _preserveStop = true;
688                 } else {
689                     _removeAllEventListners();
690                     _preserveStop = false;
691                     _soundChannel.stop();
692                     _soundChannel = null;
693                     _latency = 0;
694                     _fader.stop();
695                     _faderVolume = 1;
696                     _isPaused = false;
697                     _soundTransform.volume = _masterVolume;
698                     sequencer._sion_internal::_stopSequence();
699                    
700                     // dispatch streaming stop event
701                     dispatchEvent(new SiONEvent(SiONEvent.STREAM_STOP, this));
702                 }
703             }
704         }
705        
706        
707         /** Reset signal processor. The effector and sequencer will not reset. If you want to all of effectors and sequencers, call SiONDriver.stop(). */
708         public function reset() : void
709         {
710             sequencer._resetAllTracks();
711         }
712        
713        
714         /** Pause sound. You can resume it by play() without any arguments. */
715         public function pause() : void
716         {
717             _isPaused = true;
718         }
719        
720        
721         /** Play Sound as a background. This function should be called before play().
722          *  @param sound Sound instance to play background.
723          *  @param mixLevel Mixing level (0-1).
724          */
725         public function setBackgroundSound(sound:Sound, mixLevel:Number=1, isLooping:Boolean=false) : void
726         {
727             _backgroundSound = sound;
728             _backgroundLevel = mixLevel;
729             _backgroundLoop  = isLooping;
730             if (_backgroundBuffer == null) {
731                 _backgroundBuffer = new ByteArray();
732                 _backgroundBuffer.length = _bufferLength * 8;
733             }
734         }
735        
736        
737         /** Stop background sound. */
738         public function stopBackgroundSound() : void
739         {
740             _backgroundSound = null;
741         }
742        
743        
744         /** Fade in.
745          *  @param term Fading time [second].
746          */
747         public function fadeIn(term:Number) : void
748         {
749             _fader.setFade(_fadeVolume, 0, 1, term * _sampleRate / _bufferLength);
750             _dispatchFadingEvent = (hasEventListener(SiONEvent.FADE_PROGRESS));
751         }
752        
753        
754         /** Fade out.
755          *  @param term Fading time [second].
756          */
757         public function fadeOut(term:Number) : void
758         {
759             _fader.setFade(_fadeVolume, 1, 0, term * _sampleRate / _bufferLength);
760             _dispatchFadingEvent = (hasEventListener(SiONEvent.FADE_PROGRESS));
761         }
762        
763        
764         /** Set timer interruption.
765          *  @param length16th Interupting interval in 16th beat.
766          *  @param callback Callback function. the Type is function():void.
767          */
768         public function setTimerInterruption(length16th:Number=1, callback:Function=null) : void
769         {
770             _timerIntervalEvent.length = length16th * sequencer.setting.resolution * 0.0625;
771             _timerCallback = (length16th > 0) ? callback : null;
772         }
773        
774        
775         /** Set callback interval of SiONTrackEvent.BEAT.
776          *  @param length16th Interval in 16th beat. 2^n is only available(1,2,4,8,16....).
777          */
778         public function setBeatCallbackInterval(length16th:Number=1) : void
779         {
780             var filter:int = 1;
781             while (length16th > 1.5) {
782                 filter <<= 1;
783                 length16th *= 0.5
784             }
785             sequencer._setBeatCallbackFilter(filter - 1);
786         }
787        
788        
789         /** Force dispatch stream event. The SiONEvent.STREAM is dispatched only when the event listener is set BEFORE calling play(). You can let SiONDriver to dispatch SiONEvent.STREAM event by this function.
790          *  @param dispatch Set true to force dispatching. Or set false to not dispatching if there are no listeners.
791          */
792         _sion_internal function forceDispatchStreamEvent(dispatch:Boolean=true) : void
793         {
794             _dispatchStreamEvent = dispatch || (hasEventListener(SiONEvent.STREAM));
795         }
796        
797        
798        
799     // Interface for public data registration
800     //----------------------------------------
801         /** Set wave table data refered by %4.
802          *  @param index wave table number.
803          *  @param table wave shape vector ranges in -1 to 1.
804          */
805         public function setWaveTable(index:int, table:Vector.<Number>) : SiOPMWaveTable
806         {
807             var len:int, bits:int=-1;
808             for (len=table.length; len>0; len>>=1) bits++;
809             if (bits<2) return null;
810             var waveTable:Vector.<int> = SiONUtil.logTransVector(table, 1, null);
811             waveTable.length = 1<<bits;
812             return SiOPMTable._instance.registerWaveTable(index, waveTable);
813         }
814        
815        
816         /** Set PCM wave data rederd by %7.
817          *  @param index PCM data number.
818          *  @param data wave data, Sound, Vector.&lt;Number&gt; or Vector.&lt;int&gt; is available. The Sound instance is extracted internally, the maximum length to extract is SiOPMWavePCMData.maxSampleLengthFromSound[samples].
819          *  @param samplingNote Sampling wave's original note number, this allows decimal number
820          *  @param keyRangeFrom Assigning key range starts from (not implemented in current version)
821          *  @param keyRangeTo Assigning key range ends at (not implemented in current version)
822          *  @param srcChannelCount channel count of source data, 1 for monoral, 2 for stereo.
823          *  @param channelCount channel count of this data, 1 for monoral, 2 for stereo, 0 sets same with srcChannelCount.
824          *  @see #org.si.sion.module.SiOPMWavePCMData.maxSampleLengthFromSound
825          *  @see #render()
826          */
827         public function setPCMWave(index:int, data:*, samplingNote:Number=68, keyRangeFrom:int=0, keyRangeTo:int=127, srcChannelCount:int=2, channelCount:int=0) : SiOPMWavePCMData
828         {
829             var pcmVoice:SiMMLVoice = SiOPMTable._instance._getGlobalPCMVoice(index & (SiOPMTable.PCM_DATA_MAX-1));
830             var pcmTable:SiOPMWavePCMTable = pcmVoice.waveData as SiOPMWavePCMTable;
831             return pcmTable.setSample(new SiOPMWavePCMData(data, int(samplingNote*64), srcChannelCount, channelCount), keyRangeFrom, keyRangeTo);
832         }
833        
834        
835         /** Set sampler wave data refered by %10.
836          *  @param index note number. 0-127 for bank0, 128-255 for bank1.
837          *  @param data wave data, Sound, Vector.&lt;Number&gt; or Vector.&lt;int&gt; is available. The Sound is extracted when the length is shorter than SiOPMWaveSamplerData.extractThreshold[msec].
838          *  @param ignoreNoteOff True to set ignoring note off.
839          *  @param pan pan of this sample [-64 - 64].
840          *  @param srcChannelCount channel count of source data, 1 for monoral, 2 for stereo.
841          *  @param channelCount channel count of this data, 1 for monoral, 2 for stereo, 0 sets same with srcChannelCount.
842          *  @return created data instance
843          *  @see #org.si.sion.module.SiOPMWaveSamplerData.extractThreshold
844          *  @see #render()
845          */
846         public function setSamplerWave(index:int, data:*, ignoreNoteOff:Boolean=false, pan:int=0, srcChannelCount:int=2, channelCount:int=0) : SiOPMWaveSamplerData
847         {
848             return SiOPMTable._instance.registerSamplerData(index, data, ignoreNoteOff, pan, srcChannelCount, channelCount);
849         }
850        
851        
852         /** Set pcm voice
853          *  @param index PCM data number.
854          *  @param voice pcm voice to set, ussualy from SiONSoundFont
855          *  @see SiONSoundFont
856          */
857         public function setPCMVoice(index:int, voice:SiONVoice) : void
858         {
859             SiOPMTable._instance._setGlobalPCMVoice(index & (SiOPMTable.PCM_DATA_MAX-1), voice);
860         }
861        
862        
863         /** Set sampler table
864          *  @param bank bank number
865          *  @param table sampler table class, ussualy from SiONSoundFont
866          *  @see SiONSoundFont
867          */
868         public function setSamplerTable(bank:int, table:SiOPMWaveSamplerTable) : void
869         {
870             SiOPMTable._instance.samplerTables[bank & (SiOPMTable.SAMPLER_TABLE_MAX-1)] = table;
871         }
872        
873        
874         /** [NOT RECOMMENDED] This function is for a compatibility with previous versions, please use setPCMWave instead of this function. @see #setPCMWave(). */
875         public function setPCMData(index:int, data:Vector.<Number>, samplingOctave:int=5, keyRangeFrom:int=0, keyRangeTo:int=127, isSourceDataStereo:Boolean=false) : SiOPMWavePCMData
876         {
877             return setPCMWave(index, data, samplingOctave*12+8, keyRangeFrom, keyRangeTo, (isSourceDataStereo)?2:1);
878         }
879        
880        
881         /** [NOT RECOMMENDED] This function is for a compatibility with previous versions, please use setPCMWave instead of this function. @see #setPCMWave(). */
882         public function setPCMSound(index:int, sound:Sound, samplingOctave:int=5, keyRangeFrom:int=0, keyRangeTo:int=127) : SiOPMWavePCMData
883         {
884             return setPCMWave(index, sound, samplingOctave*12+8, keyRangeFrom, keyRangeTo, 1, 0);
885         }
886        
887        
888         /** [NOT RECOMMENDED] This function is for a compatibility with previous versions, please use setSamplerWave instead of this function. @see #setSamplerWave(). */
889         public function setSamplerData(index:int, data:Vector.<Number>, ignoreNoteOff:Boolean=false, channelCount:int=1) : SiOPMWaveSamplerData
890         {
891             return setSamplerWave(index, data, ignoreNoteOff, 0, channelCount);
892         }
893        
894        
895         /** [NOT RECOMMENDED] This function is for a compatibility with previous versions, please use setSamplerWave instead of this function. @see #setSamplerWave(). */
896         public function setSamplerSound(index:int, sound:Sound, ignoreNoteOff:Boolean=false, channelCount:int=2) : SiOPMWaveSamplerData
897         {
898             return setSamplerWave(index, sound, ignoreNoteOff, 0, channelCount);
899         }
900        
901        
902         /** Set envelop table data refered by &#64;&#64;,na,np,nt,nf,_&#64;&#64;,_na,_np,_nt and _nf.
903          *  @param index envelop table number.
904          *  @param table envelop table vector.
905          *  @param loopPoint returning point index of looping. -1 sets no loop.
906          */
907         public function setEnvelopTable(index:int, table:Vector.<int>, loopPoint:int=-1) : void
908         {
909             SiMMLTable.registerMasterEnvelopTable(index, new SiMMLEnvelopTable(table, loopPoint));
910         }
911        
912        
913         /** Set wave table data refered by %6.
914          *  @param index wave table number.
915          *  @param voice voice to register.
916          */
917         public function setVoice(index:int, voice:SiONVoice) : void
918         {
919             if (!voice._isSuitableForFMVoice) throw errorNotGoodFMVoice();
920             SiMMLTable.registerMasterVoice(index, voice);
921         }
922        
923        
924         /** Clear all of WaveTables, FM Voices, EnvelopTables, Sampler waves and PCM waves.
925          *  @see #setWaveTable()
926          *  @see #setVoice()
927          *  @see #setEnvelopTable()
928          *  @see #setSamplerWave()
929          *  @see #setPCMWave()
930          */
931         public function clearAllUserTables() : void
932         {
933             SiOPMTable.instance.resetAllUserTables();
934             SiMMLTable.instance.resetAllUserTables();
935         }
936        
937        
938        
939        
940     // Interface for intaractivity
941     //----------------------------------------
942         /** Play sound registered in sampler table (registered by setSamplerData()), same as noteOn(note, new SiONVoice(10), ...).
943          *  @param sampleNumber sample number [0-127].
944          *  @param length note length in 16th beat. 0 sets no note off, this means you should call noteOff().
945          *  @param delay note on delay units in 16th beat.
946          *  @param quant quantize in 16th beat. 0 sets no quantization. 4 sets quantization by 4th beat.
947          *  @param trackID new tracks id (0-65535).
948          *  @param isDisposable use disposable track. The disposable track will free automatically when finished rendering.
949          *         This means you should not keep a dieposable track in your code perpetually.
950          *         If you want to keep track, set this argument false. And after using, SiMMLTrack::setDisposal() to disposed by system.<br/>
951          *         [REMARKS] Not disposable track is kept perpetually in the system while streaming, this may causes critical performance loss.
952          *  @return SiMMLTrack to play the note.
953          */
954         public function playSound(sampleNumber:int,
955                                   length:Number      = 0,
956                                   delay:Number       = 0,
957                                   quant:Number       = 0,
958                                   trackID:int        = 0,
959                                   isDisposable:Boolean = true) : SiMMLTrack
960         {
961             var internalTrackID:int = (trackID & SiMMLTrack.TRACK_ID_FILTER) | SiMMLTrack.DRIVER_NOTE,
962                 mmlTrack:SiMMLTrack = null,
963                 delaySamples:Number = sequencer.calcSampleDelay(0, delay, quant);
964            
965             // check track id exception
966             if (_noteOnExceptionMode != NEM_IGNORE) {
967                 // find a track sounds at same timing
968                 mmlTrack = sequencer._findActiveTrack(internalTrackID, delaySamples);
969                 if (_noteOnExceptionMode == NEM_REJECT && mmlTrack != null) return null; // reject
970                 else if (_noteOnExceptionMode == NEM_SHIFT) { // shift timing
971                     var step:int = sequencer.calcSampleLength(quant);
972                     while (mmlTrack) {
973                         delaySamples += step;
974                         mmlTrack = sequencer._findActiveTrack(internalTrackID, delaySamples);
975                     }
976                 }
977             }
978            
979             mmlTrack = mmlTrack || sequencer._newControlableTrack(internalTrackID, isDisposable);
980             if (mmlTrack) {
981                 mmlTrack.setChannelModuleType(10, 0);
982                 mmlTrack.keyOn(sampleNumber, length * sequencer.setting.resolution * 0.0625, delaySamples);
983             }
984             return mmlTrack;
985         }
986        
987        
988         /** Note on. This function only is available after play(). The NOTE_ON_STREAM event is dispatched inside.
989          *  @param note note number [0-127].
990          *  @param voice SiONVoice to play note. You can specify null, but it sets only a default square wave.
991          *  @param length note length in 16th beat. 0 sets no note off, this means you should call noteOff().
992          *  @param delay note on delay units in 16th beat.
993          *  @param quant quantize in 16th beat. 0 sets no quantization. 4 sets quantization by 4th beat.
994          *  @param trackID new tracks id (0-65535).
995          *  @param isDisposable use disposable track. The disposable track will free automatically when finished rendering.
996          *         This means you should not keep a dieposable track in your code perpetually.
997          *         If you want to keep track, set this argument false. And after using, call SiMMLTrack::setDisposal() to disposed by system.<br/>
998          *         [REMARKS] Not disposable track is kept in the system perpetually while streaming, this may causes critical performance loss.
999          *  @return SiMMLTrack to play the note.
1000          */
1001         public function noteOn(note:int,
1002                                voice:SiONVoice    = null,
1003                                length:Number      = 0,
1004                                delay:Number       = 0,
1005                                quant:Number       = 0,
1006                                trackID:int        = 0,
1007                                isDisposable:Boolean = true) : SiMMLTrack
1008         {
1009             var internalTrackID:int = (trackID & SiMMLTrack.TRACK_ID_FILTER) | SiMMLTrack.DRIVER_NOTE,
1010                 mmlTrack:SiMMLTrack = null,
1011                 delaySamples:Number = sequencer.calcSampleDelay(0, delay, quant);
1012            
1013             // check track id exception
1014             if (_noteOnExceptionMode != NEM_IGNORE) {
1015                 // find a track sounds at same timing
1016                 mmlTrack = sequencer._findActiveTrack(internalTrackID, delaySamples);
1017                 if (_noteOnExceptionMode == NEM_REJECT && mmlTrack != null) return null; // reject
1018                 else if (_noteOnExceptionMode == NEM_SHIFT) { // shift timing
1019                     var step:int = sequencer.calcSampleLength(quant);
1020                     while (mmlTrack) {
1021                         delaySamples += step;
1022                         mmlTrack = sequencer._findActiveTrack(internalTrackID, delaySamples);
1023                     }
1024                 }
1025             }
1026
1027             mmlTrack = mmlTrack || sequencer._newControlableTrack(internalTrackID, isDisposable);
1028             if (mmlTrack) {
1029                 if (voice) voice.updateTrackVoice(mmlTrack);
1030                 mmlTrack.keyOn(note, length * sequencer.setting.resolution * 0.0625, delaySamples);
1031             }
1032             return mmlTrack;
1033         }
1034        
1035        
1036         /** Note off. This function only is available after play(). The NOTE_OFF_STREAM event is dispatched inside.
1037          *  @param note note number [-1-127]. The value of -1 ignores note number.
1038          *  @param trackID track id to note off.
1039          *  @param delay note off delay units in 16th beat.
1040          *  @param quant quantize in 16th beat. 0 sets no quantization. 4 sets quantization by 4th beat.
1041          *  @param stopImmediately stop sound with reseting channel's process
1042          *  @return All SiMMLTracks switched key off.
1043          */
1044         public function noteOff(note:int, trackID:int=0, delay:Number=0, quant:Number=0, stopImmediately:Boolean=false) : Vector.<SiMMLTrack>
1045         {
1046             var internalTrackID:int = (trackID & SiMMLTrack.TRACK_ID_FILTER) | SiMMLTrack.DRIVER_NOTE,
1047                 delaySamples:int = sequencer.calcSampleDelay(0, delay, quant), n:int,
1048                 tracks:Vector.<SiMMLTrack> = new Vector.<SiMMLTrack>();
1049             for each (var mmlTrack:SiMMLTrack in sequencer.tracks) {
1050                 if (mmlTrack._sion_sequencer_internal::_internalTrackID == internalTrackID) {
1051                     if (note == -1 || (note == mmlTrack.note && mmlTrack.channel.isNoteOn)) {
1052                         mmlTrack.keyOff(delaySamples, stopImmediately);
1053                         tracks.push(mmlTrack);
1054                     } else if (mmlTrack.executor.noteWaitingFor == note) {
1055                         // if this track is waiting for starting sound ...
1056                         mmlTrack.keyOn(note, 1, delaySamples);
1057                         tracks.push(mmlTrack);
1058                     }
1059                 }
1060             }
1061             return tracks;
1062         }
1063        
1064        
1065         /** Play sequences with synchronizing. This function only is available after play().
1066          *  @param data The SiONData including sequences. This data is used only for sequences. The system ignores wave, envelop and voice data.
1067          *  @param voice SiONVoice to play sequence. The voice setting in the sequence has priority.
1068          *  @param length note length in 16th beat. 0 sets no note off, this means you should call noteOff().
1069          *  @param delay note on delay units in 16th beat.
1070          *  @param quant quantize in 16th beat. 0 sets no quantization. 4 sets quantization by 4th beat.
1071          *  @param trackID new tracks id (0-65535).
1072          *  @param isDisposable use disposable track. The disposable track will free automatically when finished rendering.
1073          *         This means you should not keep a dieposable track in your code perpetually.
1074          *         If you want to keep track, set this argument false. And after using, call SiMMLTrack::setDisposal() to disposed by system.<br/>
1075          *         [REMARKS] Not disposable track is kept in the system perpetually while streaming, this may causes critical performance loss.
1076          *  @return list of SiMMLTracks to play sequence.
1077          */
1078         public function sequenceOn(data:SiONData,
1079                                    voice:SiONVoice  = null,
1080                                    length:Number    = 0,
1081                                    delay:Number     = 0,
1082                                    quant:Number     = 1,
1083                                    trackID:int      = 0,
1084                                    isDisposable:Boolean = true) : Vector.<SiMMLTrack>
1085         {
1086             var internalTrackID:int = (trackID & SiMMLTrack.TRACK_ID_FILTER) | SiMMLTrack.DRIVER_SEQUENCE,
1087                 mmlTrack:SiMMLTrack,
1088                 tracks:Vector.<SiMMLTrack> = new Vector.<SiMMLTrack>(),
1089                 seq:MMLSequence = data.sequenceGroup.headSequence,
1090                 delaySamples:int = sequencer.calcSampleDelay(0, delay, quant),
1091                 lengthSamples:int = sequencer.calcSampleLength(length);
1092            
1093             // create new sequence tracks
1094             while (seq) {
1095                 if (seq.isActive) {
1096                     mmlTrack = sequencer._newControlableTrack(internalTrackID, isDisposable);
1097                     mmlTrack.sequenceOn(seq, lengthSamples, delaySamples);
1098                     if (voice) voice.updateTrackVoice(mmlTrack);
1099                     tracks.push(mmlTrack);
1100                 }
1101                 seq = seq.nextSequence;
1102             }
1103             return tracks;
1104         }
1105        
1106        
1107         /** Stop the sequences with synchronizing. This function only is available after play().
1108          *  @param trackID tracks id to stop.
1109          *  @param delay sequence off delay units in 16th beat.
1110          *  @param quant quantize in 16th beat. 0 sets no quantization. 4 sets quantization by 4th beat.
1111          *  @param stopWithReset stop sound with reseting channel's process
1112          *  @return list of SiMMLTracks stopped to play sequence.
1113          */
1114         public function sequenceOff(trackID:int, delay:Number=0, quant:Number=1, stopWithReset:Boolean=false) : Vector.<SiMMLTrack>
1115         {
1116             var internalTrackID:int = (trackID & SiMMLTrack.TRACK_ID_FILTER) | SiMMLTrack.DRIVER_SEQUENCE,
1117                 delaySamples:int = sequencer.calcSampleDelay(0, delay, quant), stoppedTrack:SiMMLTrack = null,
1118                 tracks:Vector.<SiMMLTrack> = new Vector.<SiMMLTrack>();
1119             for each (var mmlTrack:SiMMLTrack in sequencer.tracks) {
1120                 if (mmlTrack._sion_sequencer_internal::_internalTrackID == internalTrackID) {
1121                     mmlTrack.sequenceOff(delaySamples, stopWithReset);
1122                     tracks.push(mmlTrack);
1123                 }
1124             }
1125             return tracks;
1126         }
1127        
1128        
1129         /** Create new user controlable track. This function only is available after play().
1130          *  @trackID new user controlable track's ID.
1131          *  @return new user controlable track. This track is NOT disposable.
1132          */
1133         public function newUserControlableTrack(trackID:int=0) : SiMMLTrack
1134         {
1135             var internalTrackID:int = (trackID & SiMMLTrack.TRACK_ID_FILTER) | SiMMLTrack.USER_CONTROLLED;
1136             return sequencer._newControlableTrack(internalTrackID, false);
1137         }
1138        
1139        
1140        
1141        
1142     //====================================================================================================
1143     // Internal uses
1144     //====================================================================================================
1145     // callback for event trigger
1146     //----------------------------------------
1147         // call back when sound streaming
1148         private function _callbackEventTriggerOn(track:SiMMLTrack) : Boolean
1149         {
1150             return _publishEventTrigger(track, track.eventTriggerTypeOn, SiONTrackEvent.NOTE_ON_FRAME, SiONTrackEvent.NOTE_ON_STREAM);
1151         }
1152        
1153         // call back when sound streaming
1154         private function _callbackEventTriggerOff(track:SiMMLTrack) : Boolean
1155         {
1156             return _publishEventTrigger(track, track.eventTriggerTypeOff, SiONTrackEvent.NOTE_OFF_FRAME, SiONTrackEvent.NOTE_OFF_STREAM);
1157         }
1158        
1159         // publish event trigger
1160         private function _publishEventTrigger(track:SiMMLTrack, type:int, frameEvent:String, streamEvent:String) : Boolean
1161         {
1162             var event:SiONTrackEvent;
1163             if (type & 1) { // frame event. dispatch later
1164                 event = new SiONTrackEvent(frameEvent, this, track);
1165                 _trackEventQueue.push(event);
1166             }
1167             if (type & 2) { // sound event. dispatch immediately
1168                 event = new SiONTrackEvent(streamEvent, this, track);
1169                 dispatchEvent(event);
1170                 return !(event.isDefaultPrevented());
1171             }
1172             return true;
1173         }
1174        
1175         // call back when tempo changed
1176         private function _callbackTempoChanged(bufferIndex:int) : void
1177         {
1178             var event:SiONTrackEvent = new SiONTrackEvent(SiONTrackEvent.CHANGE_BPM, this, null, bufferIndex);
1179             _trackEventQueue.push(event);
1180         }
1181        
1182         // call back on beat
1183         private function _callbackBeat(bufferIndex:int, beatCounter:int) : void
1184         {
1185             var event:SiONTrackEvent = new SiONTrackEvent(SiONTrackEvent.BEAT, this, null, bufferIndex, 0, beatCounter);
1186             _trackEventQueue.push(event);
1187         }
1188        
1189        
1190        
1191        
1192     // operate event listener
1193     //----------------------------------------
1194         // add all event listners
1195         private function _queue_addAllEventListners() : void
1196         {
1197             if (_listenEvent != NO_LISTEN) throw errorDriverBusy(LISTEN_QUEUE);
1198             addEventListener(Event.ENTER_FRAME, _queue_onEnterFrame, false, _eventListenerPrior);
1199             _listenEvent = LISTEN_QUEUE;
1200         }
1201        
1202        
1203         // add all event listners
1204         private function _process_addAllEventListners() : void
1205         {
1206             if (_listenEvent != NO_LISTEN) throw errorDriverBusy(LISTEN_PROCESS);
1207             addEventListener(Event.ENTER_FRAME, _process_onEnterFrame, false, _eventListenerPrior);
1208             if (hasEventListener(SiONTrackEvent.BEAT)) sequencer._setBeatCallback(_callbackBeat);
1209             else sequencer._setBeatCallback(null);
1210             _dispatchStreamEvent = (hasEventListener(SiONEvent.STREAM));
1211             _prevFrameTime = getTimer();
1212             _listenEvent = LISTEN_PROCESS;
1213         }
1214        
1215        
1216         // remove all event listners
1217         private function _removeAllEventListners() : void
1218         {
1219             switch (_listenEvent) {
1220             case LISTEN_QUEUE:
1221                 removeEventListener(Event.ENTER_FRAME, _queue_onEnterFrame);
1222                 break;
1223             case LISTEN_PROCESS:
1224                 removeEventListener(Event.ENTER_FRAME, _process_onEnterFrame);
1225                 sequencer._setBeatCallback(null);
1226                 _dispatchStreamEvent = false;
1227                 break;
1228             }
1229             _listenEvent = NO_LISTEN;
1230         }
1231        
1232        
1233         // handler for Sound COMPLETE/IO_ERROR Event
1234         private function _onSoundEvent(e:Event) : void
1235         {
1236             if (e.target is Sound) {
1237                 e.target.removeEventListener(Event.COMPLETE,        _onSoundEvent);
1238                 e.target.removeEventListener(IOErrorEvent.IO_ERROR, _onSoundEvent);
1239             } else { // e.target is SoundLoader
1240                 e.target.removeEventListener(Event.COMPLETE,   _onSoundEvent);
1241                 e.target.removeEventListener(ErrorEvent.ERROR, _onSoundEvent);
1242             }
1243             var i:int = _loadingSoundList.indexOf(e.target);
1244             if (i != -1) _loadingSoundList.splice(i, 1);
1245         }
1246        
1247        
1248        
1249        
1250     // parse
1251     //----------------------------------------
1252         // parse system command on SiONDriver
1253         private function _parseSystemCommand(systemCommands:Array) : Boolean
1254         {
1255             var id:int, wcol:uint, effectSet:Boolean = false;
1256             for each (var cmd:* in systemCommands) {
1257                 switch(cmd.command){
1258                 case "#EFFECT":
1259                     effectSet = true;
1260                     effector.parseMML(cmd.number, cmd.content, cmd.postfix);
1261                     break;
1262                 case "#WAVCOLOR":
1263                 case "#WAVC":
1264                     wcol = parseInt(cmd.content, 16);
1265                     setWaveTable(cmd.number, SiONUtil.waveColor(wcol));
1266                     break;
1267                 }
1268             }
1269             return effectSet;
1270         }
1271        
1272        
1273        
1274        
1275     // jobs queue
1276     //----------------------------------------
1277         // cancel
1278         private function _cancelAllJobs() : void
1279         {
1280             _data = null;
1281             _mmlString = null;
1282             _currentJob = 0;
1283             _jobProgress = 0;
1284             _jobQueue.length = 0;
1285             _queueLength = 0;
1286             _removeAllEventListners();
1287             dispatchEvent(new SiONEvent(SiONEvent.QUEUE_CANCEL, this, null));
1288         }
1289        
1290        
1291         // next job
1292         private function _executeNextJob() : Boolean
1293         {
1294             _data = null;
1295             _mmlString = null;
1296             _currentJob = 0;
1297             if (_jobQueue.length == 0) {
1298                 _queueLength = 0;
1299                 _removeAllEventListners();
1300                 dispatchEvent(new SiONEvent(SiONEvent.QUEUE_COMPLETE, this, null));
1301                 return true;
1302             }
1303            
1304             var queue:SiONDriverJob = _jobQueue.shift();
1305             if (queue.mml) _prepareCompile(queue.mml, queue.data);
1306             else _prepareRender(queue.data, queue.buffer, queue.channelCount, queue.resetEffector);
1307             return false;
1308         }
1309        
1310        
1311         // on enterFrame
1312         private function _queue_onEnterFrame(e:Event) : void
1313         {
1314             try {
1315                 var event:SiONEvent, t:int = getTimer();
1316                
1317                 switch (_currentJob) {
1318                 case 1: // compile
1319                     _jobProgress = sequencer.compile(_queueInterval);
1320                     _timeCompile += getTimer() - t;
1321                     break;
1322                 case 2: // render
1323                     _jobProgress += (1 - _jobProgress) * 0.5;
1324                     while (getTimer() - t <= _queueInterval) {
1325                         if (_rendering()) {
1326                             _jobProgress = 1;
1327                             break;
1328                         }
1329                     }
1330                     _timeRender += getTimer() - t;
1331                     break;
1332                 }
1333                
1334                 // finish job
1335                 if (_jobProgress == 1) {
1336                     // finish all jobs
1337                     if (_executeNextJob()) return;
1338                 }
1339                
1340                 // progress
1341                 event = new SiONEvent(SiONEvent.QUEUE_PROGRESS, this, null, true);
1342                 dispatchEvent(event);
1343                 if (event.isDefaultPrevented()) _cancelAllJobs();   // canceled
1344             } catch (e:Error) {
1345                 // error
1346                 _removeAllEventListners();
1347                 _cancelAllJobs();
1348                 if (_debugMode) throw e;
1349                 else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
1350             }
1351         }
1352        
1353        
1354        
1355        
1356     // compile
1357     //----------------------------------------
1358         // prepare to compile
1359         private function _prepareCompile(mml:String, data:SiONData) : void
1360         {
1361             if (data) data.clear();
1362             _data = data || new SiONData();
1363             _mmlString = mml;
1364             sequencer.prepareCompile(_data, _mmlString);
1365             _jobProgress = 0.01;
1366             _timeCompile = 0;
1367             _currentJob = 1;
1368         }
1369        
1370        
1371        
1372        
1373     // render
1374     //----------------------------------------
1375         // prepare for rendering
1376         private function _prepareRender(data:*, renderBuffer:Vector.<Number>, renderBufferChannelCount:int, resetEffector:Boolean) : void
1377         {
1378             // same preparation as streaming
1379             _prepareProcess(data, resetEffector);
1380            
1381             // prepare rendering buffer
1382             _renderBuffer = renderBuffer || new Vector.<Number>();
1383             _renderBufferChannelCount = (renderBufferChannelCount==2) ? 2 : 1;
1384             _renderBufferSizeMax = _renderBuffer.length;
1385             _renderBufferIndex = 0;
1386
1387             // initialize parameters
1388             _jobProgress = 0.01;
1389             _timeRender = 0;
1390             _currentJob = 2;
1391         }
1392        
1393        
1394         // rendering @return true when finished rendering.
1395         private function _rendering() : Boolean
1396         {
1397             var i:int, j:int, imax:int, extention:int,
1398                 output:Vector.<Number> = module.output,
1399                 finished:Boolean = false;
1400            
1401             // processing
1402             module._beginProcess();
1403             effector._beginProcess();
1404             sequencer._process();
1405             effector._endProcess();
1406             module._endProcess();
1407            
1408             // limit rendering length
1409             imax      = _bufferLength<<1;
1410             extention = _bufferLength<<(_renderBufferChannelCount-1);
1411             if (_renderBufferSizeMax != 0 && _renderBufferSizeMax < _renderBufferIndex+extention) {
1412                 extention = _renderBufferSizeMax - _renderBufferIndex;
1413                 finished = true;
1414             }
1415            
1416             // extend buffer
1417             if (_renderBuffer.length < _renderBufferIndex+extention) {
1418                 _renderBuffer.length = _renderBufferIndex+extention;
1419             }
1420            
1421             // copy output
1422             if (_renderBufferChannelCount==2) {
1423                 for (i=0, j=_renderBufferIndex; i<imax; i++, j++) {
1424                     _renderBuffer[j] = output[i];
1425                 }
1426             } else {
1427                 for (i=0, j=_renderBufferIndex; i<imax; i+=2, j++) {
1428                     _renderBuffer[j] = output[i];
1429                 }
1430             }
1431            
1432             // incerement index
1433             _renderBufferIndex += extention;
1434            
1435             return (finished || (_renderBufferSizeMax==0 && sequencer.isFinished));
1436         }
1437        
1438        
1439        
1440        
1441     // process
1442     //----------------------------------------
1443         // prepare for processing
1444         private function _prepareProcess(data:*, resetEffector:Boolean) : void
1445         {
1446             if (data is String) {
1447                 // compile mml and play
1448                 _tempData = _tempData || new SiONData();
1449                 _data = compile(data as String, _tempData);
1450             } else {
1451                 // type check and play
1452                 if (!(data == null || data is SiONData)) throw errorDataIncorrect();
1453                 _data = data;
1454             }
1455            
1456             // THESE FUNCTIONS ORDER IS VERY IMPORTANT !!
1457             module.initialize(_channelCount, _bitRate, _bufferLength);      // initialize DSP
1458             module.reset();                                                 // reset all channels
1459             if (resetEffector) effector.initialize();                       // initialize (or reset) effectors
1460             else effector._reset();
1461             sequencer._prepareProcess(_data, _sampleRate, _bufferLength);   // set sequencer tracks (should be called after module.reset())
1462             if (_data) _parseSystemCommand(_data.systemCommands);           // parse #EFFECT command (should be called after effector._reset())
1463             effector._prepareProcess();                                     // set effector connections
1464             _trackEventQueue.length = 0;                                    // clear event que
1465            
1466             // set position
1467             if (_data && _position > 0) {
1468                 sequencer.dummyProcess(_position * _sampleRate * 0.001);
1469             }
1470              
1471             // set timer interruption
1472             if (_timerCallback != null) {
1473                 sequencer.setGlobalSequence(_timerSequence); // set timer interruption
1474                 sequencer._setTimerCallback(_timerCallback);
1475             }
1476         }
1477        
1478        
1479         // on enterFrame
1480         private function _process_onEnterFrame(e:Event) : void
1481         {
1482             // frame rate
1483             var t:int = getTimer();
1484             _frameRate = t - _prevFrameTime;
1485             _prevFrameTime = t;
1486            
1487             // _suspendStreaming = true when first streaming
1488             if (_suspendStreaming) {
1489                 _onSuspendStream();
1490             } else {
1491                 // preserve stop
1492                 if (_preserveStop) stop();
1493
1494                 // frame trigger
1495                 if (_trackEventQueue.length > 0) {
1496                     _trackEventQueue = _trackEventQueue.filter(_trackEventQueueFilter);
1497                 }
1498             }
1499         }
1500        
1501        
1502         // _trackEventQueue filter
1503         private function _trackEventQueueFilter(e:SiONTrackEvent, i:int, v:Vector.<SiONTrackEvent>) : Boolean {
1504             if (e._decrementTimer(_frameRate)) {
1505                 dispatchEvent(e);
1506                 return false;
1507             }
1508             return true;
1509         }
1510        
1511        
1512         // suspend starting stream
1513         private function _onSuspendStream() : void {
1514             // reset suspending
1515             _suspendStreaming = _suspendWhileLoading && (_loadingSoundList.length > 0);
1516
1517             if (!_suspendStreaming) {
1518                 // dispatch streaming start event
1519                 var event:SiONEvent = new SiONEvent(SiONEvent.STREAM_START, this, null, true);
1520                 dispatchEvent(event);
1521                 if (event.isDefaultPrevented()) stop();   // canceled
1522             }
1523         }
1524        
1525
1526         // on sampleData
1527         private function _streaming(e:SampleDataEvent) : void
1528         {
1529             var buffer:ByteArray = e.data, extracted:int,
1530                 output:Vector.<Number> = module.output,
1531                 imax:int, i:int, event:SiONEvent;
1532
1533             // calculate latency (0.022675736961451247 = 1/44.1)
1534             if (_soundChannel) {
1535                 _latency = e.position * 0.022675736961451247 - _soundChannel.position;
1536             }
1537
1538             try {
1539                 // set streaming flag
1540                 _inStreaming = true;
1541                
1542                 if (_isPaused || _suspendStreaming) {
1543                     // fill silence
1544                     _fillzero(e.data);
1545                 } else {
1546                     // process starting time
1547                     var t:int = getTimer();
1548                    
1549                     // processing
1550                     module._beginProcess();
1551                     effector._beginProcess();
1552                     sequencer._process();
1553                     effector._endProcess();
1554                     module._endProcess();
1555                    
1556                     // calculate the average of processing time
1557                     _timePrevStream = t;
1558                     _timeProcessTotal -= _timeProcessData.i;
1559                     _timeProcessData.i = getTimer() - t;
1560                     _timeProcessTotal += _timeProcessData.i;
1561                     _timeProcessData   = _timeProcessData.next;
1562                     _timeProcess = _timeProcessTotal * _timeProcessAveRatio;
1563                    
1564                     // write samples
1565                     imax = output.length;
1566                     if (_backgroundSound) {
1567                         // w/ background sound
1568                         _backgroundBuffer.length = 0;
1569                         extracted = _backgroundSound.extract(_backgroundBuffer, _bufferLength);
1570                         if (_backgroundLoop) {
1571                             while (extracted < _bufferLength) {
1572                                 extracted += _backgroundSound.extract(_backgroundBuffer, _bufferLength-extracted, 0);
1573                             }
1574                         }
1575                         if (extracted == _bufferLength) {
1576                             for (i=0; i<imax; i++) buffer.writeFloat(output[i]+_backgroundBuffer.readFloat()*_backgroundLevel);
1577                         } else {
1578                             for (i=0; i<extracted; i++) buffer.writeFloat(output[i]+_backgroundBuffer.readFloat()*_backgroundLevel);
1579                             for (; i<imax; i++) buffer.writeFloat(output[i]);
1580                         }
1581                     } else {
1582                         // w/o background sound
1583                         for (i=0; i<imax; i++) buffer.writeFloat(output[i]);
1584                     }
1585                    
1586                     // dispatch streaming event
1587                     if (_dispatchStreamEvent) {
1588                         event = new SiONEvent(SiONEvent.STREAM, this, buffer, true);
1589                         dispatchEvent(event);
1590                         if (event.isDefaultPrevented()) stop();   // canceled
1591                     }
1592                    
1593                     // dispatch finishSequence event
1594                     if (!_isFinishSeqDispatched && sequencer.isSequenceFinished) {
1595                         dispatchEvent(new SiONEvent(SiONEvent.FINISH_SEQUENCE, this));
1596                         _isFinishSeqDispatched = true;
1597                     }
1598                    
1599                     // fading
1600                     if (_fader.execute()) {
1601                         var eventType:String = (_fader.isIncrement) ? SiONEvent.FADE_IN_COMPLETE : SiONEvent.FADE_OUT_COMPLETE;
1602                         dispatchEvent(new SiONEvent(eventType, this, buffer));
1603                         if (_autoStop && !_fader.isIncrement) stop();
1604                     } else {
1605                         // auto stop
1606                         if (_autoStop && sequencer.isFinished) stop();
1607                     }
1608                 }
1609                
1610                 // reset streaming flag
1611                 _inStreaming = false;
1612                
1613             } catch (e:Error) {
1614                 // error
1615                 _removeAllEventListners();
1616                 if (_debugMode) throw e;
1617                 else dispatchEvent(new ErrorEvent(ErrorEvent.ERROR, false, false, e.message));
1618             }
1619         }
1620        
1621        
1622         // fill zero
1623         private function _fillzero(buffer:ByteArray) : void {
1624             var i:int, imax:int = _bufferLength;
1625             for (i=0; i<imax; i++) {
1626                 buffer.writeFloat(0);
1627                 buffer.writeFloat(0);
1628             }
1629         }
1630        
1631        
1632        
1633        
1634     // operations
1635     //----------------------------------------
1636         // volume fading
1637         private function _fadeVolume(v:Number) : void {
1638             _faderVolume = v;
1639             _soundTransform.volume = _masterVolume * _faderVolume;
1640             if (_soundChannel) _soundChannel.soundTransform = _soundTransform;
1641             if (_dispatchFadingEvent) {
1642                 var event:SiONEvent = new SiONEvent(SiONEvent.FADE_PROGRESS, this, null, true);
1643                 dispatchEvent(event);
1644                 if (event.isDefaultPrevented()) _fader.stop();   // canceled
1645             }
1646         }
1647        
1648        
1649        
1650        
1651     // errors
1652     //----------------------------------------
1653         private function errorPluralDrivers() : Error {
1654             return new Error("SiONDriver error; Cannot create pulral SiONDrivers.");
1655         }
1656        
1657        
1658         private function errorParamNotAvailable(param:String, num:Number) : Error {
1659             return new Error("SiONDriver error; Parameter not available. " + param + String(num));
1660         }
1661        
1662        
1663         private function errorDataIncorrect() : Error {
1664             return new Error("SiONDriver error; data incorrect in play() or render().");
1665         }
1666        
1667        
1668         private function errorDriverBusy(execID:int) : Error {
1669             var states:Array = ["???", "compiling", "streaming", "rendering"];
1670             return new Error("SiONDriver error: Driver busy. Call " + states[execID] + " while " + states[_listenEvent] + ".");
1671         }
1672        
1673        
1674         private function errorCannotChangeBPM() : Error {
1675             return new Error("SiONDriver error: Cannot change bpm while rendering (SiONTrackEvent.NOTE_*_STREAM).");
1676         }
1677        
1678        
1679         private function errorNotGoodFMVoice() : Error {
1680             return new Error("SiONDriver error; Cannot register the voice.");
1681         }
1682        
1683         private function errorCannotListenLoading() : Error {
1684             return new Error("SiONDriver error; the class not available for listenSoundLoadingStatus");
1685         }
1686     }
1687 }
1688
1689
1690
1691
1692 import org.si.sion.SiONData;
1693
1694 class SiONDriverJob
1695 {
1696     public var mml:String;
1697     public var buffer:Vector.<Number>;
1698     public var data:SiONData;
1699     public var channelCount:int;
1700     public var resetEffector:Boolean;
1701    
1702     function SiONDriverJob(mml_:String, buffer_:Vector.<Number>, data_:SiONData, channelCount_:int, resetEffector_:Boolean)
1703     {
1704         mml = mml_;
1705         buffer = buffer_;
1706         data = data_ || new SiONData();
1707         channelCount = channelCount_;
1708         resetEffector = resetEffector_;
1709     }
1710 }
1711
1712
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。