class_docstr: An implementation of a classic Denoising Diffusion Probabilistic Model (DDPM)
  
  Arguments
  ---------
  model: nn.Module
      the underlying model
  
  timesteps: int
      the number of timesteps
  
  noise: str|nn.Module
      the type of noise being used
      "gaussian" will produce standard Gaussian noise
  
  
  beta_start: float
      the value of the "beta" parameter at the beginning at the end of the process
      (see the paper)
  
  beta_end: float
      the value of the "beta" parameter at the end of the process
  
  show_progress: bool
      whether to show progress during inference
  
  Example
  -------
  >>> from speechbrain.nnet.unet import UNetModel
  >>> unet = UNetModel(
  ...     in_channels=1,
  ...     model_channels=16,
  ...     norm_num_groups=4,
  ...     out_channels=1,
  ...     num_res_blocks=1,
  ...     attention_resolutions=[]
  ... )
  >>> diff = DenoisingDiffusion(
  ...     model=unet,
  ...     timesteps=5
  ... )
  >>> x = torch.randn(4, 1, 64, 64)
  >>> pred, noise, noisy_sample = diff.train_sample(x)
  >>> pred.shape
  torch.Size([4, 1, 64, 64])
  >>> noise.shape
  torch.Size([4, 1, 64, 64])
  >>> noisy_sample.shape
  torch.Size([4, 1, 64, 64])
  >>> sample = diff.sample((2, 1, 64, 64))
  >>> sample.shape
  torch.Size([2, 1, 64, 64])
docstr: Adds noise to the sample, in a forward diffusion process,
  
  Arguments
  ---------
  x: torch.Tensor
      a data sample of 2 or more dimensions, with the
      first dimension representing the batch
  noise: torch.Tensor
      the noise to add
  timesteps: torch.Tensor
      a 1-D integer tensor of a length equal to the number of
      batches in x, where each entry corresponds to the timestep
      number for the batch. If omitted, timesteps will be randomly
      sampled
  
  Returns
  -------
  result: torch.Tensor
      a tensor of the same dimension as x
code: def distort(self, x, noise=None, timesteps=None, **kwargs):
      """Adds noise to the sample, in a forward diffusion process,
  
      Arguments
      ---------
      x: torch.Tensor
          a data sample of 2 or more dimensions, with the
          first dimension representing the batch
      noise: torch.Tensor
          the noise to add
      timesteps: torch.Tensor
          a 1-D integer tensor of a length equal to the number of
          batches in x, where each entry corresponds to the timestep
          number for the batch. If omitted, timesteps will be randomly
          sampled
  
      Returns
      -------
      result: torch.Tensor
          a tensor of the same dimension as x
      """
      if timesteps is None:
          timesteps = sample_timesteps(x, self.timesteps)
      if noise is None:
          noise = self.noise(x, **kwargs)
      signal_coefficients = self.signal_coefficients[timesteps]
      noise_coefficients = self.noise_coefficients[timesteps]
      noisy_sample = (
          unsqueeze_as(signal_coefficients, x) * x
          + unsqueeze_as(noise_coefficients, noise) * noise
      )
      return noisy_sample, noise
  
imports: from collections import namedtuple
  import torch
  from torch import nn
  from torch.nn import functional
  from tqdm.auto import tqdm
  from speechbrain.utils.data_utils import unsqueeze_as
  from speechbrain.dataio.dataio import length_to_mask
  from speechbrain.utils import data_utils
label_desc: Use image node_id 3 for calling the DenoisingDiffusion obj's underlying member method code with example usage: obj.distort(x, noise, timesteps) and returns: noisy_sample,  noise