triggerAttack(unit, secondsFromNow) {
    var now = p5sound.audiocontext.currentTime;
    var tFromNow = secondsFromNow || 0;
    var t = now + tFromNow;
    this.lastAttack = t;
    this.wasTriggered = true;

    if (unit) {
      if (this.connection !== unit) {
        this.connect(unit);
      }
    }

    // get and set value (with linear ramp) to anchor automation
    var valToSet = this.control.getValueAtTime(t);

    if (this.isExponential === true) {
      this.control.exponentialRampToValueAtTime(
        this.checkExpInput(valToSet),
        t
      );
    } else {
      this.control.linearRampToValueAtTime(valToSet, t);
    }

    // after each ramp completes, cancel scheduled values
    // (so they can be overridden in case env has been re-triggered)
    // then, set current value (with linearRamp to avoid click)
    // then, schedule the next automation...

    // attack
    t += this.aTime;
    if (this.isExponential === true) {
      this.control.exponentialRampToValueAtTime(
        this.checkExpInput(this.aLevel),
        t
      );
      valToSet = this.checkExpInput(this.control.getValueAtTime(t));
      this.control.cancelScheduledValues(t);
      this.control.exponentialRampToValueAtTime(valToSet, t);
    } else {
      this.control.linearRampToValueAtTime(this.aLevel, t);
      valToSet = this.control.getValueAtTime(t);
      this.control.cancelScheduledValues(t);
      this.control.linearRampToValueAtTime(valToSet, t);
    }

    // decay to decay level (if using ADSR, then decay level == sustain level)
    t += this.dTime;
    if (this.isExponential === true) {
      this.control.exponentialRampToValueAtTime(
        this.checkExpInput(this.dLevel),
        t
      );
      valToSet = this.checkExpInput(this.control.getValueAtTime(t));
      this.control.cancelScheduledValues(t);
      this.control.exponentialRampToValueAtTime(valToSet, t);
    } else {
      this.control.linearRampToValueAtTime(this.dLevel, t);
      valToSet = this.control.getValueAtTime(t);
      this.control.cancelScheduledValues(t);
      this.control.linearRampToValueAtTime(valToSet, t);
    }
  }
Trigger the Attack, and Decay portion of the Envelope.
 Similar to holding down a key on a piano, but it will
 hold the sustain level until you let go. Input can be
 any p5.sound object, or a <a href="
 http://docs.webplatform.org/wiki/apis/webaudio/AudioParam">
 Web Audio Param</a>.

 @method  triggerAttack
 @for p5.Envelope
 @param  {Object} unit p5.sound Object or Web Audio Param
 @param  {Number} secondsFromNow time from now (in seconds)
 @example
 <div><code>
 let attackTime = 0.001;
 let decayTime = 0.2;
 let susPercent = 0.3;
 let releaseTime = 0.4;
 let env, triOsc;

 function setup() {
   let cnv = createCanvas(100, 100);
   background(220);
   textAlign(CENTER);
   textSize(10);
   text('tap to triggerAttack', width/2, height/2);

   env = new p5.Envelope();
   env.setADSR(attackTime, decayTime, susPercent, releaseTime);
   env.setRange(1.0, 0.0);
   triOsc = new p5.Oscillator('triangle');
   triOsc.freq(220);

   cnv.mousePressed(envAttack);
 }

 function envAttack()  {
   background(0, 255, 255);
   text('release to release', width/2, height/2);

   // ensures audio is enabled. See also: `userStartAudio`
   triOsc.start();

   env.triggerAttack(triOsc);
 }

 function mouseReleased() {
   background(220);
   text('tap to triggerAttack', width/2, height/2);

   env.triggerRelease(triOsc);
 }
 </code></div>