noteAttack(_note, _velocity, secondsFromNow = 0) {
    //this value is used by this._voicesInUse
    var acTime = p5sound.audiocontext.currentTime + secondsFromNow;

    //Convert note to frequency if necessary. This is because entries into this.notes
    //should be based on frequency for the sake of consistency.
    var note = noteToFreq(_note);
    var velocity = _velocity || 0.1;

    var currentVoice;

    //Release the note if it is already playing
    if (this.notes[note] && this.notes[note].getValueAtTime(acTime) !== null) {
      this.noteRelease(note, 0);
    }

    //Check to see how many voices are in use at the time the note will start
    if (this._voicesInUse.getValueAtTime(acTime) < this.maxVoices) {
      currentVoice = Math.max(~~this._voicesInUse.getValueAtTime(acTime), 0);
    }
    //If we are exceeding the polyvalue, bump off the oldest notes and replace
    //with a new note
    else {
      currentVoice = this._oldest;

      let oldestNote = this.audiovoices[this._oldest].oscillator.freq().value;
      this.noteRelease(oldestNote);
      this._oldest = (this._oldest + 1) % (this.maxVoices - 1);
    }

    //Overrite the entry in the notes object. A note (frequency value)
    //corresponds to the index of the audiovoice that is playing it
    this.notes[note] = new TimelineSignal();
    this.notes[note].setValueAtTime(currentVoice, acTime);

    //Find the scheduled change in this._voicesInUse that will be previous to this new note
    //Add 1 and schedule this value at time 't', when this note will start playing
    var previousVal =
      this._voicesInUse._searchBefore(acTime) === null
        ? 0
        : this._voicesInUse._searchBefore(acTime).value;
    this._voicesInUse.setValueAtTime(previousVal + 1, acTime);

    //Then update all scheduled values that follow to increase by 1
    this._updateAfter(acTime, 1);

    this._newest = currentVoice;
    //The audiovoice handles the actual scheduling of the note
    if (typeof velocity === 'number') {
      var maxRange = (1 / this._voicesInUse.getValueAtTime(acTime)) * 2;
      velocity = velocity > maxRange ? maxRange : velocity;
    }

    // use secondsFromNow because this method will add AudioContext currentTime
    this.audiovoices[currentVoice].triggerAttack(
      note,
      velocity,
      secondsFromNow
    );
  }
Trigger the Attack, and Decay portion of a MonoSynth.
 Similar to holding down a key on a piano, but it will
 hold the sustain level until you let go.

 @method  noteAttack
 @for p5.PolySynth
 @param  {Number} [note]           midi note on which attack should be triggered.
 @param  {Number} [velocity]       velocity of the note to play (ranging from 0 to 1)/
 @param  {Number} [secondsFromNow] time from now (in seconds)
 @example
 <div><code>
 let polySynth = new p5.PolySynth();
 let pitches = ['G', 'D', 'G', 'C'];
 let octaves = [2, 3, 4];

 function setup() {
   let cnv = createCanvas(100, 100);
   cnv.mousePressed(playChord);
   background(220);
   text('tap to play', 20, 20);
 }

 function playChord() {
   userStartAudio();

   // play a chord: multiple notes at the same time
   for (let i = 0; i < 4; i++) {
     let note = random(pitches) + random(octaves);
     polySynth.noteAttack(note, 0.1);
   }
 }

 function mouseReleased() {
   // release all voices
   polySynth.noteRelease();
 }
 </code></div>