mirror of
https://github.com/Tonejs/Tone.js
synced 2024-11-16 16:48:00 +00:00
Tone.Pattern iterates through an array of events in a number of patterns
This commit is contained in:
parent
89f4e738fc
commit
d6d9c397de
2 changed files with 132 additions and 161 deletions
132
Tone/event/Pattern.js
Normal file
132
Tone/event/Pattern.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
define(["Tone/core/Tone", "Tone/event/Loop", "Tone/control/CtrlPattern"], function (Tone) {
|
||||
|
||||
/**
|
||||
* @class Tone.Pattern arpeggiates between the given notes
|
||||
* in a number of patterns.
|
||||
* @extends {Tone.Loop}
|
||||
* @param {Function} callback The callback to invoke with the
|
||||
* event.
|
||||
* @param {Array} events The events to arpeggiate over.
|
||||
*/
|
||||
Tone.Pattern = function(){
|
||||
|
||||
var options = this.optionsObject(arguments, ["callback", "events", "pattern"], Tone.Pattern.defaults);
|
||||
|
||||
Tone.Loop.call(this, options);
|
||||
|
||||
/**
|
||||
* The pattern manager
|
||||
* @type {Tone.CtrlPattern}
|
||||
* @private
|
||||
*/
|
||||
this._pattern = new Tone.CtrlPattern({
|
||||
"values" : options.events,
|
||||
"type" : options.pattern,
|
||||
"index" : options.index
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Tone.extend(Tone.Pattern, Tone.Loop);
|
||||
|
||||
/**
|
||||
* The defaults
|
||||
* @const
|
||||
* @type {Object}
|
||||
*/
|
||||
Tone.Pattern.defaults = {
|
||||
"pattern" : Tone.CtrlPattern.Type.Up,
|
||||
"events" : [],
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal function called when the notes should be called
|
||||
* @param {Number} time The time the event occurs
|
||||
* @private
|
||||
*/
|
||||
Tone.Pattern.prototype._tick = function(time){
|
||||
this.callback(time, this._pattern.value);
|
||||
this._pattern.next();
|
||||
};
|
||||
|
||||
/**
|
||||
* The current index in the events array.
|
||||
* @memberOf Tone.Pattern#
|
||||
* @type {Time}
|
||||
* @name index
|
||||
*/
|
||||
Object.defineProperty(Tone.Pattern.prototype, "index", {
|
||||
get : function(){
|
||||
return this._pattern.index;
|
||||
},
|
||||
set : function(i){
|
||||
this._pattern.index = i;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The array of events.
|
||||
* @memberOf Tone.Pattern#
|
||||
* @type {Time}
|
||||
* @name events
|
||||
*/
|
||||
Object.defineProperty(Tone.Pattern.prototype, "events", {
|
||||
get : function(){
|
||||
return this._pattern.values;
|
||||
},
|
||||
set : function(vals){
|
||||
this._pattern.values = vals;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The current value of the pattern.
|
||||
* @memberOf Tone.Pattern#
|
||||
* @type {Time}
|
||||
* @name value
|
||||
*/
|
||||
Object.defineProperty(Tone.Pattern.prototype, "value", {
|
||||
get : function(){
|
||||
return this._pattern.value;
|
||||
},
|
||||
set : function(val){
|
||||
this._pattern.value = val;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The pattern type.
|
||||
* "up" - cycles upward
|
||||
* "down" - cycles downward
|
||||
* "upDown" - up then and down
|
||||
* "downUp" - cycles down then and up
|
||||
* "alternateUp" - jump up two and down one
|
||||
* "alternateDown" - jump down two and up one
|
||||
* "random" - randomly select an index
|
||||
* "randomWalk" - randomly moves one index away from the current position
|
||||
* "randomOnce" - randomly select an index without repeating until all values have been chosen.
|
||||
* @memberOf Tone.Pattern#
|
||||
* @type {Time}
|
||||
* @name pattern
|
||||
*/
|
||||
Object.defineProperty(Tone.Pattern.prototype, "pattern", {
|
||||
get : function(){
|
||||
return this._pattern.type;
|
||||
},
|
||||
set : function(pattern){
|
||||
this._pattern.type = pattern;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Clean up
|
||||
* @return {Tone.Pattern} this
|
||||
*/
|
||||
Tone.Pattern.prototype.dispose = function(){
|
||||
Tone.Loop.prototype.dispose.call(this);
|
||||
this._pattern.dispose();
|
||||
this._pattern = null;
|
||||
};
|
||||
|
||||
return Tone.Pattern;
|
||||
});
|
|
@ -1,161 +0,0 @@
|
|||
define(["Tone/core/Tone", "Tone/structure/Note", "Tone/structure/Part"], function (Tone) {
|
||||
|
||||
/**
|
||||
* @class Tone.Pattern arpeggiates between the given notes
|
||||
* in a number of patterns.
|
||||
* @extends {Tone}
|
||||
* @param {Function} callback The callback to invoke with the
|
||||
* event.
|
||||
* @param {Array} notes The notes to arpeggiate over.
|
||||
*/
|
||||
Tone.Pattern = function(callback, notes){
|
||||
|
||||
/**
|
||||
* Called back with the current event
|
||||
* @private
|
||||
* @type {Function}
|
||||
*/
|
||||
this._callback = callback;
|
||||
|
||||
/**
|
||||
* The notes to arpeggiate
|
||||
* @type {Array}
|
||||
*/
|
||||
this.notes = notes;
|
||||
|
||||
/**
|
||||
* The event index
|
||||
* @type {Array}
|
||||
* @private
|
||||
*/
|
||||
this._eventIndex = -1;
|
||||
|
||||
/**
|
||||
* The note which schedules the notes
|
||||
* @type {Tone.Note}
|
||||
* @private
|
||||
*/
|
||||
this._note = new Tone.Note(this._tick.bind(this));
|
||||
this._note.loop = true;
|
||||
this._note.loopEnd = "4n";
|
||||
|
||||
/**
|
||||
* The stepping direction of the notes
|
||||
* @type {Number}
|
||||
* @private
|
||||
*/
|
||||
this._arpDirection = 1;
|
||||
};
|
||||
|
||||
Tone.extend(Tone.Pattern);
|
||||
|
||||
/**
|
||||
* Start the arpeggio at the given time.
|
||||
* @param {Time=} time When to start the Arpeggio
|
||||
* @return {Tone.Pattern} this
|
||||
*/
|
||||
Tone.Pattern.prototype.start = function(time){
|
||||
this._note.start(time);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop the arpeggio at the given time.
|
||||
* @param {Time=} time When to stop the Arpeggio
|
||||
* @return {Tone.Pattern} this
|
||||
*/
|
||||
Tone.Pattern.prototype.stop = function(time){
|
||||
this._note.stop(time);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal function called when the notes should be called
|
||||
* @param {Number} time The time the event occurs
|
||||
* @private
|
||||
*/
|
||||
Tone.Pattern.prototype._tick = function(time){
|
||||
if (this._pattern === Tone.Pattern.Type.Random){
|
||||
this._eventIndex = Math.floor(Math.random() * this.notes.length);
|
||||
} else {
|
||||
this._eventIndex += this._arpDirection;
|
||||
if (this._pattern === Tone.Pattern.Type.Alternate){
|
||||
if (this._eventIndex === 0){
|
||||
this._arpDirection = 1;
|
||||
} else if (this._eventIndex === this.notes.length - 1){
|
||||
this._arpDirection = -1;
|
||||
}
|
||||
} else if (this._eventIndex < 0){
|
||||
this._eventIndex = this.notes.length - 1;
|
||||
} else if (this._eventIndex >= this.notes.length){
|
||||
this._eventIndex = 0;
|
||||
}
|
||||
}
|
||||
this._callback(time, this.notes[this._eventIndex]);
|
||||
};
|
||||
|
||||
/**
|
||||
* The interval of the notes
|
||||
* @memberOf Tone.Pattern#
|
||||
* @type {Time}
|
||||
* @name interval
|
||||
*/
|
||||
Object.defineProperty(Tone.Pattern.prototype, "interval", {
|
||||
get : function(){
|
||||
return this._note.loopEnd;
|
||||
},
|
||||
set : function(interval){
|
||||
this._note.loopEnd = interval;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @memberOf Tone.Pattern#
|
||||
* @type {Time}
|
||||
* @name pattern
|
||||
*/
|
||||
Object.defineProperty(Tone.Pattern.prototype, "pattern", {
|
||||
get : function(){
|
||||
return this._pattern;
|
||||
},
|
||||
set : function(pattern){
|
||||
switch(pattern){
|
||||
case Tone.Pattern.Type.Forward :
|
||||
this._arpDirection = 1;
|
||||
break;
|
||||
case Tone.Pattern.Type.Reverse :
|
||||
this._arpDirection = -1;
|
||||
break;
|
||||
}
|
||||
var hasType = false;
|
||||
for (var pattr in Tone.Pattern.Type){
|
||||
if (pattern === Tone.Pattern.Type[pattr]){
|
||||
hasType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasType){
|
||||
throw new Error("Invalid pattern: "+pattern);
|
||||
}
|
||||
this._pattern = pattern;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The arpeggiation patterns
|
||||
* @type {Object}
|
||||
* @enum {String}
|
||||
*/
|
||||
Tone.Pattern.Type = {
|
||||
Forward : "forward",
|
||||
Reverse : "reverse",
|
||||
Alternate : "alternate",
|
||||
Drunk : "drunk",
|
||||
Converge : "converge",
|
||||
Diverge : "diverge",
|
||||
RandomOnce : "randomOnce",
|
||||
Random : "random"
|
||||
};
|
||||
|
||||
return Tone.Pattern;
|
||||
});
|
Loading…
Reference in a new issue