
    m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         I/var/www/stems/demucs_env/lib/python3.12/site-packages/julius/resample.pyr   zResampleFrac.__init__   so    6 	&#&j.ECDDhhvv&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   sj   ;;$++%dkk*
 	dll& ii

T[[ 82 =>
 llDKK<t{{)BCIIKt{{# 	#ADKK#dkk/1R7A$**djj1ALAYYq|A~.1F!Wv%FKK

%NN6"	# 	Xu{{7';'@'@aQS'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IIb&!EE!AtG*t{{DKK$++,EF[YXXaT[[9LLA&&tE#2J'72$'>?#oodkkF.BT[[.PQ!JJ':;@@B %,? @ E E G 9=$5CX!Q-2C"CCDUCVWXX$)LL$?! !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^#. #.hsm #.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ME
:CAYFv|US[!e)<ALA1g$$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     77LUD*5144Q7F
L!((166"a&
>sABw
G
L
L
Ze
ZUY
ZCQH"%A166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     	wwr{Q!EE!Vc3Q3hKES!$Q$Y<D::LUD*5144Q7F
X!((499RD165I#sPRs(SXX 	 C388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   
    $  !588?? !F 5:DIVU\\ V3 V VV,1V!)#V=AV"")r   