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: Decode midi or piano roll to audio.
docstr_tok: ["Decode","midi","or","piano","roll","to","audio","."]
code: def midi_to_audio(
      self, q_pitch, q_vel, z=None, return_synth_params=False
  ):
      """Decode midi or piano roll to audio."""
      pg_in = self.midi_decoder(q_pitch, q_vel, z)
      midi_synth_params = self.processor_group.get_controls(pg_in)
      midi_audio = self.processor_group.get_signal(midi_synth_params)
  
      if return_synth_params:
          return midi_audio, midi_synth_params
      else:
          return midi_audio
  
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 10 for calling the MidiAutoencoder obj's underlying member method code with example usage: obj.midi_to_audio(q_pitch, q_vel, z, return_synth_params) and returns: midi_audio,  midi_synth_params, midi_audio