Tone.js/Tone/instrument/MultiSampler.js
2014-12-03 17:25:34 -05:00

150 lines
4 KiB
JavaScript

define(["Tone/core/Tone", "Tone/instrument/Sampler", "Tone/instrument/Instrument"],
function(Tone){
"use strict";
/**
* @class Aggregates multiple Tone.Samplers into a single instrument.
* Pass in a mapping of names to sample urls and an optional
* callback to invoke when all of the samples are loaded.
*
* ```javascript
* var sampler = new Tone.MultiSampler({
* "kick" : "../audio/BD.mp3",
* "snare" : "../audio/SD.mp3",
* "hat" : "../audio/hh.mp3"
* }, onload);
* //once loaded...
* sampler.triggerAttack("kick");
* ```
*
* @constructor
* @extends {Tone.Instrument}
* @param {Object} samples the samples used in this
* @param {function} onload the callback to invoke when all
* of the samples have been loaded
*/
Tone.MultiSampler = function(samples, onload){
Tone.Instrument.call(this);
/**
* the array of voices
* @type {Tone.Sampler}
*/
this.samples = {};
//make the samples
this._createSamples(samples, onload);
};
Tone.extend(Tone.MultiSampler, Tone.Instrument);
/**
* creates all of the samples and tracks their loading
*
* @param {Object} samples the samples
* @param {function} onload the onload callback
* @private
*/
Tone.MultiSampler.prototype._createSamples = function(samples, onload){
//object which tracks the number of loaded samples
var loadCounter = {
total : 0,
loaded : 0
};
//get the count
for (var s in samples){ //jshint ignore:line
loadCounter.total++;
}
//the function to invoke when a sample is loaded
var onSampleLoad = function(){
loadCounter.loaded++;
if (loadCounter.loaded === loadCounter.total){
if (onload){
onload();
}
}
};
for (var samp in samples){
var url = samples[samp];
var sampler = new Tone.Sampler(url, onSampleLoad);
sampler.connect(this.output);
this.samples[samp] = sampler;
}
};
/**
* start a sample
*
* @param {string} sample the note name to start
* @param {Tone.Time} [time=now] the time when the note should start
* @param {number} [velocity=1] the velocity of the note
*/
Tone.MultiSampler.prototype.triggerAttack = function(sample, time, velocity){
if (this.samples.hasOwnProperty(sample)){
this.samples[sample].triggerAttack(0, time, velocity);
}
};
/**
* start the release portion of the note
*
* @param {string} sample the note name to release
* @param {Tone.Time} [time=now] the time when the note should release
*/
Tone.MultiSampler.prototype.triggerRelease = function(sample, time){
if (this.samples.hasOwnProperty(sample)){
this.samples[sample].triggerRelease(time);
}
};
/**
* start the release portion of the note
*
* @param {string} sample the note name to release
* @param {Tone.Time} duration the duration of the note
* @param {Tone.Time} [time=now] the time when the note should start
* @param {number} [velocity=1] the velocity of the note
*/
Tone.MultiSampler.prototype.triggerAttackRelease = function(sample, duration, time, velocity){
if (this.samples.hasOwnProperty(sample)){
time = this.toSeconds(time);
duration = this.toSeconds(duration);
var samp = this.samples[sample];
samp.triggerAttack(0, time, velocity);
samp.triggerRelease(time + duration);
}
};
/**
* sets all the samplers with these settings
* @param {object} params the parameters to be applied
* to all internal samplers
*/
Tone.MultiSampler.prototype.set = function(params){
for (var samp in this.samples){
this.samples[samp].set(params);
}
};
/**
* set volume method borrowed form {@link Tone.Source}
* @function
*/
Tone.MultiSampler.prototype.setVolume = Tone.Source.prototype.setVolume;
/**
* clean up
*/
Tone.MultiSampler.prototype.dispose = function(){
Tone.Instrument.prototype.dispose.call(this);
for (var samp in this.samples){
this.samples[samp].dispose();
this.samples[samp] = null;
}
this.samples = null;
};
return Tone.MultiSampler;
});