class_docstr: Track the notes with an HMM based on a model of attack, decay, sustain,
  release (ADSR) envelopes.
  
  Parameters
  ----------
  onset_prob : float, optional
      Transition probability to enter an onset state.
  note_prob : float, optional
      Transition probability to enter a sounding note state.
  offset_prob : float, optional
      Transition probability to enter an offset state.
  attack_length : float, optional
      Minimum required attack (i.e. onset activation required) length.
  decay_length : float, optional
      Minimum required decay (i.e. note activation required) length.
  release_length : float, optional
      Minimum required release (i.e. note activation required) length.
  complete : bool, optional
      Require notes to transition all states (i.e. discard incomplete notes).
  onset_threshold : float, optional
      Require notes to have an onset activation greater or equal this
      threshold.
  note_threshold : float, optional
      Require notes to have a note activation greater equal this threshold.
  fps : float, optional
      Frames per second.
  pitch_offset : int, optional
      Pitch offset for the detected notes.
  
  References
  ----------
  
  .. [1] Rainer Kelz, Sebastian Böck and Gerhard Widmer,
         "Deep Polyphonic ADSR Piano Note Transcription",
         Proceedings of the 44th International Conference on Acoustics,
         Speech and Signal Processing (ICASSP), 2019.
  
  Examples
  --------
  Create a CNNPianoNoteProcessor and pass a file through the processor
  to obtain a note activation function (sampled with 50 frames per second).
  
  >>> proc = CNNPianoNoteProcessor()
  >>> act = proc('tests/data/audio/stereo_sample.wav')
  
  Track the notes by means on ADSR note tracking:
  >>> adsr = ADSRNoteTrackingProcessor()
  >>> adsr(act)  # doctest: +NORMALIZE_WHITESPACE
  array([[ 0.12, 72. , 1.44],
         [ 1.54, 41. , 1.84],
         [ 2.5 , 77. , 1.  ],
         [ 2.52, 65. , 0.96],
         [ 2.54, 60. , 0.82],
         [ 2.58, 56. , 0.82],
         [ 3.34, 75. , 0.82],
         [ 3.42, 43. , 0.74]])
code: def __init__(
      self,
      onset_prob=0.8,
      note_prob=0.8,
      offset_prob=0.5,
      attack_length=0.04,
      decay_length=0.04,
      release_length=0.02,
      complete=True,
      onset_threshold=0.5,
      note_threshold=0.5,
      fps=50,
      pitch_offset=21,
      **kwargs,
  ):
      from .notes_hmm import (
          ADSRStateSpace,
          ADSRTransitionModel,
          ADSRObservationModel,
      )
      from ..ml.hmm import HiddenMarkovModel
  
      # state space
      self.st = ADSRStateSpace(
          attack_length=int(attack_length * fps),
          decay_length=int(decay_length * fps),
          release_length=int(release_length * fps),
      )
      # transition model
      self.tm = ADSRTransitionModel(
          self.st,
          onset_prob=onset_prob,
          note_prob=note_prob,
          offset_prob=offset_prob,
      )
      # observation model
      self.om = ADSRObservationModel(self.st)
      # instantiate a HMM
      self.hmm = HiddenMarkovModel(self.tm, self.om, None)
      # save variables
      self.complete = complete
      self.onset_threshold = onset_threshold
      self.note_threshold = note_threshold
      self.pitch_offset = pitch_offset
      self.fps = fps
  
imports: from __future__ import absolute_import, division, print_function
  import numpy
  from .onsets import OnsetPeakPickingProcessor, peak_picking
  from ..processors import ParallelProcessor, Processor, SequentialProcessor
  from ..utils import combine_events
label_desc: Use image node_id 1 to create a new ADSRNoteTrackingProcessor object from inherited base classes: Processor with example: obj = ADSRNoteTrackingProcessor(onset_prob, note_prob, offset_prob, attack_length, decay_length, release_length, complete, onset_threshold, note_threshold, fps, pitch_offset)