class_docstr: Add SNR noise [-1, 1]
code: def __call__(self, signal):
      assert signal.dtype in [
          np.float32,
          np.float64,
      ], "signal only supports float32 data type"
      snr_target = (
          random.choice(self.snr_levels)
          if not self.snr_target
          else self.snr_target
      )
      if snr_target == 9999:
          return signal
      else:
          # -- get noise
          start_idx = random.randint(0, len(self.noise) - len(signal))
          noise_clip = self.noise[start_idx : start_idx + len(signal)]
          sig_power = self.get_power(signal)
          noise_clip_power = self.get_power(noise_clip)
          factor = (sig_power / noise_clip_power) / (
              10 ** (snr_target / 10.0)
          )
          desired_signal = (
              signal + noise_clip * np.sqrt(factor)
          ).astype(np.float32)
          if random.random() < 0.5:
              max_len = len(desired_signal) // 8
              start_idx = random.sample(range(len(desired_signal)), k=4)
              length = random.choices(range(max_len), k=4)
              for i in range(4):
                  desired_signal[
                      start_idx[i] : start_idx[i] + length[i]
                  ] = 0
              return desired_signal
          else:
              return desired_signal
  
imports: import random
  import cv2
  import numpy
  import torch
  from scipy import signal
label_desc: Use image node_id 3 for calling the AddNoise obj's underlying member method code with example usage: obj.__call__(signal) and returns: signal, desired_signal, desired_signal