o
    Si$4                     @   s   d dl Z d dlmZ d dlZG dd dejjZ				ddejd	ed
edede	de
dee	 dejfddZ						dd	ed
ededede	de
dee	 dejdeej fddZdejd	ed
ededejdefddZdS )    N)Optionalc                       sv   e Zd ZdZ						dddded	ed
edededee deej	 ddf fddZ
dejdejfddZ  ZS )Resamplea  Resample a signal from one frequency to another. A resampling method can be given.

    .. devices:: CPU CUDA

    .. properties:: Autograd TorchScript

    Note:
        If resampling on waveforms of higher precision than float32, there may be a small loss of precision
        because the kernel is cached once as float32. If high precision resampling is important for your application,
        the functional form will retain higher precision, but run slower because it does not cache the kernel.
        Alternatively, you could rewrite a transform that caches a higher precision kernel.

    Args:
        orig_freq (int, optional): The original frequency of the signal. (Default: ``16000``)
        new_freq (int, optional): The desired frequency. (Default: ``16000``)
        resampling_method (str, optional): The resampling method to use.
            Options: [``sinc_interp_hann``, ``sinc_interp_kaiser``] (Default: ``"sinc_interp_hann"``)
        lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper
            but less efficient. (Default: ``6``)
        rolloff (float, optional): The roll-off frequency of the filter, as a fraction of the Nyquist.
            Lower values reduce anti-aliasing, but also reduce some of the highest frequencies. (Default: ``0.99``)
        beta (float or None, optional): The shape parameter used for kaiser window.
        dtype (torch.device, optional):
            Determnines the precision that resampling kernel is pre-computed and cached. If not provided,
            kernel is computed with ``torch.float64`` then cached as ``torch.float32``.
            If you need higher precision, provide ``torch.float64``, and the pre-computed kernel is computed and
            cached as ``torch.float64``. If you use resample with lower precision, then instead of providing this
            providing this argument, please use ``Resample.to(dtype)``, so that the kernel generation is still
            carried out on ``torch.float64``.

    Example
        >>> waveform, sample_rate = ...
        >>> transform = Resample(sample_rate, sample_rate/10)
        >>> waveform = transform(waveform)
    >  sinc_interp_hann   Gz?Ndtype	orig_freqnew_freqresampling_methodlowpass_filter_widthrolloffbetar	   returnc          	   
      s   t    || _|| _tt| jt| j| _|| _|| _|| _	|| _
| j| jkrGt| j| j| j| j| j	| j||d\}| _| d| d S d S )Nr   kernel)super__init__r
   r   mathgcdintr   r   r   r   _get_sinc_resample_kernelwidthregister_buffer)	selfr
   r   r   r   r   r   r	   r   	__class__ P/home/ubuntu/.local/lib/python3.10/site-packages/lhotse/augmentation/resample.pyr   M   s*   

zResample.__init__waveformc                 C   s,   | j | jkr|S t|| j | j| j| j| jS )z
        Args:
            waveform (Tensor): Tensor of audio of dimension (..., time).

        Returns:
            Tensor: Output signal of dimension (..., time).
        )r
   r   _apply_sinc_resample_kernelr   r   r   )r   r   r   r   r   forwardo   s
   zResample.forward)r   r   r   r   r   N)__name__
__module____qualname____doc__r   strfloatr   torchr	   r   Tensorr!   __classcell__r   r   r   r   r   (   s8    &		
"r   r   r   r   r   r
   r   r   r   r   r   r   c              
   C   sn   |dks|dkrt d||kr| S tt|t|}t|||||||| j| j	\}}	t| |||||	}
|
S )a  Resamples the waveform at the new frequency using bandlimited interpolation. :cite:`RESAMPLE`.

    .. devices:: CPU CUDA

    .. properties:: Autograd TorchScript

    Note:
        ``Resample`` precomputes and reuses the resampling kernel, so using it will result in
        more efficient computation if resampling multiple waveforms with the same resampling parameters.

    Args:
        waveform (Tensor): The input signal of dimension `(..., time)`
        orig_freq (int): The original frequency of the signal
        new_freq (int): The desired frequency
        lowpass_filter_width (int, optional): Controls the sharpness of the filter, more == sharper
            but less efficient. (Default: ``6``)
        rolloff (float, optional): The roll-off frequency of the filter, as a fraction of the Nyquist.
            Lower values reduce anti-aliasing, but also reduce some of the highest frequencies. (Default: ``0.99``)
        resampling_method (str, optional): The resampling method to use.
            Options: [``"sinc_interp_hann"``, ``"sinc_interp_kaiser"``] (Default: ``"sinc_interp_hann"``)
        beta (float or None, optional): The shape parameter used for kaiser window.

    Returns:
        Tensor: The waveform at the new frequency of dimension `(..., time).`
    g        z:Original frequency and desired frequecy should be positive)
ValueErrorr   r   r   r   devicer	   r    )r   r
   r   r   r   r   r   r   r   r   	resampledr   r   r   resample~   s(   #r.   cpur   r,   r	   c	                 C   s  t | | krt ||kstd|dvrtd|t | | } t || }|dkr/tdt| |}	|	|9 }	t||  |	 }
|d urG|ntj}tj	|
 |
|  ||dd |  }tj	d| d||dd d d d f | | }||	9 }|
| |}|d	krt|tj | d
 d
 }n"|d u rd}tt|}t|td|| d
   t| }|tj9 }|	|  }t|dktd|| | }||| 9 }|d u r|jtjd}||
fS )Na  Frequencies must be of integer type to ensure quality resampling computation. To work around this, manually convert both frequencies to integer values that maintain their resampling rate ratio before passing them into the function. Example: To downsample a 44100 hz waveform by a factor of 8, use `orig_freq=8` and `new_freq=1` instead of `orig_freq=44100` and `new_freq=5512.5`. For more information, please refer to https://github.com/pytorch/audio/issues/1487.)r   sinc_interp_kaiserzInvalid resampling method: {}r   z)Low pass filter width should be positive.)r	   r,   )NNr      gQaTi-@   g      ?r   )r   	Exceptionr+   formatminr   ceilr(   float64arangeclamp_cospitensorr'   i0sqrtwheretosinfloat32)r
   r   r   r   r   r   r   r,   r	   	base_freqr   	idx_dtypeidxtwindowbeta_tensorscalekernelsr   r   r   r      sZ   	
"
&r   r   r   c                 C   s   |   std| j dt|| }t|| }|  }| d|d } | j\}}tjj	
| ||| f} tjj	j| d d d f ||d}	|	dd|d}	tt|| |  }
|	dd |
f }	|	|d d |	jdd   }	|	S )Nz?Expected floating point type for waveform tensor, but received .r1   )strider3   r2   .)is_floating_point	TypeErrorr	   r   sizeviewshaper(   nn
functionalpadconv1d	transposereshaper7   	as_tensorlong)r   r
   r   r   r   r   rR   num_wavslengthr-   target_lengthr   r   r   r      s    
  r    )r   r   r   N)r   r   r   Nr/   N)r   typingr   r(   rS   Moduler   r)   r   r'   r&   r.   r,   r	   r   r    r   r   r   r   <module>   s~   !Z
@	
d