docstr: apply masks
  
  Args:
      masks : est_masks, [(B, T, F), ...]
      real (torch.Tensor): real part of the noisy spectrum, (B, F, T)
      imag (torch.Tensor): imag part of the noisy spectrum, (B, F, T)
  
  Returns:
      masked (List[Union(torch.Tensor, ComplexTensor)]): [(B, T, F), ...]
docstr_tok: ["apply","masks","Args",":","masks",":","est_masks",",","[","(","B",",","T",",","F",")",",","...","]","real","(","torch.Tensor",")",":","real","part","of","the","noisy","spectrum",",","(","B",",","F",",","T",")","imag","(","torch.Tensor",")",":","imag","part","of","the","noisy","spectrum",",","(","B",",","F",",","T",")","Returns",":","masked","(","List","[","Union","(","torch.Tensor",",","ComplexTensor",")","]",")",":","[","(","B",",","T",",","F",")",",","...","]"]
code: def apply_masks(
      self,
      masks: List[Union[torch.Tensor, ComplexTensor]],
      real: torch.Tensor,
      imag: torch.Tensor,
  ):
      """apply masks
  
      Args:
          masks : est_masks, [(B, T, F), ...]
          real (torch.Tensor): real part of the noisy spectrum, (B, F, T)
          imag (torch.Tensor): imag part of the noisy spectrum, (B, F, T)
  
      Returns:
          masked (List[Union(torch.Tensor, ComplexTensor)]): [(B, T, F), ...]
      """
      masked = []
      for i in range(len(masks)):
          # shape (B, T, F) --> (B, F, T)
          mask_real = masks[i].real.permute(0, 2, 1)
          mask_imag = masks[i].imag.permute(0, 2, 1)
          if self.masking_mode == "E":
              # shape (B, F, T)
              spec_mags = torch.sqrt(real**2 + imag**2 + 1e-8)
              # shape (B, F, T)
              spec_phase = torch.atan2(imag, real)
              mask_mags = (mask_real**2 + mask_imag**2) ** 0.5
              # mask_mags = (mask_real ** 2 + mask_imag ** 2 + EPS) ** 0.5
              real_phase = mask_real / (mask_mags + EPS)
              imag_phase = mask_imag / (mask_mags + EPS)
              # mask_phase = torch.atan2(imag_phase + EPS, real_phase + EPS)
              mask_phase = torch.atan2(imag_phase, real_phase)
              mask_mags = torch.tanh(mask_mags)
              est_mags = mask_mags * spec_mags
              est_phase = spec_phase + mask_phase
              real = est_mags * torch.cos(est_phase)
              imag = est_mags * torch.sin(est_phase)
          elif self.masking_mode == "C":
              real, imag = (
                  real * mask_real - imag * mask_imag,
                  real * mask_imag + imag * mask_real,
              )
          elif self.masking_mode == "R":
              real, imag = real * mask_real, imag * mask_imag
  
          # shape (B, F, T) --> (B, T, F)
          if is_torch_1_9_plus and self.use_builtin_complex:
              masked.append(
                  torch.complex(
                      real.permute(0, 2, 1), imag.permute(0, 2, 1)
                  )
              )
          else:
              masked.append(
                  ComplexTensor(
                      real.permute(0, 2, 1), imag.permute(0, 2, 1)
                  )
              )
      return masked
  
file_path: espnet/espnet2/enh/separator/dccrn_separator.py
imports: from collections import OrderedDict
  from typing import Dict, List, Optional, Tuple, Union
  import torch
  import torch.nn
  import torch.nn.functional
  from packaging.version import parse
  from torch_complex.tensor import ComplexTensor
  from espnet2.enh.layers.complexnn import ComplexBatchNorm, ComplexConv2d, ComplexConvTranspose2d, NavieComplexLSTM, complex_cat
  from espnet2.enh.separator.abs_separator import AbsSeparator
label_desc: Use image node_id 5 for calling the DCCRNSeparator obj's underlying member method code with example usage: obj.apply_masks(masks, real, imag) and returns: masked