o
    zi4)                     @   sh   d dl Z d dlZd dlZd dlZd dlZd dlm  mZ	 d dl
Z
G dd dejjZG dd dZdS )    Nc                       s   e Zd ZdZ				ddededed	ed
ef
 fddZde	j
fddZde	j
fddZde	j
fddZde	j
fddZdd Zde	j
fddZedd Zejdd Z  ZS )Metera  Tensorized version of pyloudnorm.Meter. Works with batched audio tensors.

    Parameters
    ----------
    rate : int
        Sample rate of audio.
    filter_class : str, optional
        Class of weighting filter used.
        K-weighting' (default), 'Fenton/Lee 1'
        'Fenton/Lee 2', 'Dash et al.'
        by default "K-weighting"
    block_size : float, optional
        Gating block size in seconds, by default 0.400
    zeros : int, optional
         Number of zeros to use in FIR approximation of
         IIR filters, by default 512
    use_fir : bool, optional
        Whether to use FIR approximation or exact IIR formulation.
        If computing on GPU, ``use_fir=True`` will be used, as its
        much faster, by default False
    K-weighting皙?   Fratefilter_class
block_sizezerosuse_firc                    s   t    || _|| _|| _|| _tt	g d}| 
d| t|f}d|d< tt| jd|f}tt| j}	t| j D ]\}
\}}tj|j|j|||
< |j|	|
< qEt|dd d df   }| 
d| | 
d	|	 d S )
N)      ?r   r   (\?r   Gr   ).r      .firspassband_gain)super__init__r   r   r   r
   torch
from_numpynparrayregister_bufferr	   len_filters	enumerateitemsscipysignallfilterbar   copyfloat)selfr   r   r   r	   r
   r   impulser   r   i_filter_stage	__class__ L/home/ubuntu/.local/lib/python3.10/site-packages/audiotools/core/loudness.pyr   "   s"   
 zMeter.__init__datac                 C   s   |j \}}}|ddd}||| d|}| jj d }t| jj d D ](}t|||f}tj	|| j|ddf }| j
| | }|dd|d f }q$|ddd}|ddd|ddf }|S )a  Performs FIR approximation of loudness computation.

        Parameters
        ----------
        data : torch.Tensor
            Audio data of shape (nb, nch, nt).

        Returns
        -------
        torch.Tensor
            Filtered audio data.
        r      r   r   N.)shapepermutereshaper   rangeFpadjuliusfftconv
fft_conv1dr   )r$   r-   nbntnch
pad_lengthr&   r+   r+   r,   apply_filter_gpuE   s   zMeter.apply_filter_gpuc           	      C   s   | j  D ]9\}}|j}t|j |j}t|j	 |j}|
ddd}tjj|||dd}||
ddd }q|S )a  Performs IIR formulation of loudness computation.

        Parameters
        ----------
        data : torch.Tensor
            Audio data of shape (nb, nch, nt).

        Returns
        -------
        torch.Tensor
            Filtered audio data.
        r   r.   r   F)clamp)r   r   r   r   r   r!   r#   todevicer    r0   
torchaudio
functionalr   )	r$   r-   r'   r(   r   a_coeffsb_coeffs_datafilteredr+   r+   r,   apply_filter_cpuf   s   zMeter.apply_filter_cpuc                 C   s(   |j s| jr| |}|S | |}|S )aX  Applies filter on either CPU or GPU, depending
        on if the audio is on GPU or is on CPU, or if
        ``self.use_fir`` is True.

        Parameters
        ----------
        data : torch.Tensor
            Audio data of shape (nb, nch, nt).

        Returns
        -------
        torch.Tensor
            Filtered audio data.
        )is_cudar
   r<   rF   r$   r-   r+   r+   r,   apply_filter   s
   

zMeter.apply_filterc                 C   s
   |  |S )Computes integrated loudness of data.

        Parameters
        ----------
        data : torch.Tensor
            Audio data of shape (nb, nch, nt).

        Returns
        -------
        torch.Tensor
            Filtered audio data.
        )integrated_loudnessrH   r+   r+   r,   forward   s   
zMeter.forwardc                 C   s\   | j }d}d| }t|| j }t|| j | }tj|ddd||}|dd}|S )Ng      ?r   r   r.   r   r   )r   intr   r5   coreunfoldr0   	transpose)r$   
input_dataT_goverlapstepkernel_sizestrideunfoldedr+   r+   r,   _unfold   s   zMeter._unfoldc              	   C   s  t |st | }n| }t|}|jdk r |d}|jdk r*|d}|j\}}}| |}| j	}| j
}d}| |}	d|| j  |	 d }
ddt |d	d	|d	f |
 jd
dd  }||
}|
}d|||k< ||k}|d|d }ddt ||d	d	|f  d  d }|d	d	d	d	f }||||jd }|
}d|||k< d|||k< ||k||k }|d|d }t | t ||}tttjj||tdk< tttjj||td k< ddt |d	d	|f | d
  }| S )rJ   r.   r      r   g     Qr   g&1g      $@Nr   T)keepdiminf)r   	is_tensorr   r#   r"   ndim	unsqueezer/   rI   r   r   rY   r   squaresumlog10	expand_asexpandwhereisnan
zeros_liker   finfofloat32maxmin)r$   r-   rR   r8   r9   r:   r   rS   Gamma_arX   zlz_avg_gatedmaskedGamma_rLUFSr+   r+   r,   rK      sJ   







.
* (zMeter.integrated_loudnessc                 C   s   | j S )N)_filter_class)r$   r+   r+   r,   r      s   zMeter.filter_classc                 C   s.   ddl m} || j}||_|| _|j| _d S )Nr   )r   )
pyloudnormr   r   r   rs   r   )r$   valuer   meterr+   r+   r,   r      s
   
)r   r   r   F)__name__
__module____qualname____doc__rN   strr#   boolr   r   Tensorr<   rF   rI   rL   rY   rK   propertyr   setter__classcell__r+   r+   r)   r,   r      s6    #!I
r   c                   @   s,   e Zd ZdZdZ	 	d	dedefddZdS )
LoudnessMixinNir   r   r   r   c           	      K   s   | j dur| j | jS | j}| jdk r$td| j | j }| d| t| jf||d|}|| j}|	| j
ddd}| | tj||jd| j }t||| _ | j | jS )a  Calculates loudness using an implementation of ITU-R BS.1770-4.
        Allows control over gating block size and frequency weighting filters for
        additional control. Measure the integrated gated loudness of a signal.

        API is derived from PyLoudnorm, but this implementation is ported to PyTorch
        and is tensorized across batches. When on GPU, an FIR approximation of the IIR
        filters is used to compute loudness for speed.

        Uses the weighting filters and block size defined by the meter
        the integrated loudness is measured based upon the gating algorithm
        defined in the ITU-R BS.1770-4 specification.

        Parameters
        ----------
        filter_class : str, optional
            Class of weighting filter used.
            K-weighting' (default), 'Fenton/Lee 1'
            'Fenton/Lee 2', 'Dash et al.'
            by default "K-weighting"
        block_size : float, optional
            Gating block size in seconds, by default 0.400
        kwargs : dict, optional
            Keyword arguments to :py:func:`audiotools.core.loudness.Meter`.

        Returns
        -------
        torch.Tensor
            Loudness of audio data.
        Ng      ?r   )r   r   r.   r   )r?   )	_loudnessr>   r?   signal_lengthsignal_durationrN   sample_ratezero_padr   rK   
audio_datar0   truncate_samplesr   	ones_likeMIN_LOUDNESSmaximum)	r$   r   r   kwargsoriginal_lengthpad_lenrv   loudnessmin_loudnessr+   r+   r,   r     s(   
 

zLoudnessMixin.loudness)r   r   )rw   rx   ry   r   r   r{   r#   r   r+   r+   r+   r,   r     s    r   )r"   r5   numpyr   r   r   torch.nn.functionalnnrA   r3   r@   Moduler   r   r+   r+   r+   r,   <module>   s     }