Ë
      çiŒ%  ã                   óà   — d Z ddlZddlmZ ddlZddlmZ ddlm	Z	 ddl
mZ  G d„ d	ej                  j                  «      Z	 	 dd
ej                  dededededee   defd„Zd„ Zdd„Zdd„Zy)a  
Differentiable, Pytorch based resampling.
Implementation of Julius O. Smith algorithm for resampling.
See https://ccrma.stanford.edu/~jos/resample/ for details.
This implementation is specially optimized for when new_sr / old_sr is a fraction
with a small numerator and denominator when removing the gcd (e.g. new_sr = 700, old_sr = 500).

Very similar to [bmcfee/resampy](https://github.com/bmcfee/resampy) except this implementation
is optimized for the case mentioned before, while resampy is slower but more general.

é    N)ÚOptional)Ú
functionalé   )Úsinc©Úsimple_reprc            	       ór   ‡ — e Zd ZdZddedededefˆ fd„Zd„ Zddej                  d	e
e   d
efd„Zd„ Zˆ xZS )ÚResampleFracz?
    Resampling from the sample rate `old_sr` to `new_sr`.
    Úold_srÚnew_srÚzerosÚrolloffc                 ó  •— t         ‰| �  «        t        |t        «      rt        |t        «      st	        d«      ‚t        j                  ||«      }||z  | _        ||z  | _        || _	        || _
        | j                  «        y)a©  
        Args:
            old_sr (int): sample rate of the input signal x.
            new_sr (int): sample rate of the output.
            zeros (int): number of zero crossing to keep in the sinc filter.
            rolloff (float): use a lowpass filter that is `rolloff * new_sr / 2`,
                to ensure sufficient margin due to the imperfection of the FIR filter used.
                Lowering this value will reduce anti-aliasing, but will reduce some of the
                highest frequencies.

        Shape:

            - Input: `[*, T]`
            - Output: `[*, T']` with `T' = int(new_sr * T / old_sr)


        .. caution::
            After dividing `old_sr` and `new_sr` by their GCD, both should be small
            for this implementation to be fast.

        >>> import torch
        >>> resample = ResampleFrac(4, 5)
        >>> x = torch.randn(1000)
        >>> print(len(resample(x)))
        1250
        z$old_sr and new_sr should be integersN)ÚsuperÚ__init__Ú
isinstanceÚintÚ
ValueErrorÚmathÚgcdr   r   r   r   Ú_init_kernels)Úselfr   r   r   r   r   Ú	__class__s         €úd/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/julius/resample.pyr   zResampleFrac.__init__   so   ø€ ô6 	‰ÑÔÜ˜&¤#Ô&¬j¸ÄÔ.EÜÐCÓDÐDÜ�h‰h�v˜vÓ&ˆØ ‘mˆŒØ ‘mˆŒØˆŒ
ØˆŒà×ÑÕó    c                 óÈ  — | j                   | j                  k(  ry g }t        | j                  | j                   «      }|| j                  z  }t	        j
                  | j                  | j                   z  |z  «      | _        t        j                  | j                   | j                  | j                   z   «      j                  «       }t        | j                  «      D ]Å  }| | j                  z  || j                   z  z   |z  }|j                  | j                   | j                  «      }|t        j                  z  }t        j                  || j                  z  dz  «      dz  }t        |«      |z  }|j!                  |j#                  «       «       |j%                  |«       ŒÇ | j'                  dt        j(                  |«      j+                  | j                  dd«      «       y )Né   Úkernelr   éÿÿÿÿ)r   r   Úminr   r   Úceilr   Ú_widthÚtorchÚarangeÚfloatÚrangeÚclamp_ÚpiÚcosr   Údiv_ÚsumÚappendÚregister_bufferÚstackÚview)r   ÚkernelsÚsrÚidxÚiÚtÚwindowr   s           r   r   zResampleFrac._init_kernelsC   se  € Ø�;‰;˜$Ÿ+™+Ò%ØàˆÜ�—‘˜dŸk™kÓ*ˆð
 	ˆd�l‰lÑˆô& —i‘i §
¡
¨T¯[©[Ñ 8¸2Ñ =Ó>ˆŒô
 �l‰l˜DŸK™K˜<¨¯©°t·{±{Ñ)BÓC×IÑIÓKˆÜ�t—{‘{Ö#ˆAØ��D—K‘K‘ # d§k¡k¡/Ñ1°RÑ7ˆAØ—‘˜$Ÿ*™*˜ d§j¡jÓ1ˆAØ”—‘‰LˆAÜ—Y‘Y˜q §¡™|¨A™~Ó.°Ñ1ˆFÜ˜!“W˜vÑ%ˆFà�K‰K˜Ÿ
™
›Ô%Ø�N‰N˜6Õ"ð $ð 	×Ñ˜X¤u§{¡{°7Ó';×'@Ñ'@ÀÇÁÈaÐQSÓ'TÕUr   ÚxÚoutput_lengthÚfullc                 óR  — | j                   | j                  k(  r|S |j                  }|j                  d   }|j                  d|«      }t	        j
                  |dd…df   | j                  | j                  | j                   z   fd¬«      }t	        j                  || j                  | j                   ¬«      }|j                  dd«      j                  t        |dd «      dgz   «      }t        j                  | j                  |z  | j                   z  «      }t        j                  |«      j                  «       }	t        j                  |«      j                  «       }
|€|r|	n|
}n:|dk  s||	kD  rt!        d	|	› �«      ‚t        j"                  |«      }|rt!        d
«      ‚|dd|…f   S )a  
        Resample x.
        Args:
            x (Tensor): signal to resample, time should be the last dimension
            output_length (None or int): This can be set to the desired output length
                (last dimension). Allowed values are between 0 and
                ceil(length * new_sr / old_sr). When None (default) is specified, the
                floored output length will be used. In order to select the largest possible
                size, use the `full` argument.
            full (bool): return the longest possible output from the input. This can be useful
                if you chain resampling operations, and want to give the `output_length` only
                for the last one, while passing `full=True` to all the other ones.
        r   NÚ	replicate)Úmode)Ústrider   r   r   z$output_length must be between 0 and z0You cannot pass both full=True and output_length.)r   r   ÚshapeÚreshapeÚFÚpadr"   Úconv1dr   Ú	transposeÚlistr#   Ú	as_tensorr!   ÚlongÚfloorr   Útensor)r   r6   r7   r8   r=   ÚlengthÚysÚyÚfloat_output_lengthÚmax_output_lengthÚdefault_output_lengthÚapplied_output_lengths               r   ÚforwardzResampleFrac.forwardr   su  € ð �;‰;˜$Ÿ+™+Ò%ØˆHØ—‘ˆØ—‘˜‘ˆØ�I‰I�b˜&Ó!ˆÜ�E‰E�!’A�t�G‘*˜tŸ{™{¨D¯K©K¸$¿+¹+Ñ,EÐFÈ[ÔYˆÜ�X‰X�a˜Ÿ™¨T¯[©[Ô9ˆØ�L‰L˜˜AÓ×&Ñ&¤t¨E°#°2¨JÓ'7¸2¸$Ñ'>Ó?ˆä#Ÿo™o¨d¯k©k¸FÑ.BÀTÇ[Á[Ñ.PÓQÐÜ!ŸJ™JÐ':Ó;×@Ñ@ÓBÐÜ %§¡Ð,?Ó @× EÑ EÓ GÐàÐ Ù9=Ñ$5ÐCXÑ!Ø˜QÒ -Ð2CÒ"CÜÐCÐDUÐCVÐWÓXÐXä$)§L¡L°Ó$?Ð!ÙÜ Ð!SÓTÐTØ�Ð,Ð,Ð,Ð,Ñ-Ð-r   c                 ó   — t        | «      S )Nr   )r   s    r   Ú__repr__zResampleFrac.__repr__—   s   € Ü˜4Ó Ð r   )é   ç=
×£p=î?)NF)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r%   r   r   r#   ÚTensorr   ÚboolrO   rQ   Ú__classcell__)r   s   @r   r
   r
      sZ   ø„ ññ$˜sð $¨Cð $¸ð $È5õ $òL-Vñ^#.˜Ÿ™ð #.°h¸s±mð #.ÐRVó #.öJ!r   r
   r6   r   r   r   r   r7   r8   c                 óL   —  t        ||||«      j                  | «      | ||«      S )aR  
    Functional version of `ResampleFrac`, refer to its documentation for more information.

    ..warning::
        If you call repeatidly this functions with the same sample rates, then the
        resampling kernel will be recomputed everytime. For best performance, you should use
        and cache an instance of `ResampleFrac`.
    )r
   Úto)r6   r   r   r   r   r7   r8   s          r   Úresample_fracr]   ›   s,   € ð >Œ<˜ ¨¨wÓ7×:Ñ:¸1Ó=¸aÀÐPTÓUÐUr   c                 óö   — t        j                  d| z  dz   d¬«      }|dd d…   }t        j                  |  dz   | dz
  d| z  «      }|t        j                  z  }t        |«      |z  j                  ddd«      }|S )Né   r   F)Úperiodicr   ç      à?r   )r#   Úhann_windowÚlinspacer   r(   r   r/   )r   ÚwinÚwinoddr4   r   s        r   Ú_kernel_upsample2_downsample2rf   ¬   s|   € ô ×
Ñ
˜A ™I¨™M°EÔ
:€CØ���A�‰Y€FÜ�‰˜�v ‘| U¨S¡[°!°e±)Ó<€AØŒ�‰�L€AÜ�1‹g˜Ñ×$Ñ$ Q¨¨2Ó.€FØ€Mr   c                 ó2  — | j                   �^ }}t        |«      j                  | «      } t        j                  | j                  dd|«      ||¬«      ddd…f   j
                  g |¢|‘­Ž }t        j                  | |gd¬«      } |j
                  g |¢d‘­Ž S )aœ  
    Upsample x by a factor of two. The output will be exactly twice as long as the input.
    Args:
        x (Tensor): signal to upsample, time should be the last dimension
        zeros (int): number of zero crossing to keep in the sinc filter.

    This function is kept only for reference, you should use the more generic `resample_frac`
    one. This function does not perform anti-aliasing filtering.
    r   r   ©Úpadding.N)Údim)r=   rf   r\   r?   rA   r/   r#   r.   )r6   r   ÚotherÚtimer   ÚoutrJ   s          r   Ú
_upsample2rn   ·   s“   € ð —7‘7�L€UˆDÜ*¨5Ó1×4Ñ4°QÓ7€FØ
LŒ!�(‰(�1—6‘6˜"˜a Ó&¨¸Ô
>¸sÀAÁB¸wÑ
G×
LÑ
LÐ
ZÈeÐ
ZÐUYÒ
Z€CÜ�‰�Q˜�H "Ô%€AØˆ1�6‰6Ð�5Ð˜"ÒÐr   c           	      ó¢  — | j                   d   dz  dk7  rt        j                  | d«      } | dddd…f   }| dddd…f   }|j                   �^ }}t        |«      j	                  | «      }| t        j
                  |j                  dd|«      ||¬«      ddd…f   j                  g |¢|‘­Ž z   } |j                  g |¢d‘­Ž j                  d	«      S )
a™  
    Downsample x by a factor of two. The output length is half of the input, ceiled.
    Args:
        x (Tensor): signal to downsample, time should be the last dimension
        zeros (int): number of zero crossing to keep in the sinc filter.

    This function is kept only for reference, you should use the more generic `resample_frac`
    one. This function does not perform anti-aliasing filtering.
    r   r   r   )r   r   .Nr   rh   ra   )r=   r?   r@   rf   r\   rA   r/   Úmul)r6   r   ÚxevenÚxoddrk   rl   r   rm   s           r   Ú_downsample2rs   È   sä   € ð 	‡w�wˆr�{�Q�˜!ÒÜ�E‰E�!�VÓˆØˆc‘3�Q�3ˆh‰K€EØˆS�!�$�Q�$ˆY‰<€DØ—:‘:�L€UˆDÜ*¨5Ó1×4Ñ4°QÓ7€FØ
ÐX”!—(‘(˜4Ÿ9™9 R¨¨DÓ1°6À5ÔIÈ#ÈsÐPRÈsÈ(ÑS×XÑXð Ø	ðØòñ €Càˆ3�8‰8Ð�UÐ˜BÒ×#Ñ# CÓ(Ð(r   )rR   rS   NF)rR   )rW   r   Útypingr   r#   Útorch.nnr   r?   Úcorer   Úutilsr   ÚnnÚModuler
   rX   r   r%   rY   r]   rf   rn   rs   © r   r   Ú<module>r{      s–   ðñ
ó Ý ã Ý $å Ý ô!�5—8‘8—?‘?ô !ðF 5:ØDIñV�U—\‘\ð V¨3ð V¸ð VØðVØ,1ðVà!)¨#¡ðVà=AóVò"óô")r   