o
    zi                     @   s`   d dl Z d dlm  mZ d dl mZ ddlmZ ddlmZ ddlmZ G dd dej	Z
dS )	    N)nn   )AudioSignal)
STFTParams)utilc                       sX   e Zd ZdZddedef fddZ				
	ddedededededefddZ  Z	S )SpectralGatea  Spectral gating algorithm for noise reduction,
    as in Audacity/Ocenaudio. The steps are as follows:

    1.  An FFT is calculated over the noise audio clip
    2.  Statistics are calculated over FFT of the the noise
        (in frequency)
    3.  A threshold is calculated based upon the statistics
        of the noise (and the desired sensitivity of the algorithm)
    4.  An FFT is calculated over the signal
    5.  A mask is determined by comparing the signal FFT to the
        threshold
    6.  The mask is smoothed with a filter over frequency and time
    7.  The mask is appled to the FFT of the signal, and is inverted

    Implementation inspired by Tim Sainburg's noisereduce:

    https://timsainburg.com/noise-reduction-python.html

    Parameters
    ----------
    n_freq : int, optional
        Number of frequency bins to smooth by, by default 3
    n_time : int, optional
        Number of time bins to smooth by, by default 5
    r      n_freqn_timec                    s   t    tttdd|d d d tdd|d gdddf ttdd|d d d tdd|d gdddf }||  }|dd}| d| d S )Nr         .smoothing_filter)	super__init__torchoutercatlinspacesum	unsqueezeregister_buffer)selfr	   r
   r   	__class__ V/home/ubuntu/.local/lib/python3.10/site-packages/audiotools/ml/layers/spectral_gate.pyr   %   s(   


zSpectralGate.__init__      ?      @      audio_signal	nz_signaldenoise_amountn_std
win_length
hop_lengthc                 C   s<  t ||d}| }d|_||_| }||_d|jd  }|jddd}	|jddd}
|	|
|  }d|jd  }|j	\}}}}|
||d|}||k  }|j	}||| d||}| jj	d	 d
 | jj	d d
 f}tj|| j|d}|j| }|tj||jd|j9 }d| }| j|9  _|  |S )a  Perform noise reduction.

        Parameters
        ----------
        audio_signal : AudioSignal
            Audio signal that noise will be removed from.
        nz_signal : AudioSignal, optional
            Noise signal to compute noise statistics from.
        denoise_amount : float, optional
            Amount to denoise by, by default 1.0
        n_std : float, optional
            Number of standard deviations above which to consider
            noise, by default 3.0
        win_length : int, optional
            Length of window for STFT, by default 2048
        hop_length : int, optional
            Hop length for STFT, by default 512

        Returns
        -------
        AudioSignal
            Denoised audio signal.
        	sqrt_hannN   g-C6?Tr   )keepdimdimr   r   )padding)ndim)r   clone	stft_datastft_params	magnitudeclamplog10meanstdshapeexpandfloatreshaper   Fconv2dr   ensure_tensorr-   todeviceistft)r   r!   r"   r#   r$   r%   r&   r0   
nz_stft_dbnz_freq_meannz_freq_std	nz_threshstft_dbnbnacnfnt	db_thresh	stft_maskr6   	pad_tupler   r   r   forward:   s8    
zSpectralGate.forward)r   r   )r   r   r   r    )
__name__
__module____qualname____doc__intr   r   r8   rL   __classcell__r   r   r   r   r   
   s(    r   )r   torch.nn.functionalr   
functionalr:   corer   r   r   Moduler   r   r   r   r   <module>   s    