class_docstr: Helper object for computing CREPE-based f0 metrics.
  
  Note that batch operations are not possible when CREPE has viterbi argument
  set to True.
class_docstr_tok: ["Helper","object","for","computing","CREPE-based","f0","metrics",".","Note","that","batch","operations","are","not","possible","when","CREPE","has","viterbi","argument","set","to","True","."]
docstr: Update metrics based on a batch of audio.
  
  Args:
    batch: Dictionary of input features.
    audio_gen: Batch of generated audio.
docstr_tok: ["Update","metrics","based","on","a","batch","of","audio",".","Args",":","batch",":","Dictionary","of","input","features",".","audio_gen",":","Batch","of","generated","audio","."]
code: def update_state(self, batch, audio_gen):
      """Update metrics based on a batch of audio.
  
      Args:
        batch: Dictionary of input features.
        audio_gen: Batch of generated audio.
      """
      batch_size = int(audio_gen.shape[0])
      # Compute metrics per sample. No batch operations possible.
      for i in range(batch_size):
          # Extract f0 from generated audio example.
          f0_hz_gen, _ = ddsp.spectral_ops.compute_f0(
              audio_gen[i], frame_rate=self._frame_rate, viterbi=True
          )
          if "f0_hz" in batch and "f0_confidence" in batch:
              f0_hz_gt = batch["f0_hz"][i]
              f0_conf_gt = batch["f0_confidence"][i]
          else:
              # Missing f0 in ground truth, extract it.
              f0_hz_gt, f0_conf_gt = ddsp.spectral_ops.compute_f0(
                  batch["audio"][i],
                  frame_rate=self._frame_rate,
                  viterbi=True,
              )
  
          if is_outlier(f0_conf_gt):
              # Ground truth f0 was unreliable to begin with. Discard.
              f0_dist = None
          else:
              # Gound truth f0 was reliable, compute f0 distance with generated audio
              f0_dist = f0_dist_conf_thresh(
                  f0_hz_gt, f0_hz_gen, f0_conf_gt
              )
              if f0_dist is None or f0_dist > OUTLIER_MIDI_THRESH:
                  # Generated audio had untrackable pitch content or is an outlier.
                  self.metrics["outlier_ratio"].update_state(True, True)
                  logging.info(
                      "sample %d has untrackable pitch content", i
                  )
              else:
                  # Generated audio had trackable pitch content and is within tolerance
                  self.metrics["f0_dist"].update_state(f0_dist)
                  self.metrics["outlier_ratio"].update_state(
                      True, False
                  )
                  log_str = f"{self._name} | sample {i} | f0_dist(midi): {f0_dist:.3f}"
                  logging.info(log_str)
  
imports: import dataclasses
  from absl import logging
  import ddsp
  import librosa
  import mir_eval
  import note_seq
  from note_seq import sequences_lib
  import numpy
  import tensorflow.compat.v2
label_desc: Use image node_id 3 for calling the F0CrepeMetrics obj's underlying member method code with example usage: obj.update_state(batch, audio_gen) without return types