root/as3/SiOPM/trunk/src/org/si/sound/ChordPad.as

リビジョン 3839, 11.3 kB (コミッタ: keim, コミット時期: 2 年 前)

SiON ver0.60 updated

Line 
1 //----------------------------------------------------------------------------------------------------
2 // Polyphonic chord pad synthesizer
3 //  Copyright (c) 2009 keim All rights reserved.
4 //  Distributed under BSD-style license (see org.si.license.txt).
5 //----------------------------------------------------------------------------------------------------
6
7
8 package org.si.sound {
9     import org.si.sion.SiONData;
10     import org.si.sion.sequencer.SiMMLTrack;
11     import org.si.sion.utils.Chord;
12     import org.si.sound.patterns.Note;
13     import org.si.sound.patterns.Sequencer;
14     import org.si.sound.namespaces._sound_object_internal;
15    
16     /** @eventType org.si.sound.events.SoundObjectEvent.ENTER_FRAME */
17     [Event(name="enterFrame",   type="org.si.sound.events.SoundObjectEvent")]
18     /** @eventType org.si.sound.events.SoundObjectEvent.ENTER_SEGMENT */
19     [Event(name="enterSegment", type="org.si.sound.events.SoundObjectEvent")]
20    
21     /** Chord pad provides polyphonic synthesizer controled by chord and rhythm pattern. */
22     public class ChordPad extends MultiTrackSoundObject
23     {
24     // namespace
25     //----------------------------------------
26         use namespace _sound_object_internal;
27        
28        
29        
30        
31     // constants
32     //----------------------------------------
33         /** closed voicing mode [o5c,o5e,o5g,o5b,o6e,o6g] for CM7 @see voiceMode */
34         static public const CLOSED:int = 0x543210;
35        
36         /** opened voicing mode [o5c,o5g,o5b,o6e,o6g,o6b] for CM7 @see voiceMode */
37         static public const OPENED:int = 0x654320;
38        
39         /** middle-position voicing mode [o5e,o5g,o5b,o6e,o6g,o6b] for CM7 @see voiceMode */
40         static public const MIDDLE:int = 0x654321;
41        
42         /** high-position voicing mode [o5g,o5b,o6e,o6g,o6b,o7e] for CM7 @see voiceMode */
43         static public const HIGH:int = 0x765432;
44        
45         /** opened high-position voicing mode [o5g,o6e,o6g,o6b,o7e,o7g] for CM7 @see voiceMode */
46         static public const OPENED_HIGH:int = 0x876542;
47        
48        
49        
50        
51     // variables
52     //----------------------------------------
53         /** @private [protected] Monophonic sequencers */
54         protected var _operators:Vector.<Sequencer>;
55        
56         /** @private [protected] Sequence data */
57         protected var _data:SiONData;
58        
59         /** @private [protected] chord instance */
60         protected var _chord:Chord;
61         /** @private [protected] Default chord instance, this is used when the name is specifyed */
62         protected var _defaultChord:Chord = new Chord();
63         /** @private [protected] chord notes index */
64         protected var _noteIndexes:int;
65        
66         /** @private [protected] Note pattern */
67         protected var _pattern:Vector.<Note>;
68         /** @private [protected] Current length sequence pattern. */
69         protected var _currentPattern:Array;
70         /** @private [protected] Next length sequence pattern to change while playing. */
71         protected var _nextPattern:Array;
72         /** @private [protected] Change bass line pattern at the head of segment. */
73         protected var _changePatternOnSegment:Boolean;
74        
75        
76        
77        
78     // properties
79     //----------------------------------------
80         /** list of monophonic operators */
81         public function get operators() : Vector.<Sequencer> { return operators; }
82        
83         /** Number of monophonic operators */
84         public function get operatorCount() : int { return operators.length; }
85        
86        
87         /** root note of current chord @default 60 */
88         override public function get note() : int { return _chord.rootNote; }
89         override public function set note(n:int) : void {
90             if (_chord !== _defaultChord) _defaultChord.copyFrom(_chord);
91             _defaultChord.rootNote = n;
92             _chord = _defaultChord;
93             _updateChordNotes();
94         }
95        
96        
97         /** chord instance @default Chord("C") */
98         public function get chord() : Chord { return _chord; }
99         public function set chord(c:Chord) : void {
100             if (c == null) _chord = _defaultChord;
101             _chord = c;
102             _updateChordNotes();
103         }
104        
105        
106         /** specify chord by name @default "C" */
107         public function get chordName() : String { return _chord.name; }
108         public function set chordName(name:String) : void {
109             _defaultChord.name = name;
110             _chord = _defaultChord;
111             _updateChordNotes();
112         }
113        
114        
115         /** voicing mode @default CLOSED */
116         public function get voiceMode() : int { return _noteIndexes; }
117         public function set voiceMode(m:int) : void {
118             _noteIndexes = m;
119             _updateChordNotes();
120         }
121        
122        
123         /** note length in 16th beat. */
124         public function get noteLength() : Number { return _operators[0].defaultLength; }
125         public function set noteLength(l:Number) : void {
126             if (l<0.25) l=0.25;
127             else if (l>16) l=16;
128             for (var i:int=0; i<operatorCount; i++) {
129                 _operators[i].defaultLength = l;
130                 _operators[i].gridStep = l * 120;
131             }
132         }
133        
134        
135         /** Number Array of the sequence notes' length. If the value is 0, insert rest instead. */
136         public function get pattern() : Array { return _currentPattern || _nextPattern; }
137         public function set pattern(pat:Array) : void {
138             if (isPlaying && _changePatternOnSegment) _nextPattern = pat;
139             else _updateSequencePattern(pat);
140         }
141        
142        
143         /** True to change bass line pattern at the head of segment. @default true */
144         public function get changePatternOnSegment() : Boolean { return _changePatternOnSegment; }
145         public function set changePatternOnSegment(b:Boolean) : void {
146             _changePatternOnSegment = b;
147         }
148        
149        
150        
151        
152     // constructor
153     //----------------------------------------
154         /** constructor
155          *  @param chord org.si.sion.utils.Chord, chord name String or null is suitable.
156          *  @param operatorCount Number of monophonic operators (1-6).
157          *  @param voiceMode Voicing mode.
158          *  @param pattern Number Array of the sequence notes' length. If the value is 0, insert rest instead.
159          *  @param changePatternOnSegment When this is true, pattern and chord are changed at the head of next segment.
160          */
161         function ChordPad(chord:*=null, operatorCount:int=3, voiceMode:int=CLOSED, pattern:Array=null, changePatternOnSegment:Boolean=true)
162         {
163             super("ChordPad");
164            
165             if (operatorCount<1 || operatorCount>6) throw new Error("ChordPad; Number of operators should be in the range of 1 - 6.");
166            
167             _data = new SiONData();
168             _operators = new Vector.<Sequencer>(operatorCount);
169             _noteIndexes = voiceMode;
170            
171             var defaultVelocity:int = 256 / operatorCount;
172             if (defaultVelocity >128) defaultVelocity = 128;
173             for (var i:int=0; i<operatorCount; i++) {
174                 _operators[i] = new Sequencer(this, _data, 60, defaultVelocity, 1);
175             }
176            
177             if (chord is Chord) {
178                 _chord = chord as Chord;
179             } else {
180                 _chord = _defaultChord;
181                 if (chord is String) {
182                     _chord.name = chord as String;
183                 }
184             }
185            
186             _nextPattern = null;
187             _pattern = new Vector.<Note>();
188             _changePatternOnSegment = changePatternOnSegment;
189            
190             _updateChordNotes();
191             _updateSequencePattern(pattern);
192         }
193        
194        
195        
196        
197     // configure
198     //----------------------------------------
199        
200        
201        
202        
203     // operations
204     //----------------------------------------
205         /** play drum sequence */
206         override public function play() : void
207         {
208             var i:int, imax:int = _operators.length, opn:int;
209             stop();
210             _tracks = _sequenceOn(_data, false, false);
211             if (_tracks && _tracks.length == imax) {
212                 _synthesizer._registerTracks(_tracks);
213                 for (i=0, opn=0; i<imax; i++) {
214                     if (_tracks[opn].trackNumber > _tracks[i].trackNumber) opn = i;
215                     _operators[i].play(_tracks[i]);
216                 }
217                 _operators[opn].onEnterFrame   = _onEnterFrame;
218                 _operators[opn].onEnterSegment = _onEnterSegment;
219             } else {
220                 throw new Error("unknown error");
221             }
222         }
223        
224        
225         /** stop sequence */
226         override public function stop() : void
227         {
228             if (_tracks) {
229                 for (var i:int=0; i<_operators.length; i++) {
230                     _operators[i].stop();
231                     _operators[i].onEnterFrame   = null;
232                     _operators[i].onEnterSegment = null;
233                 }
234                 _synthesizer._unregisterTracks(_tracks[0], _tracks.length);
235                 for each (var t:SiMMLTrack in _tracks) t.setDisposable();
236                 _tracks = null;
237                 _sequenceOff(false);
238             }
239             _stopEffect();
240         }
241        
242        
243        
244        
245     // internals
246     //----------------------------------------
247         /** @private [protected] update chord notes */
248         protected function _updateChordNotes() : void
249         {
250             var i:int, imax:int = _operators.length, noteIndex:int;
251             for (i=0; i<imax; i++) {
252                 _operators[i].defaultNote = _chord.getNote((_noteIndexes>>(i<<2)) & 15);
253             }
254         }
255        
256        
257         /** @private [protected] update sequence pattern */
258         protected function _updateSequencePattern(lengthPattern:Array) : void
259         {
260             var i:int, imax:int;
261            
262             _currentPattern = lengthPattern;
263             if (_currentPattern) {
264                 imax = _currentPattern.length;
265                 _pattern.length = imax;
266                 for (i=0; i<imax; i++) {
267                     if (_pattern[i] == null) _pattern[i] = new Note();
268                     if (lengthPattern[i] == 0) _pattern[i].setRest();
269                     else _pattern[i].setNote(-1, -1, _currentPattern[i]);
270                 }
271                 imax = _operators.length;
272                 for (i=0; i<imax; i++) {
273                     _operators[i].pattern = _pattern;
274                 }
275             } else {
276                 for (i=0; i<imax; i++) {
277                     _operators[i].pattern = null;
278                 }
279             }
280         }
281        
282        
283         /** @private [protected] on enter segment */
284         override protected function _onEnterSegment(seq:Sequencer) : void
285         {
286             if (_nextPattern != null) {
287                 _updateSequencePattern(_nextPattern);
288                 _nextPattern = null;
289             }
290             super._onEnterSegment(seq);
291         }
292     }
293 }
294
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。