o
    ib                     @   sn  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 dd	lmZ dd
lmZ ddlmZmZmZ ddlmZ g dZed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jj d"ed#ed$eeeejf ejf fd%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jj d$ejfd.d/Z!dejd ejd0ededed$ejfd1d2Z"d3d4 Z#ej$d5d6gd7dd8d9d:d; Z%ej$d<d=gd>ddd9d?d@ Z&ej$dAdBgdCddd9dDdE Z'dFdG Z(ej$dHdIgdJddd9dKdL Z)ej$dMdNgdOddd9dPdQ Z*dS )Rz^
Beat and tempo
==============
.. autosummary::
   :toctree: generated/

   beat_track
   plp
    N   )core)onset)util)fourier_tempogram)tempo)ParameterError)moved)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                 C   sP  |du r| du rt dtj| ||tjd}|
r&|jdkr&t d|j d| sH|
r5dtjg tdfS tj	|j
dd	 td
tj|tdfS |du rUt|||||d}t|}tj||jt|jd}t||t|| ||}|
rt|}|	dkr	 ||fS |	dkr|tj||dfS |	dkr|tj|||d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.

        .. note::
            By default, the tempo is returned as an ndarray even for mono input.
            In this case, the array will have a single element and be one-dimensional.
            This is to ensure consistent return types for multi-channel input.
    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medianr*   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beats rC   J/home/ubuntu/transcripts/venv/lib/python3.10/site-packages/librosa/beat.pyr   $   sT    2


	
r   i     i,  )r   r   r   r   
win_length	tempo_min	tempo_maxr   rF   rG   rH   c                 C   sV  |du rt j| ||tjd}|dur$|dur$||kr$td| d| t||||d}tj|||d}	|durCd|d|	|k ddf< |durRd|d|	|kddf< tj	|	|j
d	d
}	tdt| }
|durp|
||	7 }
|
jd	dd}d||
|k < |t|d t|jd	dd  }tj|d||jd d}t|dd|}tj|d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   rF   )r   r   rF   r   .r)   g    .AT)axiskeepdims      ?r   r&   )r   n_fftlengthrJ   )r   r.   r/   r0   r   r   r   fourier_tempo_frequenciesr   r:   r*   log1pabslogpdfmaxtinyistftr(   clip	normalize)r   r   r   r   rF   rG   rH   r   ftgramtempo_frequenciesftmagpeak_valuespulserC   rC   rD   r     sD    
&r   
frame_ratec                 C   s   t |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 |d	 | }tt| |}t|||\}}t|}	t j	| t
d
}
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$   )r/   r1   r   r(   round__beat_local_score__normalize_onsets__beat_track_dp__last_beatr6   r7   __dp_backtrack__trim_beats)r   r   r^   r   r   frames_per_beat
localscorebacklinkcumscoretailrB   rC   rC   rD   r<     s   r<   c                 C   s"   | j dddd}| |t|   S )z2Normalize onset strength by its standard deviationr   r&   T)ddofrJ   rK   )stdr   rU   )onsetsnormrC   rC   rD   ra     s   ra   z(void(float32[:], float32[:], float32[:])z(void(float64[:], float64[:], float64[:])z(t),(n)->(t)F)nopythoncachec              
   C   s  t | }t |dkretdt|d  |d d d |d  d  }t |}tt | D ]4}d||< ttd||d  | d t||d  |D ]}||  || | ||d  |   7  < qKq.d S t |t | krtt | D ]Z}tdt||  || d d ||  d  }dt||  d }d||< ttd||d  | d t||d  |D ]}||  || | ||d  |   7  < qqsd S d S )Nr   g      r   g      @@   r#   )lenr/   exparanger;   rT   minr3   )r   rf   rg   NwindowKikrC   rC   rD   r`     s(   42*42*r`   z;void(float32[:], float32[:], float32, int32[:], float32[:])z;void(float64[:], float64[:], float32, int32[:], float64[:])z(t),(n),()->(t),(t)c              
   C   s  d|    }d}d|d< | d |d< tt|dk}t| D ]n\}}	tj }
d}t|t|||  d  |d|||    d dD ](}|dk rK n!|| |t|| t|||   d   }||
krk|}
|}qC|dkrw|	|
 ||< n|	||< |r|	|k rd||< q|||< d}qdS )	z&Core dynamic program for beat trackingg{Gz?Tr&   r   r   rq   FN)	rT   r3   rr   	enumerater/   infr;   r_   log)rg   rf   r   rh   ri   score_thresh
first_beattvry   score_i
best_scorebeat_locationlocscorerC   rC   rD   rb   .  s0   
:0
rb   z+void(float32[:], bool_[:], bool_, bool_[:])z+void(float64[:], bool_[:], bool_, bool_[:])z(t),(t),()->(t)c                 C   s   ||dd< t d}t | | |t|d t| t|d   }|r0d|d  d  }nd}d}| | |krHd||< |d7 }| | |ks:t| d }| | |krbd||< |d8 }| | |ksTdS )	zCRemove spurious leading and trailing beats from the detection arrayN   rq   rL   r#   r   Fr   )r/   hanningconvolverr   mean)rg   rB   r   beats_trimmedw
smooth_boe	thresholdnrC   rC   rD   re   a  s"   
0re   c                 C   sj   t j| dd }tjj| |d}tjj|dd}dtj| }tj| jdd t	d}t
| ||| |S )z/Identify the position of the last detected beatr&   rO   )datamaskrL   Nr'   )r   localmaxr/   mamasked_arrayr0   getdataemptyr(   r3   __last_beat_selector)ri   r   masked_scoresmedians
thresholdsrj   rC   rC   rD   rc     s   rc   z-void(float32[:], bool_[:], float32, int64[:])z-void(float64[:], bool_[:], float64, int64[:])z(t),(t),()->()c                 C   sT   t | d }||d< |dkr(|| s| | |kr||d< dS |d8 }|dksdS dS )zmVectorized helper to identify the last valid beat position:

    cumscore[n] > threshold and not mask[n]
    r   r   N)rr   )ri   r   r   outr   rC   rC   rD   r     s   r   zvoid(int32[:], int32, bool_[:])zvoid(int64[:], int64, bool_[:])z(t),()->(t)c                 C   s,   |}|dkrd||< | | }|dksdS dS )z>Populate the beat indicator array from a sequence of backlinksr   TNrC   )	backlinksrj   rB   r   rC   rC   rD   rd     s
   
rd   )+__doc__numpyr/   scipyscipy.statsnumba r   r   r   featurer   r   r8   util.exceptionsr   util.decoratorsr	   typingr
   r   r   _typingr   __all__ndarrayr5   r3   r7   statsrv_continuousstrr   r   r<   ra   guvectorizer`   rb   re   rc   r   rd   rC   rC   rC   rD   <module>   s  
	


 j
	

 >
7
"
,

