o
    siE                     @   s   d Z ddlZddlZddlmZ ddlmZ ejZdd Zdd Z	d	d
 Z
dd ZG dd dejZG dd dejZG dd dejZeeejZeeejZG dd dejZddefddZdS )a  Complex building blocks that work with PyTorch native (!) complex tensors, i.e.
dtypes complex64/complex128, or tensors for which `.is_complex()` returns True.

Note that Asteroid code has two other representations of complex numbers:

- Torchaudio representation [..., 2] where [..., 0] and [..., 1] are real and
  imaginary components, respectively
- Asteroid style representation, identical to the Torchaudio representation, but
  with the last dimension concatenated: tensor([r1, r2, ..., rn, i1, i2, ..., in]).
  The concatenated (2 * n) dimension may be at an arbitrary position, i.e. the tensor
  is of shape [..., 2 * n, ...].  See `asteroid_filterbanks.transforms` for details.
    N)
transforms)nnc                 C   s   |   S N)
is_complexx r   G/home/ubuntu/.local/lib/python3.10/site-packages/asteroid/complex_nn.pyis_torch_complex   s   r
   c                 C   s,   t t j| t | | t | fddS N)dim)torchview_as_complexstackcossin)magphaser   r   r	   torch_complex_from_magphase   s   $r   c                 C   s   t t j| |gddS r   )r   r   r   )reimr   r   r	   torch_complex_from_reim"   s   r   c                    s>   t   fdd}|j j dk |j j dk |S )a@  Make a complex-valued function callable from a real-valued one by applying it to
    the real and imaginary components independently.

    Return:
        cf(x), complex version of `f`: A function that applies `f` to the real and
        imaginary components of `x` and returns the result as PyTorch complex tensor.
    c                    s   t  | j | jS r   )r   realimagr   fr   r	   cf/   s   zon_reim.<locals>.cfz
 (complex))	functoolswraps__name____qualname__)r   r   r   r   r	   on_reim&   s
   	r"   c                       s(   e Zd ZdZ fddZdd Z  ZS )OnReImzLike `on_reim`, but for stateful modules.

    Args:
        module_cls (callable): A class or function that returns a Torch module/functional.
            Called 2x with *args, **kwargs, to construct the real and imaginary component modules.
    c                    .   t    ||i || _||i || _d S r   super__init__	re_module	im_moduleself
module_clsargskwargs	__class__r   r	   r'   C      
zOnReIm.__init__c                 C   s   t | |j| |jS r   r   r(   r   r)   r   r+   r   r   r   r	   forwardH   s   zOnReIm.forward)r    
__module__r!   __doc__r'   r4   __classcell__r   r   r/   r	   r#   ;   s    r#   c                       s2   e Zd ZdZ fddZdedefddZ  ZS )ComplexMultiplicationWrappera  Make a complex-valued module `F` from a real-valued module `f` by applying
    complex multiplication rules:

    F(a + i b) = f1(a) - f1(b) + i (f2(b) + f2(a))

    where `f1`, `f2` are instances of `f` that do *not* share weights.

    Args:
        module_cls (callable): A class or function that returns a Torch module/functional.
            Constructor of `f` in the formula above.  Called 2x with `*args`, `**kwargs`,
            to construct the real and imaginary component modules.
    c                    r$   r   r%   r*   r/   r   r	   r'   Z   r1   z%ComplexMultiplicationWrapper.__init__r   returnc                 C   s2   t | |j| |j | |j| |j S r   r2   r3   r   r   r	   r4   _   s   z$ComplexMultiplicationWrapper.forwardr    r5   r!   r6   r'   ComplexTensorr4   r7   r   r   r/   r	   r8   L   s    r8   c                       sB   e Zd ZdZ	d fdd	Zedd Zd	ed
efddZ  Z	S )ComplexSingleRNNa  Module for a complex RNN block.

    This is similar to :cls:`asteroid.masknn.recurrent.SingleRNN` but uses complex
    multiplication as described in [1]. Arguments are identical to those of `SingleRNN`,
    except for `dropout`, which is not yet supported.

    Args:
        rnn_type (str): Select from ``'RNN'``, ``'LSTM'``, ``'GRU'``. Can
            also be passed in lowercase letters.
        input_size (int): Dimension of the input feature. The input should have
            shape [batch, seq_len, input_size].
        hidden_size (int): Dimension of the hidden state.
        n_layers (int, optional): Number of layers used in RNN. Default is 1.
        bidirectional (bool, optional): Whether the RNN layers are
            bidirectional. Default is ``False``.
        dropout: Not yet supported.

    References
        [1] : "DCCRN: Deep Complex Convolution Recurrent Network for Phase-Aware Speech Enhancement",
        Yanxin Hu et al. https://arxiv.org/abs/2008.00264
       r   Fc                    s   |r
|dkr
J dt    ddlm} ||dd|d}t|fd|i|}	tj|	g| _t	|d D ]}
| j
t|fd|	jji| q5d S )Nr=   z,Dropout is not yet supported for complex RNN)	SingleRNNr   )rnn_typehidden_sizen_layersdropoutbidirectional
input_size)r&   r'   masknn.recurrentr>   r8   r   r   
ModuleListrnnsrangeappendr(   output_size)r+   r?   rD   r@   rA   rB   rC   r>   r.   	first_rnn_r/   r   r	   r'   }   s,   
zComplexSingleRNN.__init__c                 C   s   | j d jjS )Nr   )rG   r(   rJ   )r+   r   r   r	   rJ      s   zComplexSingleRNN.output_sizer   r9   c                 C   s   | j D ]}||}q|S )zInput shape [batch, seq, feats])rG   )r+   r   rnnr   r   r	   r4      s   

zComplexSingleRNN.forward)r=   r   F)
r    r5   r!   r6   r'   propertyrJ   r;   r4   r7   r   r   r/   r	   r<   f   s    
r<   c                       s.   e Zd ZdZ fddZdefddZ  ZS )BoundComplexMaskz&Module version of `bound_complex_mask`c                    s   t    || _d S r   )r&   r'   
bound_type)r+   rP   r/   r   r	   r'      s   

zBoundComplexMask.__init__maskc                 C   s   t || jS r   )bound_complex_maskrP   )r+   rQ   r   r   r	   r4      s   zBoundComplexMask.forwardr:   r   r   r/   r	   rO      s    rO   tanhrQ   c                 C   sb   |dv rt tj| S |dv r*tt| \}}|dv r#t|}n|}t||S td| )u  Bound a complex mask, as proposed in [1], section 3.2.

    Valid bound types, for a complex mask :math:`M = |M| ⋅ e^{i φ(M)}`:

    - Unbounded ("UBD"): :math:`M_{\mathrm{UBD}} = M`
    - Sigmoid ("BDSS"): :math:`M_{\mathrm{BDSS}} = σ(|M|) e^{i σ(φ(M))}`
    - Tanh ("BDT"): :math:`M_{\mathrm{BDT}} = \mathrm{tanh}(|M|) e^{i φ(M)}`

    Args:
        bound_type (str or None): The type of bound to use, either of
            "tanh"/"bdt" (default), "sigmoid"/"bdss" or None/"bdt".

    References
        [1] : "Phase-aware Speech Enhancement with Deep Complex U-Net",
        Hyeong-Seok Choi et al. https://arxiv.org/abs/1903.03107
    >   BDSSsigmoid>   NBDTUBDrS   >   rV   rS   zUnknown mask bound )	r"   r   rU   r   magphasefrom_torch_complexrS   r   
ValueError)rQ   rP   mask_mag
mask_phasemask_mag_boundedr   r   r	   rR      s   
rR   )rS   )r6   r   r   asteroid_filterbanksr   r   Tensorr;   r
   r   r   r"   Moduler#   r8   r<   partialConv2dComplexConv2dConvTranspose2dComplexConvTranspose2drO   rR   r   r   r   r	   <module>   s"    9