plugins/envelopes.cracked.js

/**
 * Attack Decay Sustain Release envelope
 *
 * [See more adsr examples](examples/envelopes.html)
 *
 * Attack time is the time taken for initial run-up of level from nil to peak, beginning when the key is first pressed.
 * Decay time is the time taken for the subsequent run down from the attack level to the designated sustain level.
 * Sustain level is the level during the main sequence of the sound's duration, until the key is released.
 * Release time is the time taken for the level to decay from the sustain level to zero after the key is released.
 *
 * @plugin
 * @category Envelope
 * @function
 * @memberof cracked
 * @name cracked#adsr
 * @param {Array} [userParams] 5 values: attack,decay,sustain,hold,release
 * @param {Array}  [userParams] 4 values: attack,decay,sustain,release
 * @param {Array} [userParams] 3 values: attack,decay,sustain (holds until released)
 * @param {String} [userParams] "slow" or "fast"
 * @param {Number} [userParams=0.5] length of the total envelope
 */
cracked.adsr = function (userParams) {
    var methods = {
        init: function (options) {

            options = options || {};

            options = __.isNum(options) ||
                __.isArr(options) ||
                __.isStr(options) ? {envelope: options} : options;

            __.begin("adsr", options).gain({

                gain: 0

            }).end("adsr");

        },
        trigger: function (params) {
            cracked.each("adsr", function (el, i, arr) {
                var p = makeEnv(params, el.getParams().settings.envelope);
                //options = attack,decay,sustain,hold,release
                el.ramp(
                    [1, p[2], p[2], 0],
                    [p[0], p[1], p[3], p[4]],
                    "gain",
                    null,
                    0
                );
            });
        },
        release: function (time) {
            time = __.ifUndef(time,0);
            cracked.each("adsr", function (el, i, arr) {
                    el.ramp(0, time, "gain");
            });
        }
    };

    if (methods[userParams]) {
        methods[userParams].apply(this, Array.prototype.slice.call(arguments, 1));
    } else {
        methods.init(userParams);
    }

    function makeEnv(userParams, nodeParams) {

        //user params take precedence over the ones stored in the node
        var args = userParams || nodeParams;

        //trigger arguments :
        //an array of 5 values [attack,decay,sustain,hold,release]
        //or 4 values [attack,decay,sustain,release] ()
        //or a one number specifying the total length of the envelope
        //or a string (either "fast" or "slow") to specify the length
        //tbd - add a proper default

        var p = [0, 0, 0, 0, 0],
            segment,
            options = args || 0.5;

        if (__.isArr(options)) {
            if (options.length === 5) {
                p = options;
            } else if (options.length === 4) {
                var sum = options[0] + options[1] + options[3];
                p = [options[0], options[1], options[2], (sum / 3), options[3]];
            } else if (options.length === 3) {
                //a,d,s, hold for two hours, r = 0
                p = [options[0], options[1], options[2], 7200, 0];
            }

        } else if (__.isNum(options)) {
            segment = options / 4;
            p = [segment, segment, 0.5, segment, segment];
        } else if (__.isStr(options)) {
            if (options === "slow") {
                options = 1;
            } else if (options === "fast") {
                options = 0.25;
            } else {
                options = 0.5;
            }
            segment = options / 4;
            p = [segment, segment, 0.5, segment, segment];
        }
        return p;
    }

    return cracked;
};