
    }Kg,b                     L   d Z ddlZddlZddl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 ddlmZmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZmZmZmZmZ ddlmZ g dZ  eddd      e      Zdddddddddddddeej>                     de deej>                     de!de de d e"d!eeeej>                  f      d"eejF                  jH                     d#e%d$e"d%eeeej>                  f   ej>                  f   fd&Z&ddddd'd(d)dd*deej>                     de deej>                     de!d+e!d,ee    d-ee    d"eejF                  jH                     d%ej>                  fd.Z'dej>                  d!ej>                  d/e de d e"d%ej>                  fd0Z(d1 Z) ejT                  d2d3gd4dd56      d7        Z+ ejT                  d8d9gd:dd6      d;        Z, ejT                  d<d=gd>dd6      d?        Z-d@ Z. ejT                  dAdBgdCdd6      dD        Z/ ejT                  dEdFgdGdd6      dH        Z0y)Iz^
Beat and tempo
==============
.. autosummary::
   :toctree: generated/

   beat_track
   plp
    N   )cache)core)onset)util)	tempogramfourier_tempogram)tempo)ParameterError)moved	vectorize)AnyCallableOptionalTupleUnion)_FloatLike_co)
beat_trackr
   plpzlibrosa.beat.tempoz0.10.0z1.0)
moved_fromversionversion_removedi"V  i   g      ^@d   Tframes)ysronset_envelope
hop_length	start_bpm	tightnesstrimbpmpriorunitssparser   r   r   r   r   r    r!   r"   r#   r$   r%   returnc                 t   |4| t        d      t        j                  | ||t        j                        }|
r(|j
                  dk7  rt        d|j
                   d      |j                         sb|
rdt        j                  g t              fS t        j                  |j                  dd	 t        
      t        j                  |t              fS |t        |||||      }t        j                  |      }t!        j"                  ||j
                  t%        |j
                              }t'        ||t        |      |z  ||      }|
rjt        j(                  |      }|	dk(  r	 ||fS |	dk(  r|t+        j,                  ||      fS |	dk(  r|t+        j.                  |||      fS t        d|	       ||fS )a  Dynamic programming beat tracker.

    Beats are detected in three stages, following the method of [#]_:

      1. Measure onset strength
      2. Estimate tempo from onset correlation
      3. Pick peaks in onset strength approximately consistent with estimated
         tempo

    .. [#] Ellis, Daniel PW. "Beat tracking by dynamic programming."
           Journal of New Music Research 36.1 (2007): 51-60.
           http://labrosa.ee.columbia.edu/projects/beattrack/

    Parameters
    ----------
    y : np.ndarray [shape=(..., n)] or None
        audio time series

    sr : number > 0 [scalar]
        sampling rate of ``y``

    onset_envelope : np.ndarray [shape=(..., m)] or None
        (optional) pre-computed onset strength envelope.

    hop_length : int > 0 [scalar]
        number of audio samples between successive ``onset_envelope`` values

    start_bpm : float > 0 [scalar]
        initial guess for the tempo estimator (in beats per minute)

    tightness : float [scalar]
        tightness of beat distribution around tempo

    trim : bool [scalar]
        trim leading/trailing beats with weak onsets

    bpm : float [scalar] or np.ndarray [shape=(...)]
        (optional) If provided, use ``bpm`` as the tempo instead of
        estimating it from ``onsets``.

        If multichannel, tempo estimates can be provided for all channels.

        Tempo estimates may also be time-varying, in which case the shape
        of ``bpm`` should match that of ``onset_envelope``, i.e.,
        one estimate provided for each frame.

    prior : scipy.stats.rv_continuous [optional]
        An optional prior distribution over tempo.
        If provided, ``start_bpm`` will be ignored.

    units : {'frames', 'samples', 'time'}
        The units to encode detected beat events in.
        By default, 'frames' are used.

    sparse : bool
        If ``True`` (default), detections are returned as an array of frames,
        samples, or time indices (as specified by ``units=``).

        If ``False``, detections are encoded as a dense boolean array where
        ``beats[..., n]`` is true if there's a beat at frame index ``n``.

        .. note:: multi-channel input is only supported when ``sparse=False``.

    Returns
    -------
    tempo : float [scalar, non-negative] or np.ndarray
        estimated global tempo (in beats per minute)

        If multi-channel and ``bpm`` is not provided, a separate
        tempo will be returned for each channel
    beats : np.ndarray
        estimated beat event locations.

        If `sparse=True` (default), beat locations are given in the specified units
        (default is frame indices).

        If `sparse=False` (required for multichannel input), beat events are
        indicated by a boolean for each frame.
    .. note::
        If no onset strength could be detected, beat_tracker estimates 0 BPM
        and returns an empty list.

    Raises
    ------
    ParameterError
        if neither ``y`` nor ``onset_envelope`` are provided,
        or if ``units`` is not one of 'frames', 'samples', or 'time'

    See Also
    --------
    librosa.onset.onset_strength

    Examples
    --------
    Track beats using time series input

    >>> y, sr = librosa.load(librosa.ex('choice'), duration=10)

    >>> tempo, beats = librosa.beat.beat_track(y=y, sr=sr)
    >>> tempo
    135.99917763157896

    Print the frames corresponding to beats

    >>> beats
    array([  3,  21,  40,  59,  78,  96, 116, 135, 154, 173, 192, 211,
           230, 249, 268, 287, 306, 325, 344, 363])

    Or print them as timestamps

    >>> librosa.frames_to_time(beats, sr=sr)
    array([0.07 , 0.488, 0.929, 1.37 , 1.811, 2.229, 2.694, 3.135,
           3.576, 4.017, 4.458, 4.899, 5.341, 5.782, 6.223, 6.664,
           7.105, 7.546, 7.988, 8.429])

    Output beat detections as a boolean array instead of frame indices
    >>> tempo, beats_dense = librosa.beat.beat_track(y=y, sr=sr, sparse=False)
    >>> beats_dense
    array([False, False, False,  True, False, False, False, False,
       False, False, False, False, False, False, False, False,
       False, False, False, False, ..., False, False,  True,
       False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False,
       False])

    Track beats using a pre-computed onset envelope

    >>> onset_env = librosa.onset.onset_strength(y=y, sr=sr,
    ...                                          aggregate=np.median)
    >>> tempo, beats = librosa.beat.beat_track(onset_envelope=onset_env,
    ...                                        sr=sr)
    >>> tempo
    135.99917763157896
    >>> beats
    array([  3,  21,  40,  59,  78,  96, 116, 135, 154, 173, 192, 211,
           230, 249, 268, 287, 306, 325, 344, 363])

    Plot the beat events against the onset strength envelope

    >>> import matplotlib.pyplot as plt
    >>> hop_length = 512
    >>> fig, ax = plt.subplots(nrows=2, sharex=True)
    >>> times = librosa.times_like(onset_env, sr=sr, hop_length=hop_length)
    >>> M = librosa.feature.melspectrogram(y=y, sr=sr, hop_length=hop_length)
    >>> librosa.display.specshow(librosa.power_to_db(M, ref=np.max),
    ...                          y_axis='mel', x_axis='time', hop_length=hop_length,
    ...                          ax=ax[0])
    >>> ax[0].label_outer()
    >>> ax[0].set(title='Mel spectrogram')
    >>> ax[1].plot(times, librosa.util.normalize(onset_env),
    ...          label='Onset strength')
    >>> ax[1].vlines(times[beats], 0, 1, alpha=0.5, color='r',
    ...            linestyle='--', label='Beats')
    >>> ax[1].legend()
    Nz$y or onset_envelope must be providedr   r   r   	aggregater   z'sparse=True (default) does not support zK-dimensional inputs. Either set sparse=False or convert the signal to mono.        dtypeshaper,   )r   r   r   r   r#   ndimaxesr   samples)r   time)r   r   zInvalid unit type: )r   r   onset_strengthnpmedianr1   anyarrayintzerosr/   float
zeros_likebool_tempo
atleast_1dr   	expand_torange__beat_trackerflatnonzeror   frames_to_samplesframes_to_time)r   r   r   r   r   r    r!   r"   r#   r$   r%   _bpmbpm_expandedbeatss                 P/home/alanp/www/video.onchill/myenv/lib/python3.12/site-packages/librosa/beat.pyr   r   %   s   T 9 !GHH--B:
 .%%*F!&&' (IJ K 	K
 "C011HH>#7#7#<EJMM.=? ? {)!
 ==D>>$'5':':',TYY'79L
 ><rZ9OQZ\`aEu%H < i//*MNNf_,,UzbQRR #6ug!>??<    i     i,  )r   r   r   r   
win_length	tempo_min	tempo_maxr#   rM   rN   rO   c                 <   |'t        j                  | ||t        j                        }||||k  rt	        d| d|       t        ||||      }t        j                  |||      }	|d|d|	|k  ddf<   |d|d|	|kD  ddf<   t        j                  |	|j                  d	
      }	t        j                  dt        j                  |      z        }
||
|j                  |	      z  }
|
j                  d	d      }d||
|k  <   |t        j                  |      dz  t        j                  |j                  d	d            z   z  }t        j                   |d||j"                  d         }t        j$                  |dd|      }t        j&                  |d      S )a  Predominant local pulse (PLP) estimation. [#]_

    The PLP method analyzes the onset strength envelope in the frequency domain
    to find a locally stable tempo for each frame.  These local periodicities
    are used to synthesize local half-waves, which are combined such that peaks
    coincide with rhythmically salient frames (e.g. onset events on a musical time grid).
    The local maxima of the pulse curve can be taken as estimated beat positions.

    This method may be preferred over the dynamic programming method of `beat_track`
    when the tempo is expected to vary significantly over time.  Additionally,
    since `plp` does not require the entire signal to make predictions, it may be
    preferable when beat-tracking long recordings in a streaming setting.

    .. [#] Grosche, P., & Muller, M. (2011).
        "Extracting predominant local pulse information from music recordings."
        IEEE Transactions on Audio, Speech, and Language Processing, 19(6), 1688-1701.

    Parameters
    ----------
    y : np.ndarray [shape=(..., n)] or None
        audio time series. Multi-channel is supported.

    sr : number > 0 [scalar]
        sampling rate of ``y``

    onset_envelope : np.ndarray [shape=(..., n)] or None
        (optional) pre-computed onset strength envelope

    hop_length : int > 0 [scalar]
        number of audio samples between successive ``onset_envelope`` values

    win_length : int > 0 [scalar]
        number of frames to use for tempogram analysis.
        By default, 384 frames (at ``sr=22050`` and ``hop_length=512``) corresponds
        to about 8.9 seconds.

    tempo_min, tempo_max : numbers > 0 [scalar], optional
        Minimum and maximum permissible tempo values.  ``tempo_max`` must be at least
        ``tempo_min``.

        Set either (or both) to `None` to disable this constraint.

    prior : scipy.stats.rv_continuous [optional]
        A prior distribution over tempo (in beats per minute).
        By default, a uniform prior over ``[tempo_min, tempo_max]`` is used.

    Returns
    -------
    pulse : np.ndarray, shape=[(..., n)]
        The estimated pulse curve.  Maxima correspond to rhythmically salient
        points of time.

        If input is multi-channel, one pulse curve per channel is computed.

    See Also
    --------
    beat_track
    librosa.onset.onset_strength
    librosa.feature.fourier_tempogram

    Examples
    --------
    Visualize the PLP compared to an onset strength envelope.
    Both are normalized here to make comparison easier.

    >>> y, sr = librosa.load(librosa.ex('brahms'))
    >>> onset_env = librosa.onset.onset_strength(y=y, sr=sr)
    >>> pulse = librosa.beat.plp(onset_envelope=onset_env, sr=sr)
    >>> # Or compute pulse with an alternate prior, like log-normal
    >>> import scipy.stats
    >>> prior = scipy.stats.lognorm(loc=np.log(120), scale=120, s=1)
    >>> pulse_lognorm = librosa.beat.plp(onset_envelope=onset_env, sr=sr,
    ...                                  prior=prior)
    >>> melspec = librosa.feature.melspectrogram(y=y, sr=sr)

    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots(nrows=3, sharex=True)
    >>> librosa.display.specshow(librosa.power_to_db(melspec,
    ...                                              ref=np.max),
    ...                          x_axis='time', y_axis='mel', ax=ax[0])
    >>> ax[0].set(title='Mel spectrogram')
    >>> ax[0].label_outer()
    >>> ax[1].plot(librosa.times_like(onset_env),
    ...          librosa.util.normalize(onset_env),
    ...          label='Onset strength')
    >>> ax[1].plot(librosa.times_like(pulse),
    ...          librosa.util.normalize(pulse),
    ...          label='Predominant local pulse (PLP)')
    >>> ax[1].set(title='Uniform tempo prior [30, 300]')
    >>> ax[1].label_outer()
    >>> ax[2].plot(librosa.times_like(onset_env),
    ...          librosa.util.normalize(onset_env),
    ...          label='Onset strength')
    >>> ax[2].plot(librosa.times_like(pulse_lognorm),
    ...          librosa.util.normalize(pulse_lognorm),
    ...          label='Predominant local pulse (PLP)')
    >>> ax[2].set(title='Log-normal tempo prior, mean=120', xlim=[5, 20])
    >>> ax[2].legend()

    PLP local maxima can be used as estimates of beat positions.

    >>> tempo, beats = librosa.beat.beat_track(onset_envelope=onset_env)
    >>> beats_plp = np.flatnonzero(librosa.util.localmax(pulse))
    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots(nrows=2, sharex=True, sharey=True)
    >>> times = librosa.times_like(onset_env, sr=sr)
    >>> ax[0].plot(times, librosa.util.normalize(onset_env),
    ...          label='Onset strength')
    >>> ax[0].vlines(times[beats], 0, 1, alpha=0.5, color='r',
    ...            linestyle='--', label='Beats')
    >>> ax[0].legend()
    >>> ax[0].set(title='librosa.beat.beat_track')
    >>> ax[0].label_outer()
    >>> # Limit the plot to a 15-second window
    >>> times = librosa.times_like(pulse, sr=sr)
    >>> ax[1].plot(times, librosa.util.normalize(pulse),
    ...          label='PLP')
    >>> ax[1].vlines(times[beats_plp], 0, 1, alpha=0.5, color='r',
    ...            linestyle='--', label='PLP Beats')
    >>> ax[1].legend()
    >>> ax[1].set(title='librosa.beat.plp', xlim=[5, 20])
    >>> ax[1].xaxis.set_major_formatter(librosa.display.TimeFormatter())
    Nr(   z
tempo_max=z must be larger than tempo_min=)r   r   r   rM   )r   r   rM   r   .r0   g    .AT)axiskeepdims      ?r   r-   )r   n_fftlengthrR   )r   r5   r6   r7   r   r	   r   fourier_tempo_frequenciesr   rA   r1   log1pabslogpdfmaxtinyistftr/   clip	normalize)r   r   r   r   rM   rN   rO   r#   ftgramtempo_frequenciesftmagpeak_valuespulses                rJ   r   r     s   N --B:
 !69	;Q#B9+N
 	

 %	F 66* 89s%	114589s%	1145 '8v{{QST HHS266&>)*E/00))d)3K"#F5; dii3&

T
0R)SSSF JJ1J~7K7KB7OE
 GGE1dE*E >>%b))rK   
frame_ratec                    t        j                  |dk        rt        d| d      |dk  rt        d      |j                  d   d| j                  d   fvr%t        d|j                   d| j                         t        j                  |d	z  |z        }t        t        |       |      }t        |||      \  }}t        |      }	t        j                  | t        
      }
t        ||	|
       t        ||
|      }
|
S )a[  Tracks beats in an onset strength envelope.

    Parameters
    ----------
    onset_envelope : np.ndarray [shape=(..., n,)]
        onset strength envelope
    bpm : float [scalar] or np.ndarray [shape=(...)]
        tempo estimate
    frame_rate : float [scalar]
        frame rate of the spectrogram (sr / hop_length, frames per second)
    tightness : float [scalar, positive]
        how closely do we adhere to bpm?
    trim : bool [scalar]
        trim leading/trailing beats with weak onsets?

    Returns
    -------
    beats : np.ndarray [shape=(n,)]
        frame numbers of beat events
    r   zbpm=z must be strictly positivez#tightness must be strictly positiver-   r   zInvalid bpm shape=z% does not match onset envelope shape=g      N@r+   )r6   r8   r   r/   round__beat_local_score__normalize_onsets__beat_track_dp__last_beatr=   r>   __dp_backtrack__trim_beats)r   r"   rf   r    r!   frames_per_beat
localscorebacklinkcumscoretailrI   s              rJ   rC   rC     s   . 
vvcQhtC5(BCDDA~BCC yy}Q 4 4R 8991#))<abpbvbvawxyy hhzD0367O $$6~$FXJ )_iPHh x DMM.5E8T5) %Z=ELrK   c                 `    | j                  ddd      }| |t        j                  |       z   z  S )z2Normalize onset strength by its standard deviationr   r-   T)ddofrR   rS   )stdr   r]   )onsetsnorms     rJ   rj   rj     s/    ::12:5DTDIIf--..rK   z(void(float32[:], float32[:], float32[:])z(void(float64[:], float64[:], float64[:])z(t),(n)->(t)F)nopythonr   c           
      ~   t        |       }t        |      dk(  rt        j                  dt        j                  |d    |d   dz         dz  |d   z  dz  z        }t        |      }t	        t        |             D ]]  }d||<   t	        t        d||dz  z   |z
  dz         t        ||dz  z   |            D ]!  }||xx   ||   | ||dz  z   |z
     z  z  cc<   # _ y t        |      t        |       k(  rt	        t        |             D ]  }t        j                  dt        j                  ||    ||   dz         dz  ||   z  dz  z        }dt        ||         z  dz   }d||<   t	        t        d||dz  z   |z
  dz         t        ||dz  z   |            D ]!  }||xx   ||   | ||dz  z   |z
     z  z  cc<   #  y y )Nr   g      r   g      @@   r*   )lenr6   exparangerB   r\   minr:   )r   ro   rp   NwindowKiks           rJ   ri   ri     s    	NA
?q  		?1+=*=q?QTU?U VY] ]`opq`r rwxxxyKs>*+AJqM 3q!a1f*q.1"45s1qAv:q7IJ1^A1HaK-H!HH K	 , 
_	^!4	4 s>*+AVVDBIIq/A.A?STCUXYCY$Z]a$adstudv$v{|#||}FC*++a/AJqM3q!a1f*q.1"45s1qAv:q7IJ1^AQJN-K!KK K , 
5rK   z;void(float32[:], float32[:], float32, int32[:], float32[:])z;void(float64[:], float64[:], float32, int32[:], float64[:])z(t),(n),()->(t),(t)c           
      2   d| j                         z  }d}d|d<   | d   |d<   t        t        |      dkD        }t        |       D ]  \  }}	t        j
                   }
d}t        |t	        j                  |||z     dz        z
  |d|||z     z  z
  dz
  d      D ]S  }|dk  r nL||   |t	        j                  ||z
        t	        j                  |||z           z
  dz  z  z
  }||
kD  sP|}
|}U |dk\  r	|	|
z   ||<   n|	||<   |r|	|k  rd||<   |||<   d} y)	z&Core dynamic program for beat trackingg{Gz?Tr-   r   r   r{   FN)	r\   r:   r|   	enumerater6   infrB   rh   log)rp   ro   r    rq   rr   score_thresh
first_beattvr   score_i
best_scorebeat_locationlocscores                 rJ   rk   rk   (  s[    *..**L JHQKQ-HQK 
S!A%	&B
+
7vvX
 RXXob1f&=&ABBAO\^ab\bLcHcDcfgDgilmCQwSMIC266/Z\_`Z`JaCb1bef0f$ffEz!"
 # n A!J.HQK "HQK 'L0HQK'HQKJ7 ,rK   z+void(float32[:], bool_[:], bool_, bool_[:])z+void(float64[:], bool_[:], bool_, bool_[:])z(t),(t),()->(t)c                    ||dd t        j                  d      }t        j                  | |   |      t        |      dz  t        |       t        |      dz  z    }|rd|dz  j	                         dz  z  }nd}d}| |   |k  rd||<   |dz  }| |   |k  rt        |       dz
  }| |   |k  rd||<   |dz  }| |   |k  ry)	zCRemove spurious leading and trailing beats from the detection arrayN   r{   rT   r*   r   Fr   )r6   hanningconvolver|   mean)rp   rI   r!   beats_trimmedw
smooth_boe	thresholdns           rJ   rn   rn   [  s     M! 	

1A Z.23q619S_SQRVUVY=VWJ JM//1367		 	
A
Q-9
$ a	Q Q-9
$ 	J!A
Q-9
$ a	Q Q-9
$ 	rK   c                 j   t        j                  | d       }t        j                  j	                  | |      }t        j                  j                  |d      }dt        j                  j                  |      z  }t        j                  | j                  dd t              }t        | |||       |S )z/Identify the position of the last detected beatr-   rW   )datamaskrT   Nr.   )r   localmaxr6   mamasked_arrayr7   getdataemptyr/   r:   __last_beat_selector)rr   r   masked_scoresmedians
thresholdsrs   s         rJ   rl   rl     s     MM(,,DEE&&H4&@Meell=rl2Gruu}}W--J 88(.."-S9D4T:KrK   z-void(float32[:], bool_[:], float32, int64[:])z-void(float64[:], bool_[:], float64, int64[:])z(t),(t),()->()c                 r    t        |       dz
  }||d<   |dk\  r||   s| |   |k\  r||d<   y|dz  }|dk\  ryy)zmVectorized helper to identify the last valid beat position:

    cumscore[n] > threshold and not mask[n]
    r   r   N)r|   )rr   r   r   outr   s        rJ   r   r     sR     	HACF
q&Aw8A;)3CFFA q&rK   zvoid(int32[:], int32, bool_[:])zvoid(int64[:], int64, bool_[:])z(t),()->(t)c                 4    |}|dk\  rd||<   | |   }|dk\  ryy)z>Populate the beat indicator array from a sequence of backlinksr   TN )	backlinksrs   rI   r   s       rJ   rm   rm     s+     	A
q&aaL q&rK   )1__doc__numpyr6   scipyscipy.statsnumba_cacher    r   r   r   featurer   r	   r
   r?   util.exceptionsr   util.decoratorsr   r   typingr   r   r   r   r   _typingr   __all__ndarrayr<   r:   r>   statsrv_continuousstrr   r   rC   rj   guvectorizeri   rk   rn   rl   r   rm   r   rK   rJ   <module>r      sd           1 $ + - 8 8 "
( 	X-xQVW
	 #+/6:15]

] 	] RZZ(	]
 ] ] ] ] 
%rzz12	3] EKK--.] ] ] 5

*+RZZ78]D #+/!#!$15z*

z* 	z* RZZ(	z*
 z* z* z* z* EKK--.z* ZZz*z3JJ3%'ZZ3=B3OT3\`3ZZ3n/ 66	
 	U$L$LD II	
 	T#)#)X 55
 		< ;;	
 	T

  --	
 	T

rK   