docstr: Forward computations from the mixture to the separated signals.
docstr_tok: ["Forward","computations","from","the","mixture","to","the","separated","signals","."]
code: def compute_forward(self, mix, targets, stage, noise=None):
      """Forward computations from the mixture to the separated signals."""
  
      # Unpack lists and put tensors in the right device
      mix, mix_lens = mix
      mix, mix_lens = mix.to(self.device), mix_lens.to(self.device)
  
      # Convert targets to tensor
      targets = torch.cat(
          [
              targets[i][0].unsqueeze(-1)
              for i in range(self.hparams.num_spks)
          ],
          dim=-1,
      ).to(self.device)
      # [1,t,2,2] dim = -1 is num_speakers
  
      # Add speech distortions
      if stage == sb.Stage.TRAIN:
          with torch.no_grad():
              if (
                  self.hparams.use_speedperturb
                  or self.hparams.use_rand_shift
              ):
                  mix, targets = self.add_speed_perturb(
                      targets, mix_lens
                  )
  
                  mix = targets.sum(-1)
                  if "noise" in self.hparams.experiment_name:
                      noise = noise.to(self.device)
                      len_noise = noise.shape[1]
                      len_mix = mix.shape[1]
                      min_len = min(len_noise, len_mix)
  
                      # add the noise
                      if noise.ndim == 2:
                          noise = noise.unsqueeze(-1)
                      mix = mix[:, :min_len] + noise[:, :min_len]
  
                      # fix the length of targets also
                      targets = targets[:, :min_len, :]
  
              if self.hparams.use_wavedrop:
                  mix = self.hparams.drop_chunk(mix, mix_lens)
                  mix = self.hparams.drop_freq(mix)
  
              if self.hparams.limit_training_signal_len:
                  mix, targets = self.cut_signals(mix, targets)
  
      # Separation
      if "independent" in self.hparams.experiment_name:
          mix_wl = self.hparams.EncoderL(mix[:, :, 0])
          est_maskl = self.hparams.MaskNetL(mix_wl)
          mix_wl = torch.stack([mix_wl] * self.hparams.num_spks)
          sep_hl = mix_wl * est_maskl
  
          mix_wr = self.hparams.EncoderR(mix[:, :, 1])
          est_maskr = self.hparams.MaskNetR(mix_wr)
          mix_wr = torch.stack([mix_wr] * self.hparams.num_spks)
          sep_hr = mix_wr * est_maskr
      elif "cross" in self.hparams.experiment_name:
          EPS = 1e-8
          compute_stft = STFT(
              sample_rate=self.hparams.sample_rate,
              win_length=256 * 1000.0 / self.hparams.sample_rate,
              hop_length=128 * 1000.0 / self.hparams.sample_rate,
              n_fft=256,
          ).to(self.device)
          mix_stft = compute_stft(mix).permute(-1, 0, 2, 1, 3)
          # IPD = torch.atan2(mix_stft[:, :, :, :, 1], mix_stft[:, :, :, :, 0])
          # sinIPD = torch.sin(IPD[0] - IPD[1])
          # cosIPD = torch.cos(IPD[0] - IPD[1])
          ILD_beforelog = spectral_magnitude(mix_stft[0], power=0.5) / (
              spectral_magnitude(mix_stft[1], power=0.5) + EPS
          )
          ILD = 10 * torch.log10(ILD_beforelog + EPS)
          # print(ILD.shape) # [1,129,t/win]
  
          # Separation
          mix_wl = self.hparams.EncoderL(mix[:, :, 0])
          # [1,64,t/k]
          n_samples = mix_wl.shape[-1]
          ILD_upsample = F.interpolate(ILD, size=n_samples)
          conv1 = Conv1d(
              ILD_upsample.shape[1], mix_wl.shape[1], kernel_size=1
          ).to(self.device)
          ILD_cat = conv1(ILD_upsample)
  
          mix_catl = torch.cat((mix_wl, ILD_cat), dim=1)
          est_maskl = self.hparams.MaskNetL(mix_catl)
          mix_wl = torch.stack([mix_wl] * self.hparams.num_spks)
          sep_hl = mix_wl * torch.chunk(est_maskl, 2, dim=2)[0]
  
          mix_wr = self.hparams.EncoderR(mix[:, :, 1])
          mix_catr = torch.cat((mix_wr, -ILD_cat), dim=1)
          est_maskr = self.hparams.MaskNetR(mix_catr)
          mix_wr = torch.stack([mix_wr] * self.hparams.num_spks)
          sep_hr = mix_wr * torch.chunk(est_maskr, 2, dim=2)[0]
      elif "parallel" in self.hparams.experiment_name:
          mix_wl1 = self.hparams.EncoderL(mix[:, :, 0])
          mix_wr2 = self.hparams.EncoderR(mix[:, :, 1])
          mix_wl = torch.cat((mix_wl1, mix_wr2), dim=1)
  
          est_maskl = self.hparams.MaskNetL(mix_wl)
          mix_wl1 = torch.stack([mix_wl1] * self.hparams.num_spks)
          mix_wr2 = torch.stack([mix_wr2] * self.hparams.num_spks)
          sep_hl1 = mix_wl1 * torch.chunk(est_maskl, 2, dim=2)[0]
          sep_hr2 = mix_wr2 * torch.chunk(est_maskl, 2, dim=2)[1]
  
          mix_wl2 = self.hparams.EncoderR(mix[:, :, 0])
          mix_wr1 = self.hparams.EncoderL(mix[:, :, 1])
          mix_wr = torch.cat((mix_wl2, mix_wr1), dim=1)
  
          est_maskr = self.hparams.MaskNetR(mix_wr)
          mix_wl2 = torch.stack([mix_wl2] * self.hparams.num_spks)
          mix_wr1 = torch.stack([mix_wr1] * self.hparams.num_spks)
          sep_hl2 = mix_wl2 * torch.chunk(est_maskr, 2, dim=2)[0]
          sep_hr1 = mix_wr1 * torch.chunk(est_maskr, 2, dim=2)[1]
          sep_hl = sep_hl1 + sep_hr2
          sep_hr = sep_hl2 + sep_hr1
      else:
          raise ValueError(
              "Experiment name in hparams should contain one of these--'independent', 'cross', and 'parallel'."
          )
  
      # Decoding
      est_sourcel = torch.cat(
          [
              self.hparams.DecoderL(sep_hl[i]).unsqueeze(-1)
              for i in range(self.hparams.num_spks)
          ],
          dim=-1,
      )
  
      est_sourcer = torch.cat(
          [
              self.hparams.DecoderR(sep_hr[i]).unsqueeze(-1)
              for i in range(self.hparams.num_spks)
          ],
          dim=-1,
      )
  
      est_source = torch.cat(
          [est_sourcel.unsqueeze(-2), est_sourcer.unsqueeze(-2)], dim=-2
      )
      # T changed after conv1d in encoder, fix it here
      T_origin = mix.size(1)
      T_est = est_source.size(1)
      if T_origin > T_est:
          est_source = F.pad(
              est_source, (0, 0, 0, 0, 0, T_origin - T_est)
          )
      else:
          est_source = est_source[:, :T_origin, :]
  
      return est_source, targets
  
imports: import os
  import sys
  import torch
  import torch.nn.functional
  import torchaudio
  import speechbrain
  import speechbrain.nnet.schedulers
  from speechbrain.utils.distributed import run_on_main
  from hyperpyyaml import load_hyperpyyaml
  import numpy
  from tqdm import tqdm
  import csv
  import logging
  from pyroomacoustics.experimental.localization import tdoa
  from speechbrain.processing.features import STFT, spectral_magnitude
  from torch.nn import Conv1d
  from speechbrain.core import AMPConfig
label_desc: Use image node_id 1 for calling the Separation obj's underlying member method code with example usage: obj.compute_forward(mix, targets, stage, noise) and returns: est_source,  targets