docstr: Forward.
  
  Args:
      input (torch.Tensor or ComplexTensor): STFT spectrum [B, T, (C,) F (,2)]
          B is the batch size
          T is the number of time frames
          C is the number of microphone channels (optional)
          F is the number of frequency bins
          2 is real and imaginary parts (optional if input is a complex tensor)
      ilens (torch.Tensor): input lengths [Batch]
      additional (Dict or None): other data included in model
          "mode": one of ("no_dereverb", "dereverb", "both")
          1. "no_dereverb": only use the first memory group for denoising
              without dereverberation
          2. "dereverb": only use the second memory group for denoising
              with dereverberation
          3. "both": use both memory groups for denoising with and without
              dereverberation
  
  Returns:
      masked (List[Union(torch.Tensor, ComplexTensor)]): [(B, T, F), ...]
      ilens (torch.Tensor): (B,)
      others predicted data, e.g. masks: OrderedDict[
          'mask_spk1': torch.Tensor(Batch, Frames, Freq),
          'mask_spk2': torch.Tensor(Batch, Frames, Freq),
          ...
          'mask_spkn': torch.Tensor(Batch, Frames, Freq),
      ]
code: def forward(
      self,
      input: Union[torch.Tensor, ComplexTensor],
      ilens: torch.Tensor,
      additional: Optional[Dict] = None,
  ) -> Tuple[
      List[Union[torch.Tensor, ComplexTensor]],
      torch.Tensor,
      OrderedDict,
  ]:
      """Forward.
  
      Args:
          input (torch.Tensor or ComplexTensor): STFT spectrum [B, T, (C,) F (,2)]
              B is the batch size
              T is the number of time frames
              C is the number of microphone channels (optional)
              F is the number of frequency bins
              2 is real and imaginary parts (optional if input is a complex tensor)
          ilens (torch.Tensor): input lengths [Batch]
          additional (Dict or None): other data included in model
              "mode": one of ("no_dereverb", "dereverb", "both")
              1. "no_dereverb": only use the first memory group for denoising
                  without dereverberation
              2. "dereverb": only use the second memory group for denoising
                  with dereverberation
              3. "both": use both memory groups for denoising with and without
                  dereverberation
  
      Returns:
          masked (List[Union(torch.Tensor, ComplexTensor)]): [(B, T, F), ...]
          ilens (torch.Tensor): (B,)
          others predicted data, e.g. masks: OrderedDict[
              'mask_spk1': torch.Tensor(Batch, Frames, Freq),
              'mask_spk2': torch.Tensor(Batch, Frames, Freq),
              ...
              'mask_spkn': torch.Tensor(Batch, Frames, Freq),
          ]
      """
      # B, 2, T, (C,) F
      if is_complex(input):
          feature = torch.stack([input.real, input.imag], dim=1)
      else:
          assert input.size(-1) == 2, input.shape
          feature = input.moveaxis(-1, 1)
  
      # B, C, 2, F, T
      if feature.ndim == 4:
          feature = feature.moveaxis(-1, -2).unsqueeze(1)
      elif feature.ndim == 5:
          feature = feature.permute(0, 3, 1, 4, 2).contiguous()
      else:
          raise ValueError(f"Invalid input shape: {feature.shape}")
  
      B, C, RI, F, T = feature.shape
      feature = feature.reshape(-1, RI, F, T)
      feature = self.post_encoder(feature)  # B*C, enc_channels, F, T
      feature = feature.reshape(B, C, -1, F, T).contiguous()
  
      others = {}
      # B, enc_channels * num_spk, F, T
      if additional is not None:
          mode = additional.get("mode", "no_dereverb")
          if mode == "no_dereverb":
              processed = self.uses(
                  feature, ref_channel=self.ref_channel
              )
          elif mode == "dereverb":
              processed = self.uses(
                  feature, ref_channel=self.ref_channel, mem_idx=1
              )
          elif mode == "both":
              # For training with multii-condition data
              # 1. denoised output without dereverberation
              processed = self.uses(
                  feature, ref_channel=self.ref_channel, mem_idx=0
              )
  
              # 2. denoised output with dereverberation
              processed2 = self.uses(
                  feature, ref_channel=self.ref_channel, mem_idx=1
              )
              processed2 = processed2.reshape(
                  B * self.num_spk, self.enc_channels, F, T
              )
              processed2 = self.pre_decoder(processed2)
              specs2 = processed2.reshape(
                  B, self.num_spk, 2, F, T
              ).moveaxis(-1, -2)
              # B, num_spk, T, F
              if not is_complex(input):
                  for spk in range(specs2.size(1)):
                      others[f"dereverb{spk + 1}"] = ComplexTensor(
                          specs2[:, spk, 0], specs2[:, spk, 1]
                      )
              else:
                  for spk in range(specs2.size(1)):
                      others[f"dereverb{spk + 1}"] = new_complex_like(
                          input, (specs2[:, spk, 0], specs2[:, spk, 1])
                      )
          else:
              raise ValueError(mode)
      else:
          mode = ""
          processed = self.uses(feature, ref_channel=self.ref_channel)
  
      processed = processed.reshape(
          B * self.num_spk, self.enc_channels, F, T
      )
      processed = self.pre_decoder(processed)
      specs = processed.reshape(B, self.num_spk, 2, F, T).moveaxis(
          -1, -2
      )
  
      # B, num_spk, T, F
      if not is_complex(input):
          specs = list(
              ComplexTensor(specs[:, :, 0], specs[:, :, 1]).unbind(1)
          )
      else:
          specs = list(
              new_complex_like(
                  input, (specs[:, :, 0], specs[:, :, 1])
              ).unbind(1)
          )
  
      return specs, ilens, others
  
file_path: espnet/espnet2/enh/separator/uses_separator.py
imports: from collections import OrderedDict
  from typing import Dict, List, Optional, Tuple, Union
  import torch
  from torch_complex.tensor import ComplexTensor
  from espnet2.enh.layers.complex_utils import is_complex, new_complex_like
  from espnet2.enh.layers.uses import USES
  from espnet2.enh.separator.abs_separator import AbsSeparator
label_desc: Use image node_id 2 for calling the USESSeparator obj's underlying member method code with example usage: obj.forward(input, ilens, additional) and returns: specs,  ilens,  others