code: def build_audio(is_clean, params, index, audio_samples_length=-1):
      """Construct an audio signal from source files"""
  
      fs_output = params["fs"]
      silence_length = params["silence_length"]
      if audio_samples_length == -1:
          audio_samples_length = int(
              params["audio_length"] * params["fs"]
          )
  
      output_audio = np.zeros(0)
      remaining_length = audio_samples_length
      files_used = []
      clipped_files = []
  
      if is_clean:
          data_iterator = iter(params["clean_data"])
          idx = index
      else:
          data_iterator = iter(params["noise_data"])
          idx = index
  
      # initialize silence
      silence = np.zeros(int(fs_output * silence_length))
  
      # iterate through multiple clips until we have a long enough signal
      tries_left = MAXTRIES
      while remaining_length > 0 and tries_left > 0:
          # read next audio file and resample if necessary
          fs_input = params["fs_input"]
          batch = next(data_iterator)
          input_audio = batch["sig"].numpy()
  
          if input_audio is None:
              sys.stderr.write(
                  "\nWARNING: Cannot read file: %s\n" % batch["__key__"]
              )
              continue
          if fs_input != fs_output:
              input_audio = librosa.resample(
                  input_audio, orig_sr=fs_input, target_sr=fs_output
              )
  
          # if current file is longer than remaining desired length, and this is
          # noise generation or this is training set, subsample it randomly
          if len(input_audio) > remaining_length and (
              not is_clean or not params["is_test_set"]
          ):
              idx_seg = np.random.randint(
                  0, len(input_audio) - remaining_length
              )
              input_audio = input_audio[
                  idx_seg : idx_seg + remaining_length
              ]
  
          # check for clipping, and if found move onto next file
          if is_clipped(input_audio):
              clipped_files.append(batch["__key__"])
              tries_left -= 1
              continue
  
          # concatenate current input audio to output audio stream
          files_used.append(batch["__key__"])
          output_audio = np.append(output_audio, input_audio)
          remaining_length -= len(input_audio)
  
          # add some silence if we have not reached desired audio length
          if remaining_length > 0:
              silence_len = min(remaining_length, len(silence))
              output_audio = np.append(
                  output_audio, silence[:silence_len]
              )
              remaining_length -= silence_len
  
      if (
          tries_left == 0
          and not is_clean
          and "noise_data" in params.keys()
      ):
          print(
              "There are not enough non-clipped files in the "
              + "given noise directory to complete the audio build"
          )
          return [], [], clipped_files, idx
  
      return output_audio, files_used, clipped_files, idx
  
imports: import sys
  import os
  from pathlib import Path
  import random
  import time
  import numpy
  from scipy import signal
  from scipy.io import wavfile
  import librosa
  import utils
  from audiolib import segmental_snr_mixer, activitydetector, is_clipped
  import pandas
  import json
  from functools import partial
  from typing import Dict
  from collections import defaultdict
  import speechbrain
  import webdataset
  from hyperpyyaml import load_hyperpyyaml
  import torch
label_desc: Use image node_id 2 for calling a global function with example usage: build_audio(is_clean, params, index, audio_samples_length) and returns: output_audio,  files_used,  clipped_files,  idx, list,  list,  clipped_files,  idx