Ë
      çi  ã                   óZ  — d Z ddlZddlmZmZ ddlZddlmZ ddl	m
Z
 ddlmZ ddlmZ  G d	„ d
ej                  j                   «      Z G d„ dej                  j                   «      Z	 	 ddej&                  dee   dedededee   fd„Z	 	 ddej&                  dededededee   fd„Zy)z$
FIR windowed sinc lowpass filters.
é    N)ÚSequenceÚOptional)Ú
functionalé   )Úsinc)Ú
fft_conv1d©Úsimple_reprc                   óV   ‡ — e Zd ZdZ	 	 d
dee   dedededee   f
ˆ fd„Z	d„ Z
d	„ Zˆ xZS )ÚLowPassFiltersa­
  
    Bank of low pass filters. Note that a high pass or band pass filter can easily
    be implemented by substracting a same signal processed with low pass filters with different
    frequencies (see `julius.bands.SplitBands` for instance).
    This uses a windowed sinc filter, very similar to the one used in
    `julius.resample`. However, because we do not change the sample rate here,
    this filter can be much more efficiently implemented using the FFT convolution from
    `julius.fftconv`.

    Args:
        cutoffs (list[float]): list of cutoff frequencies, in [0, 0.5] expressed as `f/f_s` where
            f_s is the samplerate and `f` is the cutoff frequency.
            The upper limit is 0.5, because a signal sampled at `f_s` contains only
            frequencies under `f_s / 2`.
        stride (int): how much to decimate the output. Keep in mind that decimation
            of the output is only acceptable if the cutoff frequency is under `1/ (2 * stride)`
            of the original sampling rate.
        pad (bool): if True, appropriately pad the input with zero over the edge. If `stride=1`,
            the output will have the same length as the input.
        zeros (float): Number of zero crossings to keep.
            Controls the receptive field of the Finite Impulse Response filter.
            For lowpass filters with low cutoff frequency, e.g. 40Hz at 44.1kHz,
            it is a bad idea to set this to a high value.
            This is likely appropriate for most use. Lower values
            will result in a faster filter, but with a slower attenuation around the
            cutoff frequency.
        fft (bool or None): if True, uses `julius.fftconv` rather than PyTorch convolutions.
            If False, uses PyTorch convolutions. If None, either one will be chosen automatically
            depending on the effective filter size.


    ..warning::
        All the filters will use the same filter size, aligned on the lowest
        frequency provided. If you combine a lot of filters with very diverse frequencies, it might
        be more efficient to split them over multiple modules with similar frequencies.

    ..note::
        A lowpass with a cutoff frequency of 0 is defined as the null function
        by convention here. This allows for a highpass with a cutoff of 0 to
        be equal to identity, as defined in `julius.filters.HighPassFilters`.

    Shape:

        - Input: `[*, T]`
        - Output: `[F, *, T']`, with `T'=T` if `pad` is True and `stride` is 1, and
            `F` is the numer of cutoff frequencies.

    >>> lowpass = LowPassFilters([1/4])
    >>> x = torch.randn(4, 12, 21, 1024)
    >>> list(lowpass(x).shape)
    [1, 4, 12, 21, 1024]
    ÚcutoffsÚstrideÚpadÚzerosÚfftc           
      ó”  •— t         ‰| �  «        t        |«      | _        t	        | j                  «      dk  rt        d«      ‚t        | j                  «      dkD  rt        d«      ‚|| _        || _        || _	        t        |t	        | j                  D �cg c]
  }|dkD  sŒ	|‘Œ c}«      z  dz  «      | _        |€| j                  dkD  }|| _        t        j                  d| j                  z  dz   d¬	«      }t        j                  | j                   | j                  dz   «      }g }	|D ]l  }
|
dk(  rt        j                   |«      }n>d|
z  |z  t#        d|
z  t$        j&                  z  |z  «      z  }||j)                  «       z  }|	j+                  |«       Œn | j-                  d
t        j.                  |	«      d d …d f   «       y c c}w )Nr   z(Minimum cutoff must be larger than zero.g      à?z'A cutoff above 0.5 does not make sense.é   é    r   F)ÚperiodicÚfilters)ÚsuperÚ__init__Úlistr   ÚminÚ
ValueErrorÚmaxr   r   r   ÚintÚ	half_sizer   ÚtorchÚhann_windowÚarangeÚ
zeros_liker   ÚmathÚpiÚsumÚappendÚregister_bufferÚstack)Úselfr   r   r   r   r   ÚcÚwindowÚtimer   ÚcutoffÚfilter_Ú	__class__s               €úc/Volumes/fast/ai/experiments/voice-extract-mac/.venv/lib/python3.12/site-packages/julius/lowpass.pyr   zLowPassFilters.__init__H   s�  ø€ ä‰ÑÔÜ˜G“}ˆŒÜˆt�|‰|Ó˜qÒ ÜÐGÓHÐHÜˆt�|‰|Ó˜sÒ"ÜÐFÓGÐGØˆŒØˆŒØˆŒ
Ü˜U¤S°T·\²\Ó)K±\°ÀQÈÃUª!°\Ñ)KÓ%LÑLÈqÑPÓQˆŒØˆ;Ø—.‘. 2Ñ%ˆCØˆŒÜ×"Ñ" 1 t§~¡~Ñ#5¸Ñ#9ÀEÔJˆÜ�|‰|˜TŸ^™^˜O¨T¯^©^¸aÑ-?Ó@ˆØˆÛˆFØ˜Š{Ü×*Ñ*¨4Ó0‘à˜f™* vÑ-´°Q¸±ZÄ$Ç'Á'Ñ5IÈDÑ5PÓ0QÑQ�ð ˜7Ÿ;™;›=Ñ(�Ø�N‰N˜7Õ#ð ð 	×Ñ˜Y¬¯©°GÓ(<ºQÀ¸WÑ(EÕFùò! *Ls   Â
GÂGc                 ó4  — t        |j                  «      }|j                  dd|d   «      }| j                  r.t	        j                  || j
                  | j
                  fd¬«      }| j                  r#t        || j                  | j                  ¬«      }n,t	        j                  || j                  | j                  ¬«      }|j                  dt        | j                  «      «       |j                  d   |d<   |j                  ddd«      j                  |«      S )Néÿÿÿÿr   Ú	replicate)Úmode)r   r   r   )r   ÚshapeÚviewr   ÚFr   r   r   r   r   Úconv1dÚinsertÚlenr   ÚpermuteÚreshape)r)   Úinputr5   Úouts       r0   ÚforwardzLowPassFilters.forwarde   sÉ   € Ü�U—[‘[Ó!ˆØ—
‘
˜2˜q %¨¡)Ó,ˆØ�8Š8Ü—E‘E˜% $§.¡.°$·.±.Ð!AÈÔTˆEØ�8Š8Ü˜U D§L¡L¸¿¹ÔE‰Cä—(‘(˜5 $§,¡,°t·{±{ÔCˆCØ�‰�Qœ˜DŸL™LÓ)Ô*Ø—I‘I˜b‘Mˆˆb‰	Ø�{‰{˜1˜a Ó#×+Ñ+¨EÓ2Ð2ó    c                 ó   — t        | «      S ©Nr	   ©r)   s    r0   Ú__repr__zLowPassFilters.__repr__r   ó   € Ü˜4Ó Ð r@   ©r   Té   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Úfloatr   Úboolr   r   r?   rD   Ú__classcell__©r/   s   @r0   r   r      sU   ø„ ñ3ðj OSØ9=ñG ¨¡ð G¸ð GÀtð GØðGØ(0°©õGò:3ö!r@   r   c                   ó    ‡ — e Zd ZdZ	 	 ddededededee   f
ˆ fd„Ze	d„ «       Z
e	d	„ «       Ze	d
„ «       Ze	d„ «       Ze	d„ «       Zd„ Zd„ Zˆ xZS )ÚLowPassFiltera7  
    Same as `LowPassFilters` but applies a single low pass filter.

    Shape:

        - Input: `[*, T]`
        - Output: `[*, T']`, with `T'=T` if `pad` is True and `stride` is 1.

    >>> lowpass = LowPassFilter(1/4, stride=2)
    >>> x = torch.randn(4, 124)
    >>> list(lowpass(x).shape)
    [4, 62]
    r-   r   r   r   r   c                 óL   •— t         ‰| �  «        t        |g||||«      | _        y rB   )r   r   r   Ú
_lowpasses)r)   r-   r   r   r   r   r/   s         €r0   r   zLowPassFilter.__init__…   s$   ø€ ä‰ÑÔÜ(¨&¨°6¸3ÀÀsÓKˆ�r@   c                 ó4   — | j                   j                  d   S ©Nr   )rS   r   rC   s    r0   r-   zLowPassFilter.cutoffŠ   s   € à�‰×&Ñ& qÑ)Ð)r@   c                 ó.   — | j                   j                  S rB   )rS   r   rC   s    r0   r   zLowPassFilter.strideŽ   s   € à�‰×%Ñ%Ð%r@   c                 ó.   — | j                   j                  S rB   )rS   r   rC   s    r0   r   zLowPassFilter.pad’   ó   € à�‰×"Ñ"Ð"r@   c                 ó.   — | j                   j                  S rB   )rS   r   rC   s    r0   r   zLowPassFilter.zeros–   s   € à�‰×$Ñ$Ð$r@   c                 ó.   — | j                   j                  S rB   )rS   r   rC   s    r0   r   zLowPassFilter.fftš   rX   r@   c                 ó*   — | j                  |«      d   S rU   )rS   )r)   r=   s     r0   r?   zLowPassFilter.forwardž   s   € Ø�‰˜uÓ% aÑ(Ð(r@   c                 ó   — t        | «      S rB   r	   rC   s    r0   rD   zLowPassFilter.__repr__¡   rE   r@   rF   )rH   rI   rJ   rK   rL   r   rM   r   r   Úpropertyr-   r   r   r   r   r?   rD   rN   rO   s   @r0   rQ   rQ   v   s´   ø„ ñð DHØ9=ñL˜uð L¨cð L¸Dð LØðLØ(0°©õLð
 ñ*ó ð*ð ñ&ó ð&ð ñ#ó ð#ð ñ%ó ð%ð ñ#ó ð#ò)ö!r@   rQ   r=   r   r   r   r   r   c                 óJ   —  t        |||||«      j                  | «      | «      S )z[
    Functional version of `LowPassFilters`, refer to this class for more information.
    )r   Úto)r=   r   r   r   r   r   s         r0   Úlowpass_filtersr`   ¥   s*   € ð FŒ>˜' 6¨3°°sÓ;×>Ñ>¸uÓEÀeÓLÐLr@   r-   c                 ó*   — t        | |g||||«      d   S )zƒ
    Same as `lowpass_filters` but with a single cutoff frequency.
    Output will not have a dimension inserted in the front.
    r   )r`   )r=   r-   r   r   r   r   s         r0   Úlowpass_filterrb   ®   s    € ô ˜5 6 (¨F°C¸ÀÓDÀQÑGÐGr@   rF   )rK   r#   Útypingr   r   r   Útorch.nnr   r7   Úcorer   Úfftconvr   Úutilsr
   ÚnnÚModuler   rQ   ÚTensorrL   r   rM   r`   rb   © r@   r0   Ú<module>rl      så   ðñó ß %ã Ý $å Ý Ý ôa!�U—X‘X—_‘_ô a!ôH,!�E—H‘H—O‘Oô ,!ð` 26Ø<@ñM˜5Ÿ<™<ð M°8¸E±?ð MØðMØ*.ðMà ðMà+3°D©>óMð 15Ø;?ñH˜%Ÿ,™,ð H°ð HØðHØ)-ðHàðHà*2°4©.ôHr@   