class_docstr: Definition of sine generator
  SineGen(samp_rate, harmonic_num = 0,
          sine_amp = 0.1, noise_std = 0.003,
          voiced_threshold = 0,
          flag_for_pulse=False)
  
  sample_rate: sampling rate in Hz
  harmonic_num: number of harmonic overtones (default 0)
  sine_amp: amplitude of sine-wavefrom (default 0.1)
  noise_std: std of Gaussian noise (default 0.003)
  voiced_thoreshold: F0 threshold for U/V classification (default 0)
  flag_for_pulse: this SinGen is used inside PulseGen (default False)
  
  Note: when flag_for_pulse is True, the first time step of a voiced
      segment is always sin(np.pi) or cos(0)
docstr: sine_tensor, uv = forward(f0)
  input F0: tensor(batchsize=1, length, dim=1)
            f0 for unvoiced steps should be 0
  output sine_tensor: tensor(batchsize=1, length, dim)
  output uv: tensor(batchsize=1, length, 1)
docstr_tok: ["sine_tensor",",","uv","=","forward","(","f0",")","input","F0",":","tensor","(","batchsize=1",",","length",",","dim=1",")","f0","for","unvoiced","steps","should","be","0","output","sine_tensor",":","tensor","(","batchsize=1",",","length",",","dim",")","output","uv",":","tensor","(","batchsize=1",",","length",",","1",")"]
code: def forward(self, f0):
      """sine_tensor, uv = forward(f0)
      input F0: tensor(batchsize=1, length, dim=1)
                f0 for unvoiced steps should be 0
      output sine_tensor: tensor(batchsize=1, length, dim)
      output uv: tensor(batchsize=1, length, 1)
      """
      with torch.no_grad():
          f0_buf = torch.zeros(
              f0.shape[0], f0.shape[1], self.dim, device=f0.device
          )
          # print("f0_buf", f0_buf.shape)
          # print("f0", f0.shape)
          # fundamental component
          f0_buf[:, :, 0] = f0[:, :, 0]
          for idx in np.arange(self.harmonic_num):
              # idx + 2: the (idx+1)-th overtone, (idx+2)-th harmonic
              f0_buf[:, :, idx + 1] = f0_buf[:, :, 0] * (idx + 2)
  
          # generate sine waveforms
          sine_waves = self._f02sine(f0_buf) * self.sine_amp
  
          # generate uv signal
          # uv = torch.ones(f0.shape)
          # uv = uv * (f0 > self.voiced_threshold)
          uv = self._f02uv(f0)
  
          # noise: for unvoiced should be similar to sine_amp
          #        std = self.sine_amp/3 -> max value ~ self.sine_amp
          # .       for voiced regions is self.noise_std
          noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
          noise = noise_amp * torch.randn_like(sine_waves)
  
          # first: set the unvoiced part to 0 by uv
          # then: additive noise
          sine_waves = sine_waves * uv + noise
      return sine_waves, uv, noise
  
imports: import numpy
  import torch
label_desc: Use image node_id 4 for calling the SineGen obj's underlying member method code with example usage: obj.forward(f0) and returns: sine_waves,  uv,  noise