code: def run(logdir, run_name, wave_name, wave_constructor):
      """Generate wave data of the given form.
  
      The provided function `wave_constructor` should accept a scalar tensor
      of type float32, representing the frequency (in Hz) at which to
      construct a wave, and return a tensor of shape [1, _samples(), `n`]
      representing audio data (for some number of channels `n`).
  
      Waves will be generated at frequencies ranging from A4 to A5.
  
      Arguments:
        logdir: the top-level directory into which to write summary data
        run_name: the name of this run; will be created as a subdirectory
          under logdir
        wave_name: the name of the wave being generated
        wave_constructor: see above
      """
      tf.compat.v1.reset_default_graph()
      tf.compat.v1.set_random_seed(0)
  
      # On each step `i`, we'll set this placeholder to `i`. This allows us
      # to know "what time it is" at each step.
      step_placeholder = tf.compat.v1.placeholder(tf.float32, shape=[])
  
      # We want to linearly interpolate a frequency between A4 (440 Hz) and
      # A5 (880 Hz).
      with tf.name_scope("compute_frequency"):
          f_min = 440.0
          f_max = 880.0
          t = step_placeholder / (FLAGS.steps - 1)
          frequency = f_min * (1.0 - t) + f_max * t
  
      # Let's log this frequency, just so that we can make sure that it's as
      # expected.
      tf.compat.v1.summary.scalar("frequency", frequency)
  
      # Now, we pass this to the wave constructor to get our waveform. Doing
      # so within a name scope means that any summaries that the wave
      # constructor produces will be namespaced.
      with tf.name_scope(wave_name):
          waveform = wave_constructor(frequency)
  
      # We also have the opportunity to annotate each audio clip with a
      # label. This is a good place to include the frequency, because it'll
      # be visible immediately next to the audio clip.
      with tf.name_scope("compute_labels"):
          samples = tf.shape(input=waveform)[0]
          wave_types = tf.tile(
              ["*Wave type:* `%s`." % wave_name], [samples]
          )
          frequencies = tf.strings.join(
              [
                  "*Frequency:* ",
                  tf.tile(
                      [tf.as_string(frequency, precision=2)], [samples]
                  ),
                  " Hz.",
              ]
          )
          samples = tf.strings.join(
              [
                  "*Sample:* ",
                  tf.as_string(tf.range(samples) + 1),
                  " of ",
                  tf.as_string(samples),
                  ".",
              ]
          )
          labels = tf.strings.join(
              [wave_types, frequencies, samples], separator=" "
          )
  
      # We can place a description next to the summary in TensorBoard. This
      # is a good place to explain what the summary represents, methodology
      # for creating it, etc. Let's include the source code of the function
      # that generated the wave.
      source = "\n".join(
          "    %s" % line.rstrip()
          for line in inspect.getsourcelines(wave_constructor)[0]
      )
      description = "A wave of type `%r`, generated via:\n\n%s" % (
          wave_name,
          source,
      )
  
      # Here's the crucial piece: we interpret this result as audio.
      summary.op(
          "waveform",
          waveform,
          FLAGS.sample_rate,
          labels=labels,
          display_name=wave_name,
          description=description,
      )
  
      # Now, we can collect up all the summaries and begin the run.
      summ = tf.compat.v1.summary.merge_all()
  
      sess = tf.compat.v1.Session()
      writer = tf.compat.v1.summary.FileWriter(
          os.path.join(logdir, run_name)
      )
      writer.add_graph(sess.graph)
      sess.run(tf.compat.v1.global_variables_initializer())
      for step in range(FLAGS.steps):
          s = sess.run(summ, feed_dict={step_placeholder: float(step)})
          writer.add_summary(s, global_step=step)
      writer.close()
  
file_path: guildai/examples/tensorboard/audio.py
imports: import inspect
  import math
  import os.path
  from absl import app
  from absl import flags
  import tensorflow
  from tensorboard.plugins.audio import summary
label_desc: Use image node_id 2 for calling a global function with example usage: run(logdir, run_name, wave_name, wave_constructor) without return types