U
    -eyF                     @   s  d 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 ddlmZmZmZmZ dddgZeddddeZddddddddddd
eej eeej eeeeee eejj e eeejf dddZ!ddddddddd eej eeej eeee ee eejj ejd!	d"dZ"ejeeeeejd#d$d%Z#d&d' Z$d(d) Z%d*d+ Z&d,d- Z'ejejeejd.d/d0Z(dS )1z^
Beat and tempo
==============
.. autosummary::
   :toctree: generated/

   beat_track
   plp
    N   )cache)core)onset)util)	tempogramfourier_tempogram)tempo)ParameterError)moved)AnyCallableOptionalTuple
beat_trackr	   plpzlibrosa.beat.tempoz0.10.0z1.0)Z
moved_fromversionZversion_removedi"V  i   g      ^@d   Tframes)
ysronset_envelope
hop_length	start_bpm	tightnesstrimbpmpriorunits)r   r   r   r   r   r   r   r   r   r   returnc        
         C   s   |dkr,| dkrt dtj| ||tjd}| sFdtjg tdfS |dkrdt|||||dd }t	||t
|| ||}
|	dkr||
fS |	dkr|tj|
|d	fS |	d
kr|tj|
||dfS t d|	 d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=(n,)] 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]
        (optional) If provided, use ``bpm`` as the tempo instead of
        estimating it from ``onsets``.
    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.

    Returns
    -------
    tempo : float [scalar, non-negative]
        estimated global tempo (in beats per minute)
    beats : np.ndarray [shape=(m,)]
        estimated beat event locations in the specified units
        (default is frame indices)
    .. 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])

    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   Z	aggregater   Zdtype)r   r   r   r   r   r   Zsamples)r   time)r   r   zInvalid unit type: )r
   r   onset_strengthnpmediananyarrayint_tempo__beat_trackerfloatr   Zframes_to_samplesZframes_to_time)r   r   r   r   r   r   r   r   r   r   beats r-   M/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/librosa/beat.pyr   #   s:       	i     i,  )r   r   r   r   
win_length	tempo_min	tempo_maxr   )	r   r   r   r   r0   r1   r2   r   r   c                 C   sV  |dkrt j| ||tjd}|dk	rH|dk	rH||krHtd| d| t||||d}tj|||d}	|dk	rd|d|	|k ddf< |dk	rd|d|	|kddf< tj	|	|j
d	d
}	tdt| }
|dk	r|
||	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   r0   )r   r   r0   r   .)ndimZaxesg    .AT)axisZkeepdims      ?r   )r   Zn_fftlength)r5   )r   r#   r$   r%   r
   r   r   Zfourier_tempo_frequenciesr   Z	expand_tor4   log1pabsZlogpdfmaxZtinyZistftshapeZclip	normalize)r   r   r   r   r0   r1   r2   r   ZftgramZtempo_frequenciesZftmagZpeak_valuespulser-   r-   r.   r      sT          &   )r   r   fft_resr   r   r   c           
      C   s   |dkrt dtd| | }t| |}t|||\}}t|g}	||	d  dkrh|	||	d   qDtj|	ddd td}	t	||	|}	|	S )a  Tracks beats in an onset strength envelope.

    Parameters
    ----------
    onset_envelope : np.ndarray [shape=(n,)]
        onset strength envelope
    bpm : float [scalar]
        tempo estimate
    fft_res : float [scalar]
        resolution of the fft (sr / hop_length)
    tightness : float [scalar]
        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 must be strictly positiveg      N@r7   Nr!   )
r
   round__beat_local_score__beat_track_dp__last_beatappendr$   r'   r(   __trim_beats)
r   r   r?   r   r   period
localscorebacklinkcumscorer,   r-   r-   r.   r*     s    

r*   c                 C   s    | j dd}|dkr| | } | S )z1Map onset strength function into the range [0, 1]r   )Zddofr   )Zstd)ZonsetsZnormr-   r-   r.   __normalize_onsets  s    rJ   c                 C   s<   t dt | |d d | d  }tjt| |dS )z?Construct the local score for an onset envlope and given periodg      r   g      @@   same)r$   exparangescipysignalconvolverJ   )r   rF   windowr-   r-   r.   rA     s    (rA   c                 C   s  t j| td}t | }t jd| t |d  d td}|dkrLtd| t | | d  }d}t| D ]\}}	t dt	|d  t
|}
| }||
d |||
d   ||
d< t |}|	||  ||< |r|	d	|   k rd
||< n|| ||< d}|d }qr||fS )z&Core dynamic program for beat trackingr!   r3   rK   r   r   z#tightness must be strictly positiveTNg{Gz?r7   F)r$   Z
zeros_liker(   rN   r@   r
   log	enumeratemaximumminlencopyZargmaxr;   )rG   rF   r   rH   rI   rR   ZtxwtZ
first_beatiZscore_iZz_pad
candidatesZbeat_locationr-   r-   r.   rB     s&    
$$


rB   c                 C   s8   t | }t| t| }t| | d |k S )z1Get the last beat from the cumulative score arrayrK   )r   Zlocalmaxr$   r%   argwherer;   )rI   ZmaxesZ	med_scorer-   r-   r.   rC     s    
rC   )rG   r,   r   r   c                 C   s\   t j| | t jdd}|r6d|d  d  }nd}t||k}|| |  S )z*Remove spurious leading and trailing beats   rL   r6   rK   g        )	rO   rP   rQ   ZhannZmeanr$   r[   rV   r;   )rG   r,   r   Z
smooth_boe	thresholdZvalidr-   r-   r.   rE     s    rE   ))__doc__numpyr$   rO   Zscipy.stats_cacher    r   r   r   featurer   r   r	   r)   Zutil.exceptionsr
   Zutil.decoratorsr   typingr   r   r   r   __all__Zndarrayr+   r(   boolstatsZrv_continuousstrr   r   r*   rJ   rA   rB   rC   rE   r-   r-   r-   r.   <module>   s   


 %
 ?    5+	