| 1 |
//---------------------------------------------------------------------------------------------------- |
|---|
| 2 |
// Bass sequencer class |
|---|
| 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.*; |
|---|
| 10 |
import org.si.sion.utils.Chord; |
|---|
| 11 |
import org.si.sion.utils.Scale; |
|---|
| 12 |
import org.si.sound.patterns.Note; |
|---|
| 13 |
import org.si.sound.patterns.Sequencer; |
|---|
| 14 |
import org.si.sound.patterns.BassSequencerPresetPattern; |
|---|
| 15 |
import org.si.sound.namespaces._sound_object_internal; |
|---|
| 16 |
|
|---|
| 17 |
/** @eventType org.si.sound.events.SoundObjectEvent.ENTER_FRAME */ |
|---|
| 18 |
[Event(name="enterFrame", type="org.si.sound.events.SoundObjectEvent")] |
|---|
| 19 |
/** @eventType org.si.sound.events.SoundObjectEvent.ENTER_SEGMENT */ |
|---|
| 20 |
[Event(name="enterSegment", type="org.si.sound.events.SoundObjectEvent")] |
|---|
| 21 |
|
|---|
| 22 |
/** Bass sequencer provides simple monophonic bass line. */ |
|---|
| 23 |
public class BassSequencer extends PatternSequencer |
|---|
| 24 |
{ |
|---|
| 25 |
// namespace |
|---|
| 26 |
//---------------------------------------- |
|---|
| 27 |
use namespace _sound_object_internal; |
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
// static variables |
|---|
| 33 |
//---------------------------------------- |
|---|
| 34 |
static private var _presetPattern:BassSequencerPresetPattern = null; |
|---|
| 35 |
static private var bassPatternList:Array; |
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
// variables |
|---|
| 41 |
//---------------------------------------- |
|---|
| 42 |
/** @private [protected] chord instance */ |
|---|
| 43 |
protected var _scale:Scale; |
|---|
| 44 |
/** @private [protected] Default chord instance, this is used when the name is specifyed */ |
|---|
| 45 |
protected var _defaultChord:Chord = new Chord(); |
|---|
| 46 |
|
|---|
| 47 |
/** @private [protected] pettern. */ |
|---|
| 48 |
protected var _pattern:Vector.<Note>; |
|---|
| 49 |
/** @private [protected] Current length sequence pattern. */ |
|---|
| 50 |
protected var _currentPattern:Array; |
|---|
| 51 |
/** @private [protected] Next length sequence pattern to change while playing. */ |
|---|
| 52 |
protected var _nextPattern:Array; |
|---|
| 53 |
/** @private [protected] pettern number. */ |
|---|
| 54 |
protected var _patternNumber:int; |
|---|
| 55 |
/** @private [protected] Change bass line pattern at the head of segment. */ |
|---|
| 56 |
protected var _changePatternOnSegment:Boolean; |
|---|
| 57 |
|
|---|
| 58 |
|
|---|
| 59 |
|
|---|
| 60 |
// properties |
|---|
| 61 |
//---------------------------------------- |
|---|
| 62 |
/** Preset voice list */ |
|---|
| 63 |
//public function get presetVoice() : BassSequencerPresetVoice { return _presetVoice; } |
|---|
| 64 |
|
|---|
| 65 |
/** Preset pattern list */ |
|---|
| 66 |
public function get presetPattern() : BassSequencerPresetPattern { return _presetPattern; } |
|---|
| 67 |
|
|---|
| 68 |
|
|---|
| 69 |
/** Bass note of chord */ |
|---|
| 70 |
override public function get note() : int { return _scale.bassNote; } |
|---|
| 71 |
override public function set note(n:int) : void { |
|---|
| 72 |
if (_scale !== _defaultChord) _defaultChord.copyFrom(_scale); |
|---|
| 73 |
_defaultChord.bassNote = n; |
|---|
| 74 |
_scale = _defaultChord; |
|---|
| 75 |
_updateBassNote(); |
|---|
| 76 |
} |
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
/** chord instance */ |
|---|
| 80 |
public function get scale() : Scale { return _scale; } |
|---|
| 81 |
public function set scale(s:Scale) : void { |
|---|
| 82 |
_scale = s || _defaultChord; |
|---|
| 83 |
_updateBassNote(); |
|---|
| 84 |
} |
|---|
| 85 |
|
|---|
| 86 |
|
|---|
| 87 |
/** specify chord by name */ |
|---|
| 88 |
public function get chordName() : String { return _scale.name; } |
|---|
| 89 |
public function set chordName(name:String) : void { |
|---|
| 90 |
_defaultChord.name = name; |
|---|
| 91 |
_scale = _defaultChord; |
|---|
| 92 |
_updateBassNote(); |
|---|
| 93 |
} |
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 |
/** maximum limit of bass line Pattern number */ |
|---|
| 97 |
public function get patternNumberMax() : int { |
|---|
| 98 |
return bassPatternList.length; |
|---|
| 99 |
} |
|---|
| 100 |
|
|---|
| 101 |
|
|---|
| 102 |
/** bass line Pattern number */ |
|---|
| 103 |
public function get patternNumber() : int { return _patternNumber; } |
|---|
| 104 |
public function set patternNumber(n:int) : void { |
|---|
| 105 |
if (n < 0 || n >= bassPatternList.length) return; |
|---|
| 106 |
_patternNumber = n; |
|---|
| 107 |
pattern = bassPatternList[n]; |
|---|
| 108 |
} |
|---|
| 109 |
|
|---|
| 110 |
|
|---|
| 111 |
/** Number Array of the sequence notes. If the value is 0, insert rest instead. */ |
|---|
| 112 |
public function get pattern() : Array { return _currentPattern || _nextPattern; } |
|---|
| 113 |
public function set pattern(pat:Array) : void { |
|---|
| 114 |
if (isPlaying && _changePatternOnSegment) { |
|---|
| 115 |
_nextPattern = pat; |
|---|
| 116 |
} else { |
|---|
| 117 |
_currentPattern = pat; |
|---|
| 118 |
_updateBassNote(); |
|---|
| 119 |
} |
|---|
| 120 |
} |
|---|
| 121 |
|
|---|
| 122 |
|
|---|
| 123 |
/** True to change bass line pattern at the head of segment. @default true */ |
|---|
| 124 |
public function get changePatternOnNextSegment() : Boolean { return _changePatternOnSegment; } |
|---|
| 125 |
public function set changePatternOnNextSegment(b:Boolean) : void { |
|---|
| 126 |
_changePatternOnSegment = b; |
|---|
| 127 |
} |
|---|
| 128 |
|
|---|
| 129 |
|
|---|
| 130 |
|
|---|
| 131 |
|
|---|
| 132 |
// constructor |
|---|
| 133 |
//---------------------------------------- |
|---|
| 134 |
/** constructor |
|---|
| 135 |
* @param scale Bassline scale or chord or chord name. |
|---|
| 136 |
* @param patternNumber bass line pattern number |
|---|
| 137 |
* @param changePatternOnSegment When this is true, pattern and chord are changed at the head of next segment. |
|---|
| 138 |
* @see org.si.sion.utils.Scale |
|---|
| 139 |
*/ |
|---|
| 140 |
function BassSequencer(chord:*=null, patternNumber:int=6, changePatternOnSegment:Boolean=true) |
|---|
| 141 |
{ |
|---|
| 142 |
super(); |
|---|
| 143 |
name = "BassSequencer"; |
|---|
| 144 |
|
|---|
| 145 |
if (_presetPattern == null) { |
|---|
| 146 |
_presetPattern = new BassSequencerPresetPattern(); |
|---|
| 147 |
bassPatternList = _presetPattern["bass"]; |
|---|
| 148 |
} |
|---|
| 149 |
|
|---|
| 150 |
_pattern = new Vector.<Note>(); |
|---|
| 151 |
|
|---|
| 152 |
_changePatternOnSegment = false; |
|---|
| 153 |
if (chord is String) this.chordName = chord as String; |
|---|
| 154 |
else this.scale = chord as Chord; |
|---|
| 155 |
this.patternNumber = patternNumber; |
|---|
| 156 |
_changePatternOnSegment = changePatternOnSegment; |
|---|
| 157 |
|
|---|
| 158 |
_sequencer.onEnterFrame = _onEnterFrame; |
|---|
| 159 |
_sequencer.onEnterSegment = _onEnterSegment; |
|---|
| 160 |
} |
|---|
| 161 |
|
|---|
| 162 |
|
|---|
| 163 |
/** @private [protected] */ |
|---|
| 164 |
protected function _updateBassNote() : void |
|---|
| 165 |
{ |
|---|
| 166 |
var i:int, imax:int, bn:int = _scale.bassNote; |
|---|
| 167 |
if (_currentPattern) { |
|---|
| 168 |
imax = _currentPattern.length; |
|---|
| 169 |
_pattern.length = imax; |
|---|
| 170 |
for (i=0; i<imax; i++) { |
|---|
| 171 |
if (_pattern[i] == null) _pattern[i] = new Note(); |
|---|
| 172 |
if (_currentPattern[i]) { |
|---|
| 173 |
_pattern[i].note = _currentPattern[i].note - 33 + bn; |
|---|
| 174 |
_pattern[i].velocity = _currentPattern[i].velocity; |
|---|
| 175 |
_pattern[i].length = _currentPattern[i].length; |
|---|
| 176 |
} else { |
|---|
| 177 |
_pattern[i].setRest(); |
|---|
| 178 |
} |
|---|
| 179 |
} |
|---|
| 180 |
} else { |
|---|
| 181 |
_pattern.length = 16; |
|---|
| 182 |
for (i=0; i<16; i++) { |
|---|
| 183 |
if (_pattern[i] == null) _pattern[i] = new Note(); |
|---|
| 184 |
_pattern[i].setRest(); |
|---|
| 185 |
} |
|---|
| 186 |
} |
|---|
| 187 |
_sequencer.pattern = _pattern; |
|---|
| 188 |
} |
|---|
| 189 |
|
|---|
| 190 |
|
|---|
| 191 |
/** @private [protected] enter segment handler */ |
|---|
| 192 |
override protected function _onEnterSegment(seq:Sequencer) : void |
|---|
| 193 |
{ |
|---|
| 194 |
if (_nextPattern) { |
|---|
| 195 |
_currentPattern = _nextPattern; |
|---|
| 196 |
_nextPattern = null; |
|---|
| 197 |
_updateBassNote(); |
|---|
| 198 |
} |
|---|
| 199 |
super._onEnterSegment(seq); |
|---|
| 200 |
} |
|---|
| 201 |
} |
|---|
| 202 |
} |
|---|
| 203 |
|
|---|