class_docstr: Autoencoder that has a MIDI representation at its bottleneck.
  
  Here is a crude diagram of the MidiAutoencoder architecture:
  
          MidiEncoder               MidiDecoder
                 +------> (MIDI) ------+
                 |                     |
                 |                     v
             (f0,amps,             (f0,amps,
              hd,noise)---+         hd,noise)
                 ^        |            |
      SynthCoder |        |            |
                 |        |            |
              (f0,Ld)     | DDSP       | DDSP
                 ^        | Synth      | Synth
           CREPE |        |            |
                 |        |            v
               Audio      +------->  Audio
               Input             Reconstruction
  
  The MidiAutoencoder has two "branches":
    - The Inner Branch or "SynthCoder" Branch. This is the path that
      goes from Audio Input, CREPE, SynthCoder, DDSP Synth, Audio
      Reconstruction in the diagram above.
      This branch has the same set up
      as the DDSP Autoencoder described in the original DDSP ICLR 2020 paper. It
      learns a parameterized encoding of the input audio (i.e., a harmonic
      disribution, noise coefficients, etc).
  
    - The Outer Branch. This path starts at the output of the SynthCoder, goes
      to the MidiEncoder, the MidiDecoder, to the DDSP Synth and to a (separate)
      Audio Reconstruction.
      This branch uses the parameterized audio output of
      the SynthCoder Branch as input to produce a MIDI-like representation of
      the audio. This is another autoencoder network with the MIDI at its center
      and outputs another set of parameterized audio features to reconstruct the
      input audio. The parts of this second autoencoder are referred to as the
      MIDI encoder and MIDI decoder, respectively.
  
  In essence, each of these branches is its own Autoencoder and they're stacked
  on top of each other such that the output of the Inner Branch is fed as
  input to the Outer Branch.
  
  This class defines a standard MidiAutoencoder w/ no bells and whistles. It
  uses a quantized 1D representation at the bottleneck to represent MIDI pitch.
  Further child classes (below) enhance this common functionality. This class
  acts as a base class for the other MidiAutoencoder variants.
docstr: Constructor.
  
  Args:
    synthcoder: Callable network that decodes f0, loudness, z to synth
      parameters (amplitude, noise magnitudes, and a harmonic distribution).
    midi_encoder: Callable network that will be used to create a MIDI-like
      latent.
    midi_decoder: Callable network that will turn the MIDI latent vector back
      into f0 and amplitude features.
    sg_before_midiae: Bool indicating whether a stop gradient will happen
      before the MIDI space autoencoder.
    reverb: Bool controlling whether reverb is added to the processor group.
    preprocessor: Module to preprocess the input batch.
    reconstruction_losses: LossGroup for any and all things that need to be
      reconstructed (synth_audio, f0, amps, hd, noise, f0, etc).
    qpitch_f0rec_loss: Margin loss obj between quantized pitch and f0
      reconstruction. Ignored if `None`.
    pitch_f0rec_loss: Margin loss obj between unquantized pitch and f0
      reconstruction. Ignored if `None`.
    pitch_qpitch_loss: L-norm loss obj between unquantized pitch and quantized
      pitch. Ignored if `None`.
    midi_slowness_loss: Callable loss object that computes how slow the latent
      space is. Ignored if `None`.
    mask_f0_loss: Ignore f0 reconstruction loss where f0 and MIDI are very
      different.
    **kwargs: Other kwargs for keras models including `name`.
docstr_tok: ["Constructor",".","Args",":","synthcoder",":","Callable","network","that","decodes","f0",",","loudness",",","z","to","synth","parameters","(","amplitude",",","noise","magnitudes",",","and","a","harmonic","distribution",")",".","midi_encoder",":","Callable","network","that","will","be","used","to","create","a","MIDI-like","latent",".","midi_decoder",":","Callable","network","that","will","turn","the","MIDI","latent","vector","back","into","f0","and","amplitude","features",".","sg_before_midiae",":","Bool","indicating","whether","a","stop","gradient","will","happen","before","the","MIDI","space","autoencoder",".","reverb",":","Bool","controlling","whether","reverb","is","added","to","the","processor","group",".","preprocessor",":","Module","to","preprocess","the","input","batch",".","reconstruction_losses",":","LossGroup","for","any","and","all","things","that","need","to","be","reconstructed","(","synth_audio",",","f0",",","amps",",","hd",",","noise",",","f0",",","etc",")",".","qpitch_f0rec_loss",":","Margin","loss","obj","between","quantized","pitch","and","f0","reconstruction",".","Ignored","if","`","None","`",".","pitch_f0rec_loss",":","Margin","loss","obj","between","unquantized","pitch","and","f0","reconstruction",".","Ignored","if","`","None","`",".","pitch_qpitch_loss",":","L-norm","loss","obj","between","unquantized","pitch","and","quantized","pitch",".","Ignored","if","`","None","`",".","midi_slowness_loss",":","Callable","loss","object","that","computes","how","slow","the","latent","space","is",".","Ignored","if","`","None","`",".","mask_f0_loss",":","Ignore","f0","reconstruction","loss","where","f0","and","MIDI","are","very","different",".","*","*","kwargs",":","Other","kwargs","for","keras","models","including","`","name","`","."]
code: def __init__(
      self,
      synthcoder=None,
      midi_encoder=None,
      midi_decoder=None,
      sg_before_midiae=True,
      reverb=True,
      preprocessor=None,
      reconstruction_losses=None,
      qpitch_f0rec_loss=None,
      pitch_f0rec_loss=None,
      pitch_qpitch_loss=None,
      midi_slowness_loss=None,
      mask_f0_loss=True,
      **kwargs,
  ):
      """Constructor.
  
      Args:
        synthcoder: Callable network that decodes f0, loudness, z to synth
          parameters (amplitude, noise magnitudes, and a harmonic distribution).
        midi_encoder: Callable network that will be used to create a MIDI-like
          latent.
        midi_decoder: Callable network that will turn the MIDI latent vector back
          into f0 and amplitude features.
        sg_before_midiae: Bool indicating whether a stop gradient will happen
          before the MIDI space autoencoder.
        reverb: Bool controlling whether reverb is added to the processor group.
        preprocessor: Module to preprocess the input batch.
        reconstruction_losses: LossGroup for any and all things that need to be
          reconstructed (synth_audio, f0, amps, hd, noise, f0, etc).
        qpitch_f0rec_loss: Margin loss obj between quantized pitch and f0
          reconstruction. Ignored if `None`.
        pitch_f0rec_loss: Margin loss obj between unquantized pitch and f0
          reconstruction. Ignored if `None`.
        pitch_qpitch_loss: L-norm loss obj between unquantized pitch and quantized
          pitch. Ignored if `None`.
        midi_slowness_loss: Callable loss object that computes how slow the latent
          space is. Ignored if `None`.
        mask_f0_loss: Ignore f0 reconstruction loss where f0 and MIDI are very
          different.
        **kwargs: Other kwargs for keras models including `name`.
      """
      super().__init__(**kwargs)
  
      # Network objects
      self.synthcoder = synthcoder
      self.midi_encoder = midi_encoder
      self.midi_decoder = midi_decoder
  
      # Reconstruction Loss functions
      self.reconstruction_losses = reconstruction_losses
      self.mask_f0_loss = mask_f0_loss
  
      # Closeness and slowness losses
      self.qpitch_f0rec_loss = qpitch_f0rec_loss
      self.pitch_f0rec_loss = pitch_f0rec_loss
      self.pitch_qpitch_loss = pitch_qpitch_loss
      self.slowness_loss = midi_slowness_loss
  
      # Options for training
      self.sg_before_midiae = sg_before_midiae
  
      # Pre & post processing
      self.preprocessor = preprocessor
      if isinstance(
          self.preprocessor, preprocessing.F0PowerPreprocessor
      ):
          self.db_key = "power_db"
      else:
          self.db_key = "loudness_db"
  
      # Explicitly define the DAG & Processor Group
      harmonic_synth = ddsp.synths.Harmonic()
      noise = ddsp.synths.FilteredNoise()
      add = ddsp.processors.Add()
  
      dag = [
          (
              harmonic_synth,
              ["amplitudes", "harmonic_distribution", "f0_hz"],
          ),
          (noise, ["magnitudes"]),
          (add, ["filtered_noise/signal", "harmonic/signal"]),
      ]
  
      if reverb:
          reverb_module = ddsp.effects.FilteredNoiseReverb(
              trainable=True,
              reverb_length=24000,
              n_frames=500,
              n_filter_banks=32,
              name="reverb",
          )
          dag.append(((reverb_module), ["add/signal"]))
  
      self.processor_group = ddsp.processors.ProcessorGroup(dag=dag)
  
imports: import ddsp
  from ddsp.training import nn
  from ddsp.training import preprocessing
  from ddsp.training.models.model import Model
  import tensorflow
label_desc: Use image node_id 1 to create a new MidiAutoencoder object from inherited base classes: Model with example: obj = MidiAutoencoder(synthcoder, midi_encoder, midi_decoder, sg_before_midiae, reverb, preprocessor, reconstruction_losses, qpitch_f0rec_loss, pitch_f0rec_loss, pitch_qpitch_loss, midi_slowness_loss, mask_f0_loss)