
    }Kg-                      d Z ddlm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mZmZmZmZmZmZmZmZmZmZ ddl m!Z! ddl"m#Z#m$Z$m%Z% dZ&g dZ'dddd	 	 	 	 	 	 	 	 	 	 	 	 	 dkdZ( ed       e       ddld       Z)dddmdZ*dndZ+dodZ,dd	 	 	 	 	 	 	 	 	 dpdZ-	 	 	 	 	 	 	 	 dqdZ.dd	 	 	 	 	 	 	 	 	 dpdZ/ddd d!	 	 	 	 	 	 	 	 	 drd"Z0ed#d#d#d$	 	 	 	 	 	 	 	 	 dsd%       Z1ed#d#d&	 	 	 	 	 	 	 	 	 dtd'       Z1dddd$	 	 	 	 	 	 	 	 	 dud(Z1 ed)      ejd                  dddd*	 	 	 	 	 	 	 	 	 	 	 dvd+       Z3ejh                  d,        Z5ejh                  d-        Z6 ejn                  g d.d/d d 0      d1        Z8 ejn                  g d.d/d d 0      d2        Z9dddwd3Z:dddwd4Z; ejn                  g d5d6d d 7      d8        Z<d dd9	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dxd:Z= ed)      d;dd<	 	 	 	 	 	 	 dyd=       Z>dej~                  d>	 	 	 	 	 	 	 dzd?Z@dddd d@	 	 	 	 	 	 	 	 	 	 	 d{dAZA ed)      dd ddB	 	 	 	 	 	 	 	 	 	 	 d|dC       ZBdddD	 	 	 	 	 	 	 	 	 d}dEZCd~dFZDddGddHZEdddI	 	 	 	 	 	 	 ddJZF ej                  d d 7      dddKddL       ZHdddK	 	 	 	 	 	 	 ddMZI edNeej                  ej                  j                  f   O      ZMed#d#dKddP       ZNed#d#dK	 	 	 	 	 	 	 ddQ       ZNdddK	 	 	 	 	 	 	 ddRZNddddSZOej                  dTddUZQej~                  dTddVZR ej                  d d 7      dW        ZSddddXZT ej                  d d 7      dY        ZUddddZZV ej                  d[d\gd d d]      dd^       ZXeeYd_f   ZZ ed`eeZej                  f   O      Z[dddaZ\ ej                  dbdcgd d d]      ddd       Z]ee^dedff   Z_ed#dgddh       Z`ed#dgddi       Z`ddg	 	 	 	 	 ddjZ`y)zUtility functions    )annotationsN)
as_strided   )cache   )ParameterError)
Deprecated)	ArrayLike	DTypeLike)AnyCallableIterableListDictOptionalSequenceTupleTypeVarUnionoverload)Literal)_SequenceLike_FloatLike_co_ComplexLike_coi   )MAX_MEM_BLOCKframe
pad_center	expand_to
fix_lengthvalid_audio	valid_intis_positive_intvalid_intervals
fix_frames	axis_sortlocalmaxlocalmin	normalize	peak_picksparsify_rowsshearstackfill_off_diagonalindex_to_slicesyncsoftmaskbuf_to_floattinycyclic_gradient	dtype_r2c	dtype_c2rcount_unique	is_uniqueabs2phasorF)axis	writeablesubokc               `   t        j                  | d|      } | j                  |   |k  r t        d| j                  |   dd|d      |dk  rt        d|d      | j                  t        | j                  |   g      z   }t        | j                        }||xx   |dz
  z  cc<   t        |      t        |g      z   }t        | ||||      }	|d	k  r|dz
  }
n|dz   }
t        j                  |	d
|
      }	t        d      g|	j                  z  }t        d	d|      ||<   |	t        |         S )a  Slice a data array into (overlapping) frames.

    This implementation uses low-level stride manipulation to avoid
    making a copy of the data.  The resulting frame representation
    is a new view of the same input data.

    For example, a one-dimensional input ``x = [0, 1, 2, 3, 4, 5, 6]``
    can be framed with frame length 3 and hop length 2 in two ways.
    The first (``axis=-1``), results in the array ``x_frames``::

        [[0, 2, 4],
         [1, 3, 5],
         [2, 4, 6]]

    where each column ``x_frames[:, i]`` contains a contiguous slice of
    the input ``x[i * hop_length : i * hop_length + frame_length]``.

    The second way (``axis=0``) results in the array ``x_frames``::

        [[0, 1, 2],
         [2, 3, 4],
         [4, 5, 6]]

    where each row ``x_frames[i]`` contains a contiguous slice of the input.

    This generalizes to higher dimensional inputs, as shown in the examples below.
    In general, the framing operation increments by 1 the number of dimensions,
    adding a new "frame axis" either before the framing axis (if ``axis < 0``)
    or after the framing axis (if ``axis >= 0``).

    Parameters
    ----------
    x : np.ndarray
        Array to frame
    frame_length : int > 0 [scalar]
        Length of the frame
    hop_length : int > 0 [scalar]
        Number of steps to advance between frames
    axis : int
        The axis along which to frame.
    writeable : bool
        If ``False``, then the framed view of ``x`` is read-only.
        If ``True``, then the framed view is read-write.  Note that writing to the framed view
        will also write to the input array ``x`` in this case.
    subok : bool
        If True, sub-classes will be passed-through, otherwise the returned array will be
        forced to be a base-class array (default).

    Returns
    -------
    x_frames : np.ndarray [shape=(..., frame_length, N_FRAMES, ...)]
        A framed view of ``x``, for example with ``axis=-1`` (framing on the last dimension)::

            x_frames[..., j] == x[..., j * hop_length : j * hop_length + frame_length]

        If ``axis=0`` (framing on the first dimension), then::

            x_frames[j] = x[j * hop_length : j * hop_length + frame_length]

    Raises
    ------
    ParameterError
        If ``x.shape[axis] < frame_length``, there is not enough data to fill one frame.

        If ``hop_length < 1``, frames cannot advance.

    See Also
    --------
    numpy.lib.stride_tricks.as_strided

    Examples
    --------
    Extract 2048-sample frames from monophonic signal with a hop of 64 samples per frame

    >>> y, sr = librosa.load(librosa.ex('trumpet'))
    >>> frames = librosa.util.frame(y, frame_length=2048, hop_length=64)
    >>> frames
    array([[-1.407e-03, -2.604e-02, ..., -1.795e-05, -8.108e-06],
           [-4.461e-04, -3.721e-02, ..., -1.573e-05, -1.652e-05],
           ...,
           [ 7.960e-02, -2.335e-01, ..., -6.815e-06,  1.266e-05],
           [ 9.568e-02, -1.252e-01, ...,  7.397e-06, -1.921e-05]],
          dtype=float32)
    >>> y.shape
    (117601,)

    >>> frames.shape
    (2048, 1806)

    Or frame along the first axis instead of the last:

    >>> frames = librosa.util.frame(y, frame_length=2048, hop_length=64, axis=0)
    >>> frames.shape
    (1806, 2048)

    Frame a stereo signal:

    >>> y, sr = librosa.load(librosa.ex('trumpet', hq=True), mono=False)
    >>> y.shape
    (2, 117601)
    >>> frames = librosa.util.frame(y, frame_length=2048, hop_length=64)
    (2, 2048, 1806)

    Carve an STFT into fixed-length patches of 32 frames with 50% overlap

    >>> y, sr = librosa.load(librosa.ex('trumpet'))
    >>> S = np.abs(librosa.stft(y))
    >>> S.shape
    (1025, 230)
    >>> S_patch = librosa.util.frame(S, frame_length=32, hop_length=16)
    >>> S_patch.shape
    (1025, 32, 13)
    >>> # The first patch contains the first 32 frames of S
    >>> np.allclose(S_patch[:, :, 0], S[:, :32])
    True
    >>> # The second patch contains frames 16 to 16+32=48, and so on
    >>> np.allclose(S_patch[:, :, 1], S[:, 16:48])
    True
    F)copyr=   zInput is too short (n=dz) for frame_length=r   zInvalid hop_length: )stridesshaper=   r<   r   r:   N)nparrayrB   r   rA   tuplelistr   moveaxisslicendim)xframe_length
hop_lengthr;   r<   r=   out_stridesx_shape_trimmed	out_shapexwtarget_axisslicess               V/home/alanp/www/video.onchill/myenv/lib/python3.12/site-packages/librosa/util/utils.pyr   r   H   sE   F 	e,Awwt}|#$QWWT]1$55HVWHXY
 	
 A~3Jq>BCC ))eQYYt_$566K 177mOD\A--o&~)>>I		;iu	
B axQhQh	R[	)B Dk]RWW$FD*-F4LeFm       )level)monoc                  t        | t        j                        st        d      t        j                  | j
                  t        j                        st        d      | j                  dk(  rt        d| j                         t        |t              rd}|r5| j                  dk7  r&t        d| j                  dd	| j                         t        j                  |       j                         st        d
      y)af  Determine whether a variable contains valid audio data.

    The following conditions must be satisfied:

    - ``type(y)`` is ``np.ndarray``
    - ``y.dtype`` is floating-point
    - ``y.ndim != 0`` (must have at least one dimension)
    - ``np.isfinite(y).all()`` samples must be all finite values

    If ``mono`` is specified, then we additionally require
    - ``y.ndim == 1``

    Parameters
    ----------
    y : np.ndarray
        The input data to validate

    mono : bool
        Whether or not to require monophonic audio

        .. warning:: The ``mono`` parameter is deprecated in version 0.9 and will be
          removed in 0.10.

    Returns
    -------
    valid : bool
        True if all tests pass

    Raises
    ------
    ParameterError
        In any of the conditions specified above fails

    Notes
    -----
    This function caches at level 20.

    Examples
    --------
    >>> # By default, valid_audio allows only mono signals
    >>> filepath = librosa.ex('trumpet', hq=True)
    >>> y_mono, sr = librosa.load(filepath, mono=True)
    >>> y_stereo, _ = librosa.load(filepath, mono=False)
    >>> librosa.util.valid_audio(y_mono), librosa.util.valid_audio(y_stereo)
    True, False

    >>> # To allow stereo signals, set mono=False
    >>> librosa.util.valid_audio(y_stereo, mono=False)
    True

    See Also
    --------
    numpy.float32
    z(Audio data must be of type numpy.ndarrayz!Audio data must be floating-pointr   z;Audio data must be at least one-dimensional, given y.shape=Fr   z)Invalid shape for monophonic audio: ndim=r@   z, shape=z%Audio buffer is not finite everywhereT)
isinstancerC   ndarrayr   
issubdtypedtypefloatingrI   rB   r	   isfiniteall)yrW   s     rS   r    r       s    p a$GHH=="++.@AAvv{I!''S
 	
 $
#!7qz!''S
 	
 ;;q>DEErT   castc               t    |t         j                  }t        |      st        d      t	         ||             S )a  Ensure that an input value is integer-typed.
    This is primarily useful for ensuring integrable-valued
    array indices.

    Parameters
    ----------
    x : number
        A scalar value to be cast to int
    cast : function [optional]
        A function to modify ``x`` before casting.
        Default: `np.floor`

    Returns
    -------
    x_int : int
        ``x_int = int(cast(x))``

    Raises
    ------
    ParameterError
        If ``cast`` is provided and is not callable.
    zcast parameter must be callable)rC   floorcallabler   int)rJ   rb   s     rS   r!   r!   ?  s3    . |xxD>>??tAw<rT   c                P    t        | t        t        j                  f      xr | dkD  S )zCheck that x is a positive integer, i.e. 1 or greater.

    Parameters
    ----------
    x : number

    Returns
    -------
    positive : bool
    r   )rY   rf   rC   integerrJ   s    rS   r"   r"   _  s#     a#rzz*+7Q7rT   c                    | j                   dk7  s| j                  d   dk7  rt        d      t        j                  | dddf   | dddf   kD        rt        d|  d      y	)
a  Ensure that an array is a valid representation of time intervals:

        - intervals.ndim == 2
        - intervals.shape[1] == 2
        - intervals[i, 0] <= intervals[i, 1] for all i

    Parameters
    ----------
    intervals : np.ndarray [shape=(n, 2)]
        set of time intervals

    Returns
    -------
    valid : bool
        True if ``intervals`` passes validation.
    r   r:   z intervals must have shape (n, 2)Nr   r   z
intervals=z! must have non-negative durationsT)rI   rB   r   rC   any)	intervalss    rS   r#   r#   n  se    " ~~ioob1Q6?@@	vvi1o	!Q$/0z)4UVWWrT   r;   c                  |j                  dd       | j                  |   }t        ||z
  dz        }dg| j                  z  }|t        ||z
  |z
        f||<   |dk  rt	        d|dd|dd	      t        j                  | |fi |S )
a(  Pad an array to a target length along a target axis.

    This differs from `np.pad` by centering the data prior to padding,
    analogous to `str.center`

    Examples
    --------
    >>> # Generate a vector
    >>> data = np.ones(5)
    >>> librosa.util.pad_center(data, size=10, mode='constant')
    array([ 0.,  0.,  1.,  1.,  1.,  1.,  1.,  0.,  0.,  0.])

    >>> # Pad a matrix along its first dimension
    >>> data = np.ones((3, 5))
    >>> librosa.util.pad_center(data, size=7, axis=0)
    array([[ 0.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  0.],
           [ 1.,  1.,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  1.,  1.],
           [ 1.,  1.,  1.,  1.,  1.],
           [ 0.,  0.,  0.,  0.,  0.],
           [ 0.,  0.,  0.,  0.,  0.]])
    >>> # Or its second dimension
    >>> librosa.util.pad_center(data, size=7, axis=1)
    array([[ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
           [ 0.,  1.,  1.,  1.,  1.,  1.,  0.],
           [ 0.,  1.,  1.,  1.,  1.,  1.,  0.]])

    Parameters
    ----------
    data : np.ndarray
        Vector to be padded and centered
    size : int >= len(data) [scalar]
        Length to pad ``data``
    axis : int
        Axis along which to pad and center the data
    **kwargs : additional keyword arguments
        arguments passed to `np.pad`

    Returns
    -------
    data_padded : np.ndarray
        ``data`` centered and padded to length ``size`` along the
        specified axis

    Raises
    ------
    ParameterError
        If ``size < data.shape[axis]``

    See Also
    --------
    numpy.pad
    modeconstantr   r   r   r   zTarget size (r@   z) must be at least input size ())
setdefaultrB   rf   rI   r   rC   pad)datasizer;   kwargsnlpadlengthss          rS   r   r     s    r fj)

4AqQDh"G3tax$/0GDMaxD8#B1Q%qI
 	
 66$*6**rT   c                  	 t        |      }t        |      | j                  k7  rt	        d| d| j
                         || j                  k  rt	        d| j
                   d|       dg|z  }t        |      D ]  \  }}| j
                  |   ||<    | j                  |      S # t        $ r t        |g      }Y w xY w)a  Expand the dimensions of an input array with

    Parameters
    ----------
    x : np.ndarray
        The input array
    ndim : int
        The number of dimensions to expand to.  Must be at least ``x.ndim``
    axes : int or slice
        The target axis or axes to preserve from x.
        All other axes will have length 1.

    Returns
    -------
    x_exp : np.ndarray
        The expanded version of ``x``, satisfying the following:
            ``x_exp[axes] == x``
            ``x_exp.ndim == ndim``

    See Also
    --------
    np.expand_dims

    Examples
    --------
    Expand a 1d array into an (n, 1) shape

    >>> x = np.arange(3)
    >>> librosa.util.expand_to(x, ndim=2, axes=0)
    array([[0],
       [1],
       [2]])

    Expand a 1d array into a (1, n) shape

    >>> librosa.util.expand_to(x, ndim=2, axes=1)
    array([[0, 1, 2]])

    Expand a 2d array into (1, n, m, 1) shape

    >>> x = np.vander(np.arange(3))
    >>> librosa.util.expand_to(x, ndim=4, axes=[1,2]).shape
    (1, 3, 3, 1)
    zShape mismatch between axes=z and input x.shape=zCannot expand x.shape=z to fewer dimensions ndim=r   )rE   	TypeErrorlenrI   r   rB   	enumeratereshape)rJ   rI   axesaxes_tuprB   iaxis          rS   r   r     s    b!; 8}*8*4GyQ
 	
 aff}$QWWI-GvN
 	
 sTzEH%3WWQZc
 & 99U#  !$=!s   B& &B>=B>c               *   |j                  dd       | j                  |   }||kD  r6t        d      g| j                  z  }t        d|      ||<   | t	        |         S ||k  r1dg| j                  z  }d||z
  f||<   t        j                  | |fi |S | S )am  Fix the length an array ``data`` to exactly ``size`` along a target axis.

    If ``data.shape[axis] < n``, pad according to the provided kwargs.
    By default, ``data`` is padded with trailing zeros.

    Examples
    --------
    >>> y = np.arange(7)
    >>> # Default: pad with zeros
    >>> librosa.util.fix_length(y, size=10)
    array([0, 1, 2, 3, 4, 5, 6, 0, 0, 0])
    >>> # Trim to a desired length
    >>> librosa.util.fix_length(y, size=5)
    array([0, 1, 2, 3, 4])
    >>> # Use edge-padding instead of zeros
    >>> librosa.util.fix_length(y, size=10, mode='edge')
    array([0, 1, 2, 3, 4, 5, 6, 6, 6, 6])

    Parameters
    ----------
    data : np.ndarray
        array to be length-adjusted
    size : int >= 0 [scalar]
        desired length of the array
    axis : int, <= data.ndim
        axis along which to fix length
    **kwargs : additional keyword arguments
        Parameters to ``np.pad``

    Returns
    -------
    data_fixed : np.ndarray [shape=data.shape]
        ``data`` either trimmed or padded to length ``size``
        along the specified axis.

    See Also
    --------
    numpy.pad
    ro   rp   Nr   rq   )rs   rB   rH   rI   rE   rC   rt   )ru   rv   r;   rw   rx   rR   rz   s          rS   r   r     s    T fj)

4A4x+*Q~tE&M""	
T(TYY&D1HvvdG.v..KrT   Tx_minx_maxrt   c                  t        j                  |       } t        j                  | dk        rt        d      |r||t        j                  | ||      } |rRg }||j                  |       ||j                  |       t        j                  t        j                  |      | f      } || | |k\     } || | |k     } t        j                  |       j                  t              }|S )av  Fix a list of frames to lie within [x_min, x_max]

    Examples
    --------
    >>> # Generate a list of frame indices
    >>> frames = np.arange(0, 1000.0, 50)
    >>> frames
    array([   0.,   50.,  100.,  150.,  200.,  250.,  300.,  350.,
            400.,  450.,  500.,  550.,  600.,  650.,  700.,  750.,
            800.,  850.,  900.,  950.])
    >>> # Clip to span at most 250
    >>> librosa.util.fix_frames(frames, x_max=250)
    array([  0,  50, 100, 150, 200, 250])
    >>> # Or pad to span up to 2500
    >>> librosa.util.fix_frames(frames, x_max=2500)
    array([   0,   50,  100,  150,  200,  250,  300,  350,  400,
            450,  500,  550,  600,  650,  700,  750,  800,  850,
            900,  950, 2500])
    >>> librosa.util.fix_frames(frames, x_max=2500, pad=False)
    array([  0,  50, 100, 150, 200, 250, 300, 350, 400, 450, 500,
           550, 600, 650, 700, 750, 800, 850, 900, 950])

    >>> # Or starting away from zero
    >>> frames = np.arange(200, 500, 33)
    >>> frames
    array([200, 233, 266, 299, 332, 365, 398, 431, 464, 497])
    >>> librosa.util.fix_frames(frames)
    array([  0, 200, 233, 266, 299, 332, 365, 398, 431, 464, 497])
    >>> librosa.util.fix_frames(frames, x_max=500)
    array([  0, 200, 233, 266, 299, 332, 365, 398, 431, 464, 497,
           500])

    Parameters
    ----------
    frames : np.ndarray [shape=(n_frames,)]
        List of non-negative frame indices
    x_min : int >= 0 or None
        Minimum allowed frame index
    x_max : int >= 0 or None
        Maximum allowed frame index
    pad : boolean
        If ``True``, then ``frames`` is expanded to span the full range
        ``[x_min, x_max]``

    Returns
    -------
    fixed_frames : np.ndarray [shape=(n_fixed_frames,), dtype=int]
        Fixed frame indices, flattened and sorted

    Raises
    ------
    ParameterError
        If ``frames`` contains negative values
    r   zNegative frame index detected)
rC   asarrayrk   r   clipappendconcatenateuniqueastyperf   )framesr   r   rt   pad_datar   s         rS   r$   r$   T  s    z ZZF	vvfqj<== !U%6.
OOE"OOE"H!5v >?%(%(6*11#6FMrT   .)r;   indexvaluec                    y N Sr;   r   r   s       rS   r%   r%          rT   )r;   r   c                    y r   r   r   s       rS   r%   r%     r   rT   c               V   |t         j                  }| j                  dk7  rt        d       || t        j                  d|z
  | j                              }t        j
                  |      }t        d      g| j                  z  }|||<   |r| t        |         |fS | t        |         S )a6
  Sort an array along its rows or columns.

    Examples
    --------
    Visualize NMF output for a spectrogram S

    >>> # Sort the columns of W by peak frequency bin
    >>> y, sr = librosa.load(librosa.ex('trumpet'))
    >>> S = np.abs(librosa.stft(y))
    >>> W, H = librosa.decompose.decompose(S, n_components=64)
    >>> W_sort = librosa.util.axis_sort(W)

    Or sort by the lowest frequency bin

    >>> W_sort = librosa.util.axis_sort(W, value=np.argmin)

    Or sort the rows instead of the columns

    >>> W_sort_rows = librosa.util.axis_sort(W, axis=0)

    Get the sorting index also, and use it to permute the rows of H

    >>> W_sort, idx = librosa.util.axis_sort(W, index=True)
    >>> H_sort = H[idx, :]

    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots(nrows=2, ncols=2)
    >>> img_w = librosa.display.specshow(librosa.amplitude_to_db(W, ref=np.max),
    ...                                  y_axis='log', ax=ax[0, 0])
    >>> ax[0, 0].set(title='W')
    >>> ax[0, 0].label_outer()
    >>> img_act = librosa.display.specshow(H, x_axis='time', ax=ax[0, 1])
    >>> ax[0, 1].set(title='H')
    >>> ax[0, 1].label_outer()
    >>> librosa.display.specshow(librosa.amplitude_to_db(W_sort,
    ...                                                  ref=np.max),
    ...                          y_axis='log', ax=ax[1, 0])
    >>> ax[1, 0].set(title='W sorted')
    >>> librosa.display.specshow(H_sort, x_axis='time', ax=ax[1, 1])
    >>> ax[1, 1].set(title='H sorted')
    >>> ax[1, 1].label_outer()
    >>> fig.colorbar(img_w, ax=ax[:, 0], orientation='horizontal')
    >>> fig.colorbar(img_act, ax=ax[:, 1], orientation='horizontal')

    Parameters
    ----------
    S : np.ndarray [shape=(d, n)]
        Array to be sorted

    axis : int [scalar]
        The axis along which to compute the sorting values

        - ``axis=0`` to sort rows by peak column index
        - ``axis=1`` to sort columns by peak row index

    index : boolean [scalar]
        If true, returns the index array as well as the permuted data.

    value : function
        function to return the index corresponding to the sort order.
        Default: `np.argmax`.

    Returns
    -------
    S_sort : np.ndarray [shape=(d, n)]
        ``S`` with the columns or rows permuted in sorting order
    idx : np.ndarray (optional) [shape=(d,) or (n,)]
        If ``index == True``, the sorting index used to permute ``S``.
        Length of ``idx`` corresponds to the selected ``axis``.

    Raises
    ------
    ParameterError
        If ``S`` does not have exactly 2 dimensions (``S.ndim != 2``)
    Nr   z'axis_sort is only defined for 2D arraysr   rm   )rC   argmaxrI   r   modargsortrH   rE   )r   r;   r   r   bin_idxidx
sort_slices          rS   r%   r%     s    d }		vv{FGGABFF1t8QVV45G
**W
C+'JJtz"#S((z"##rT   (   )normr;   	thresholdfillc               ~   |t        |       }n|dk  rt        d| d      |dvrt        d| d      t        j                  t        j                  |             st        d      t        j
                  |       j                  t              }d	}|| S |t        j                  k(  rt        j                  ||d
      }n|t        j                   k(  rt        j                  ||d
      }n|dk(  r6|d
u rt        d      t        j                  |dkD  |d
|j                        }nt        j                  t        |      t        j                        rQ|dkD  rLt        j                  ||z  |d
      d|z  z  }||j                   d|z  z  }n-|j"                  |   d|z  z  }nt        dt%        |             ||k  }t        j&                  |       }	|d||<   | |z  |	dd |	S |r5t        j(                  ||<   | |z  |	dd ||	t        j*                  |	      <   |	S t        j                  ||<   | |z  |	dd |	S )a  Normalize an array along a chosen axis.

    Given a norm (described below) and a target axis, the input
    array is scaled so that::

        norm(S, axis=axis) == 1

    For example, ``axis=0`` normalizes each column of a 2-d array
    by aggregating over the rows (0-axis).
    Similarly, ``axis=1`` normalizes each row of a 2-d array.

    This function also supports thresholding small-norm slices:
    any slice (i.e., row or column) with norm below a specified
    ``threshold`` can be left un-normalized, set to all-zeros, or
    filled with uniform non-zero values that normalize to 1.

    Note: the semantics of this function differ from
    `scipy.linalg.norm` in two ways: multi-dimensional arrays
    are supported, but matrix-norms are not.

    Parameters
    ----------
    S : np.ndarray
        The array to normalize

    norm : {np.inf, -np.inf, 0, float > 0, None}
        - `np.inf`  : maximum absolute value
        - `-np.inf` : minimum absolute value
        - `0`    : number of non-zeros (the support)
        - float  : corresponding l_p norm
            See `scipy.linalg.norm` for details.
        - None : no normalization is performed

    axis : int [scalar]
        Axis along which to compute the norm.

    threshold : number > 0 [optional]
        Only the columns (or rows) with norm at least ``threshold`` are
        normalized.

        By default, the threshold is determined from
        the numerical precision of ``S.dtype``.

    fill : None or bool
        If None, then columns (or rows) with norm below ``threshold``
        are left as is.

        If False, then columns (rows) with norm below ``threshold``
        are set to 0.

        If True, then columns (rows) with norm below ``threshold``
        are filled uniformly such that the corresponding norm is 1.

        .. note:: ``fill=True`` is incompatible with ``norm=0`` because
            no uniform vector exists with l0 "norm" equal to 1.

    Returns
    -------
    S_norm : np.ndarray [shape=S.shape]
        Normalized array

    Raises
    ------
    ParameterError
        If ``norm`` is not among the valid types defined above

        If ``S`` is not finite

        If ``fill=True`` and ``norm=0``

    See Also
    --------
    scipy.linalg.norm

    Notes
    -----
    This function caches at level 40.

    Examples
    --------
    >>> # Construct an example matrix
    >>> S = np.vander(np.arange(-2.0, 2.0))
    >>> S
    array([[-8.,  4., -2.,  1.],
           [-1.,  1., -1.,  1.],
           [ 0.,  0.,  0.,  1.],
           [ 1.,  1.,  1.,  1.]])
    >>> # Max (l-infinity)-normalize the columns
    >>> librosa.util.normalize(S)
    array([[-1.   ,  1.   , -1.   ,  1.   ],
           [-0.125,  0.25 , -0.5  ,  1.   ],
           [ 0.   ,  0.   ,  0.   ,  1.   ],
           [ 0.125,  0.25 ,  0.5  ,  1.   ]])
    >>> # Max (l-infinity)-normalize the rows
    >>> librosa.util.normalize(S, axis=1)
    array([[-1.   ,  0.5  , -0.25 ,  0.125],
           [-1.   ,  1.   , -1.   ,  1.   ],
           [ 0.   ,  0.   ,  0.   ,  1.   ],
           [ 1.   ,  1.   ,  1.   ,  1.   ]])
    >>> # l1-normalize the columns
    >>> librosa.util.normalize(S, norm=1)
    array([[-0.8  ,  0.667, -0.5  ,  0.25 ],
           [-0.1  ,  0.167, -0.25 ,  0.25 ],
           [ 0.   ,  0.   ,  0.   ,  0.25 ],
           [ 0.1  ,  0.167,  0.25 ,  0.25 ]])
    >>> # l2-normalize the columns
    >>> librosa.util.normalize(S, norm=2)
    array([[-0.985,  0.943, -0.816,  0.5  ],
           [-0.123,  0.236, -0.408,  0.5  ],
           [ 0.   ,  0.   ,  0.   ,  0.5  ],
           [ 0.123,  0.236,  0.408,  0.5  ]])

    >>> # Thresholding and filling
    >>> S[:, -1] = 1e-308
    >>> S
    array([[ -8.000e+000,   4.000e+000,  -2.000e+000,
              1.000e-308],
           [ -1.000e+000,   1.000e+000,  -1.000e+000,
              1.000e-308],
           [  0.000e+000,   0.000e+000,   0.000e+000,
              1.000e-308],
           [  1.000e+000,   1.000e+000,   1.000e+000,
              1.000e-308]])

    >>> # By default, small-norm columns are left untouched
    >>> librosa.util.normalize(S)
    array([[ -1.000e+000,   1.000e+000,  -1.000e+000,
              1.000e-308],
           [ -1.250e-001,   2.500e-001,  -5.000e-001,
              1.000e-308],
           [  0.000e+000,   0.000e+000,   0.000e+000,
              1.000e-308],
           [  1.250e-001,   2.500e-001,   5.000e-001,
              1.000e-308]])
    >>> # Small-norm columns can be zeroed out
    >>> librosa.util.normalize(S, fill=False)
    array([[-1.   ,  1.   , -1.   ,  0.   ],
           [-0.125,  0.25 , -0.5  ,  0.   ],
           [ 0.   ,  0.   ,  0.   ,  0.   ],
           [ 0.125,  0.25 ,  0.5  ,  0.   ]])
    >>> # Or set to constant with unit-norm
    >>> librosa.util.normalize(S, fill=True)
    array([[-1.   ,  1.   , -1.   ,  1.   ],
           [-0.125,  0.25 , -0.5  ,  1.   ],
           [ 0.   ,  0.   ,  0.   ,  1.   ],
           [ 0.125,  0.25 ,  0.5  ,  1.   ]])
    >>> # With an l1 norm instead of max-norm
    >>> librosa.util.normalize(S, norm=1, fill=True)
    array([[-0.8  ,  0.667, -0.5  ,  0.25 ],
           [-0.1  ,  0.167, -0.25 ,  0.25 ],
           [ 0.   ,  0.   ,  0.   ,  0.25 ],
           [ 0.1  ,  0.167,  0.25 ,  0.25 ]])
    Nr   z
threshold=z must be strictly positive)NFTzfill=z must be None or booleanzInput must be finiter   Tr;   keepdimsz*Cannot normalize with norm=0 and fill=True)r;   r   r\         ?g      zUnsupported norm: )r2   r   rC   r_   r^   absr   floatinfmaxminsumr\   r[   typenumberrv   rB   repr
empty_likenanisnan)
r   r   r;   r   r   mag	fill_normlength	small_idxSnorms
             rS   r(   r(   '  s&   F G		az)4NOPP&&uTF*BCDD66"++a.!344 &&)

5
!C I|	$6	"&&$6	4< !MNNadTK	tDz299	-$(T	t<tL<TD[1I		$D4K8I 1$t*>?? "IMM!E|yv:a L 
 FFyv:a!*bhhuo L FFyv:aLrT   c                0    | d   | d   kD  | d   | d   k\  z  S )z*Numba stencil for local maxima computationr   r:   r   r   ri   s    rS   _localmax_stenr     '     aD1R5LQqTQqT\**rT   c                0    | d   | d   k  | d   | d   k  z  S )z*Numba stencil for local minima computationr   r:   r   r   ri   s    rS   _localmin_stenr     r   rT   )zvoid(int16[:], bool_[:])zvoid(int32[:], bool_[:])zvoid(int64[:], bool_[:])zvoid(float32[:], bool_[:])zvoid(float64[:], bool_[:])z(n)->(n))r   nopythonc                     t        |       |dd y)z+Vectorized wrapper for the localmax stencilN)r   rJ   r`   s     rS   	_localmaxr          !AaDrT   c                     t        |       |dd y)z+Vectorized wrapper for the localmin stencilN)r   r   s     rS   	_localminr   ,  r   rT   c                   | j                  d|      }t        j                  | t              }|j                  d|      }t	        ||       |d   |d   kD  |d<   |S )a  Find local maxima in an array

    An element ``x[i]`` is considered a local maximum if the following
    conditions are met:

    - ``x[i] > x[i-1]``
    - ``x[i] >= x[i+1]``

    Note that the first condition is strict, and that the first element
    ``x[0]`` will never be considered as a local maximum.

    Examples
    --------
    >>> x = np.array([1, 0, 1, 2, -1, 0, -2, 1])
    >>> librosa.util.localmax(x)
    array([False, False, False,  True, False,  True, False,  True], dtype=bool)

    >>> # Two-dimensional example
    >>> x = np.array([[1,0,1], [2, -1, 0], [2, 1, 3]])
    >>> librosa.util.localmax(x, axis=0)
    array([[False, False, False],
           [ True, False, False],
           [False,  True,  True]], dtype=bool)
    >>> librosa.util.localmax(x, axis=1)
    array([[False, False,  True],
           [False, False,  True],
           [False, False,  True]], dtype=bool)

    Parameters
    ----------
    x : np.ndarray [shape=(d1,d2,...)]
        input vector or array
    axis : int
        axis along which to compute local maximality

    Returns
    -------
    m : np.ndarray [shape=x.shape, dtype=bool]
        indicator array of local maximality along ``axis``

    See Also
    --------
    localmin
    r:   r\   .r:   .)swapaxesrC   r   boolr   )rJ   r;   xilmaxlmaxis        rS   r&   r&   =  s`    \ 
B	B ==$'DMM"d#E b% [2g;.E'NKrT   c                   | j                  d|      }t        j                  | t              }|j                  d|      }t	        ||       |d   |d   k  |d<   |S )a  Find local minima in an array

    An element ``x[i]`` is considered a local minimum if the following
    conditions are met:

    - ``x[i] < x[i-1]``
    - ``x[i] <= x[i+1]``

    Note that the first condition is strict, and that the first element
    ``x[0]`` will never be considered as a local minimum.

    Examples
    --------
    >>> x = np.array([1, 0, 1, 2, -1, 0, -2, 1])
    >>> librosa.util.localmin(x)
    array([False,  True, False, False,  True, False,  True, False])

    >>> # Two-dimensional example
    >>> x = np.array([[1,0,1], [2, -1, 0], [2, 1, 3]])
    >>> librosa.util.localmin(x, axis=0)
    array([[False, False, False],
           [False,  True,  True],
           [False, False, False]])

    >>> librosa.util.localmin(x, axis=1)
    array([[False,  True, False],
           [False,  True, False],
           [False,  True, False]])

    Parameters
    ----------
    x : np.ndarray [shape=(d1,d2,...)]
        input vector or array
    axis : int
        axis along which to compute local minimality

    Returns
    -------
    m : np.ndarray [shape=x.shape, dtype=bool]
        indicator array of local minimality along ``axis``

    See Also
    --------
    localmax
    r:   r   r   r   )r   rC   r   r   r   )rJ   r;   r   lminlminis        rS   r'   r'   z  s`    ^ 
B	B ==$'DMM"d#E b% [2g;.E'NKrT   )zKvoid(float32[:], uint32, uint32, uint32, uint32, float32, uint32, bool_[:])zKvoid(float64[:], uint32, uint32, uint32, uint32, float32, uint32, bool_[:])zIvoid(int32[:], uint32, uint32, uint32, uint32, float32, uint32, bool_[:])zIvoid(int64[:], uint32, uint32, uint32, uint32, float32, uint32, bool_[:])z(n),(),(),(),(),(),()->(n))r   r   c                   | d   t        j                  | dt        || j                  d                k\  |d<   |dxx   | d   t        j                  | dt        || j                  d                |z   k\  z  cc<   |d   r|dz   }nd}|| j                  d   k  rt        j                  | t        d||z
        t        ||z   | j                  d                }	| |   |	k(  ||<   ||   s|dz  }gt        j                  | t        d||z
        t        ||z   | j                  d                }
||xx   | |   |
|z   k\  z  cc<   ||   s|dz  }||dz   z  }|| j                  d   k  ryy)z&Vectorized wrapper for the peak-pickerr   Nr   )rC   r   r   rB   mean)rJ   pre_maxpost_maxpre_avgpost_avgdeltawaitpeaksrx   maxnavgns              rS   __peak_pickr     sp    !q!;#h
";<==E!H	!H1#=C!''!*$=!>?%GGHHQx1H
aggaj.vvqQ'	*3qz1771:+FGH aDDLaQxFAwwqQ'	*3qz1771:+FGHaQqTTE\)*QxFA 	
TAX% aggaj.rT   )sparser;   c                  |dk  rt        d      |dk  rt        d      |dk  rt        d      |dk  rt        d      |dk  rt        d      |dk  rt        d      |r(| j                  dk7  rt        d	| j                   d
      t        |t        j                        }t        |t        j                        }t        |t        j                        }t        |t        j                        }t        |t        j                        }t        j
                  | t              }	t        | j                  |d      |||||||	j                  |d             |rt        j                  |	      S |	S )a  Use a flexible heuristic to pick peaks in a signal.

    A sample n is selected as an peak if the corresponding ``x[n]``
    fulfills the following three conditions:

    1. ``x[n] == max(x[n - pre_max:n + post_max])``
    2. ``x[n] >= mean(x[n - pre_avg:n + post_avg]) + delta``
    3. ``n - previous_n > wait``

    where ``previous_n`` is the last sample picked as a peak (greedily).

    This implementation is based on [#]_ and [#]_.

    .. [#] Boeck, Sebastian, Florian Krebs, and Markus Schedl.
        "Evaluating the Online Capabilities of Onset Detection Methods." ISMIR.
        2012.

    .. [#] https://github.com/CPJKU/onset_detection/blob/master/onset_program.py

    Parameters
    ----------
    x : np.ndarray
        input signal to peak picks from
    pre_max : int >= 0 [scalar]
        number of samples before ``n`` over which max is computed
    post_max : int >= 1 [scalar]
        number of samples after ``n`` over which max is computed
    pre_avg : int >= 0 [scalar]
        number of samples before ``n`` over which mean is computed
    post_avg : int >= 1 [scalar]
        number of samples after ``n`` over which mean is computed
    delta : float >= 0 [scalar]
        threshold offset for mean
    wait : int >= 0 [scalar]
        number of samples to wait after picking a peak
    sparse : bool [scalar]
        If `True`, the output are indices of detected peaks.
        If `False`, the output is a dense boolean array of the same
        shape as ``x``.
    axis : int [scalar]
        the axis over which to detect peaks.

    Returns
    -------
    peaks : np.ndarray [shape=(n_peaks,) or shape=x.shape, dtype=int or bool]
        indices of peaks in ``x`` (sparse=True)
        or a boolean array where `peaks[..., n]` indicates a peak at frame index `n` (sparse=False)

    Raises
    ------
    ParameterError
        If any input lies outside its defined range

    Examples
    --------
    >>> y, sr = librosa.load(librosa.ex('trumpet'))
    >>> onset_env = librosa.onset.onset_strength(y=y, sr=sr,
    ...                                          hop_length=512,
    ...                                          aggregate=np.median)
    >>> peaks = librosa.util.peak_pick(onset_env, pre_max=3, post_max=3, pre_avg=3, post_avg=5, delta=0.5, wait=10)
    >>> peaks
    array([  3,  27,  40,  61,  72,  88, 103])

    Using dense output to make a boolean array of peak indicators
    >>> librosa.util.peak_pick(onset_env, pre_max=3, post_max=3, pre_avg=3, post_avg=5,
    ...                        delta=0.5, wait=10, sparse=False)
    array([False, False, ..., False, False])

    >>> import matplotlib.pyplot as plt
    >>> times = librosa.times_like(onset_env, sr=sr, hop_length=512)
    >>> fig, ax = plt.subplots(nrows=2, sharex=True)
    >>> D = np.abs(librosa.stft(y))
    >>> librosa.display.specshow(librosa.amplitude_to_db(D, ref=np.max),
    ...                          y_axis='log', x_axis='time', ax=ax[1])
    >>> ax[0].plot(times, onset_env, alpha=0.8, label='Onset strength')
    >>> ax[0].vlines(times[peaks], 0,
    ...              onset_env.max(), color='r', alpha=0.8,
    ...              label='Selected peaks')
    >>> ax[0].legend(frameon=True, framealpha=0.8)
    >>> ax[0].label_outer()
    r   zpre_max must be non-negativezpre_avg must be non-negativezdelta must be non-negativezwait must be non-negativezpost_max must be positivezpost_avg must be positiver   z'sparse=True (default) does not support zU-dimensional inputs. Either set sparse=False or process each dimension independently.ra   r   r:   )
r   rI   r!   rC   ceil
zeros_liker   r   r   flatnonzero)
rJ   r   r   r   r   r   r   r   r;   r   s
             rS   r)   r)     sV   z {;<<{;<<qy9::ax8991}8991}899!&&A+F66( ST U 	U
 bgg.G0Hbgg.G0HT(DMM!4(E

4$gx(ESWY^YgYghlnpYqr~~e$$LrT   g{Gz?)quantiler\   c                  | j                   dk(  r| j                  d      } n(| j                   dkD  rt        d| j                   d      d|cxk  rdk  sn t        d|d      || j                  }t
        j                  j                  | j                  |	      }t        j                  |       }t        j                  |dd
      }t        j                  |d      }t        j                  ||z  d      }t        j                  ||k  d      }t        |      D ]1  \  }	}
t        j                  ||	   ||	|
f   k\        }| |	|f   ||	|f<   3 |j!                         S )a~	  Return a row-sparse matrix approximating the input

    Parameters
    ----------
    x : np.ndarray [ndim <= 2]
        The input matrix to sparsify.
    quantile : float in [0, 1.0)
        Percentage of magnitude to discard in each row of ``x``
    dtype : np.dtype, optional
        The dtype of the output array.
        If not provided, then ``x.dtype`` will be used.

    Returns
    -------
    x_sparse : ``scipy.sparse.csr_matrix`` [shape=x.shape]
        Row-sparsified approximation of ``x``

        If ``x.ndim == 1``, then ``x`` is interpreted as a row vector,
        and ``x_sparse.shape == (1, len(x))``.

    Raises
    ------
    ParameterError
        If ``x.ndim > 2``

        If ``quantile`` lies outside ``[0, 1.0)``

    Notes
    -----
    This function caches at level 40.

    Examples
    --------
    >>> # Construct a Hann window to sparsify
    >>> x = scipy.signal.hann(32)
    >>> x
    array([ 0.   ,  0.01 ,  0.041,  0.09 ,  0.156,  0.236,  0.326,
            0.424,  0.525,  0.625,  0.72 ,  0.806,  0.879,  0.937,
            0.977,  0.997,  0.997,  0.977,  0.937,  0.879,  0.806,
            0.72 ,  0.625,  0.525,  0.424,  0.326,  0.236,  0.156,
            0.09 ,  0.041,  0.01 ,  0.   ])
    >>> # Discard the bottom percentile
    >>> x_sparse = librosa.util.sparsify_rows(x, quantile=0.01)
    >>> x_sparse
    <1x32 sparse matrix of type '<type 'numpy.float64'>'
        with 26 stored elements in Compressed Sparse Row format>
    >>> x_sparse.todense()
    matrix([[ 0.   ,  0.   ,  0.   ,  0.09 ,  0.156,  0.236,  0.326,
              0.424,  0.525,  0.625,  0.72 ,  0.806,  0.879,  0.937,
              0.977,  0.997,  0.997,  0.977,  0.937,  0.879,  0.806,
              0.72 ,  0.625,  0.525,  0.424,  0.326,  0.236,  0.156,
              0.09 ,  0.   ,  0.   ,  0.   ]])
    >>> # Discard up to the bottom 10th percentile
    >>> x_sparse = librosa.util.sparsify_rows(x, quantile=0.1)
    >>> x_sparse
    <1x32 sparse matrix of type '<type 'numpy.float64'>'
        with 20 stored elements in Compressed Sparse Row format>
    >>> x_sparse.todense()
    matrix([[ 0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.   ,  0.326,
              0.424,  0.525,  0.625,  0.72 ,  0.806,  0.879,  0.937,
              0.977,  0.997,  0.997,  0.977,  0.937,  0.879,  0.806,
              0.72 ,  0.625,  0.525,  0.424,  0.326,  0.   ,  0.   ,
              0.   ,  0.   ,  0.   ,  0.   ]])
    r   )r   r:   r   z8Input must have 2 or fewer dimensions. Provided x.shape=.        zInvalid quantile z.2fr   Tr   rm   )rI   r   r   rB   r\   scipyr   
lil_matrixrC   r   r   sortcumsumargminr~   wheretocsr)rJ   r   r\   x_sparsemagsnormsmag_sortcumulative_magthreshold_idxr   jr   s               rS   r*   r*   `  sE   H 	vv{IIg	
!FqwwiqQ
 	
 (Q0#?@@}||&&qwwe&<H66!9DFF4a$/Ewwt!$HYYx%/a8NIInx7a@M-(1hhtAw(1a4.01QV9C ) >>rT   )n_bytesr\   c                   dt        dd|z  dz
  z        z  }d|d}|t        j                  | |      j                  |      z  S )a  Convert an integer buffer to floating point values.
    This is primarily useful when loading integer-valued wav data
    into numpy arrays.

    Parameters
    ----------
    x : np.ndarray [dtype=int]
        The integer-valued data buffer
    n_bytes : int [1, 2, 4]
        The number of bytes per sample in ``x``
    dtype : numeric type
        The target output type (default: 32-bit float)

    Returns
    -------
    x_float : np.ndarray [dtype=float]
        The input data buffer cast to floating point
    r   r      z<ir@   )r   rC   
frombufferr   )rJ   r   r\   scalefmts        rS   r1   r1     sT    , %q7{a/011E wqk
C 2==C(//666rT   )idx_minidx_maxsteprt   c          	         t        | |||      }t        ||dd       D cg c]  \  }}t        |||       c}}S c c}}w )aK  Generate a slice array from an index array.

    Parameters
    ----------
    idx : list-like
        Array of index boundaries
    idx_min, idx_max : None or int
        Minimum and maximum allowed indices
    step : None or int
        Step size for each slice.  If `None`, then the default
        step of 1 is used.
    pad : boolean
        If `True`, pad ``idx`` to span the range ``idx_min:idx_max``.

    Returns
    -------
    slices : list of slice
        ``slices[i] = slice(idx[i], idx[i+1], step)``
        Additional slice objects may be added at the beginning or end,
        depending on whether ``pad==True`` and the supplied values for
        ``idx_min`` and ``idx_max``.

    See Also
    --------
    fix_frames

    Examples
    --------
    >>> # Generate slices from spaced indices
    >>> librosa.util.index_to_slice(np.arange(20, 100, 15))
    [slice(20, 35, None), slice(35, 50, None), slice(50, 65, None), slice(65, 80, None),
     slice(80, 95, None)]
    >>> # Pad to span the range (0, 100)
    >>> librosa.util.index_to_slice(np.arange(20, 100, 15),
    ...                             idx_min=0, idx_max=100)
    [slice(0, 20, None), slice(20, 35, None), slice(35, 50, None), slice(50, 65, None),
     slice(65, 80, None), slice(80, 95, None), slice(95, 100, None)]
    >>> # Use a step of 5 for each slice
    >>> librosa.util.index_to_slice(np.arange(20, 100, 15),
    ...                             idx_min=0, idx_max=100, step=5)
    [slice(0, 20, 5), slice(20, 35, 5), slice(35, 50, 5), slice(50, 65, 5), slice(65, 80, 5),
     slice(80, 95, 5), slice(95, 100, 5)]
    r   r   N)r$   ziprH   )r   r   r   r   rt   	idx_fixedstartends           rS   r.   r.     sM    h 3gW#FI 9<IyQRQS}8UV8UE%d#8UVVVs   =)	aggregatert   r;   c          
     Z   |t         j                  }t        | j                        }t        j                  |D cg c]  }t        |t               c}      r|}nt        j                  |D cg c]/  }t        j                  t        |      t         j                        1 c}      r&t        t        j                  |      d||   |      }nt        d|       t        |      }t        |      ||<   t        j                  |t        j                  |       rdnd| j                         }	t        d      g| j"                  z  }
t        d      g|	j"                  z  }t%        |      D ]1  \  }}||
|<   |||<    || t'        |
         |      |	t'        |      <   3 |	S c c}w c c}w )	a  Aggregate a multi-dimensional array between specified boundaries.

    .. note::
        In order to ensure total coverage, boundary points may be added
        to ``idx``.

        If synchronizing a feature matrix against beat tracker output, ensure
        that frame index numbers are properly aligned and use the same hop length.

    Parameters
    ----------
    data : np.ndarray
        multi-dimensional array of features
    idx : sequence of ints or slices
        Either an ordered array of boundary indices, or
        an iterable collection of slice objects.
    aggregate : function
        aggregation function (default: `np.mean`)
    pad : boolean
        If `True`, ``idx`` is padded to span the full range ``[0, data.shape[axis]]``
    axis : int
        The axis along which to aggregate data

    Returns
    -------
    data_sync : ndarray
        ``data_sync`` will have the same dimension as ``data``, except that the ``axis``
        coordinate will be reduced according to ``idx``.

        For example, a 2-dimensional ``data`` with ``axis=-1`` should satisfy::

            data_sync[:, i] = aggregate(data[:, idx[i-1]:idx[i]], axis=-1)

    Raises
    ------
    ParameterError
        If the index set is not of consistent type (all slices or all integers)

    Notes
    -----
    This function caches at level 40.

    Examples
    --------
    Beat-synchronous CQT spectra

    >>> y, sr = librosa.load(librosa.ex('choice'))
    >>> tempo, beats = librosa.beat.beat_track(y=y, sr=sr, trim=False)
    >>> C = np.abs(librosa.cqt(y=y, sr=sr))
    >>> beats = librosa.util.fix_frames(beats)

    By default, use mean aggregation

    >>> C_avg = librosa.util.sync(C, beats)

    Use median-aggregation instead of mean

    >>> C_med = librosa.util.sync(C, beats,
    ...                              aggregate=np.median)

    Or sub-beat synchronization

    >>> sub_beats = librosa.segment.subsegment(C, beats)
    >>> sub_beats = librosa.util.fix_frames(sub_beats)
    >>> C_med_sub = librosa.util.sync(C, sub_beats, aggregate=np.median)

    Plot the results

    >>> import matplotlib.pyplot as plt
    >>> beat_t = librosa.frames_to_time(beats, sr=sr)
    >>> subbeat_t = librosa.frames_to_time(sub_beats, sr=sr)
    >>> fig, ax = plt.subplots(nrows=3, sharex=True, sharey=True)
    >>> librosa.display.specshow(librosa.amplitude_to_db(C,
    ...                                                  ref=np.max),
    ...                          x_axis='time', ax=ax[0])
    >>> ax[0].set(title='CQT power, shape={}'.format(C.shape))
    >>> ax[0].label_outer()
    >>> librosa.display.specshow(librosa.amplitude_to_db(C_med,
    ...                                                  ref=np.max),
    ...                          x_coords=beat_t, x_axis='time', ax=ax[1])
    >>> ax[1].set(title='Beat synchronous CQT power, '
    ...                 'shape={}'.format(C_med.shape))
    >>> ax[1].label_outer()
    >>> librosa.display.specshow(librosa.amplitude_to_db(C_med_sub,
    ...                                                  ref=np.max),
    ...                          x_coords=subbeat_t, x_axis='time', ax=ax[2])
    >>> ax[2].set(title='Sub-beat synchronous CQT power, '
    ...                 'shape={}'.format(C_med_sub.shape))
    Nr   )r   r   rt   zInvalid index set: FC)orderr\   rm   )rC   r   rF   rB   r_   rY   rH   r[   r   rh   r.   r   r   r}   empty	isfortranr\   rI   r~   rE   )ru   r   r  rt   r;   rB   _rR   	agg_shapedata_aggidx_inidx_aggr   segments                 rS   r/   r/     sc   D GG	E	vvS1Sz!U#S12	SAStAw

3SA	BJJsOQd
 23%899UI&kIdOxxT 24::H Dk]TYY&FT{mhmm+G'
7t#,T%--@t#Lw  (
 O1 2As   F#/4F()powersplit_zerosc                  | j                   |j                   k7  r%t        d| j                    d|j                          t        j                  | dk        st        j                  |dk        rt        d      |dk  rt        d      | j                  }t        j
                  |t        j                        st        j                  }t        j                  | |      j                  |      }|t        j                  |      j                  k  }d||<   t        j                  |      r9| |z  |z  }||z  |z  }| }	||	xx   ||	   ||	   z   z  cc<   |rd||<   |S d||<   |S | |kD  }|S )	au	  Robustly compute a soft-mask operation.

        ``M = X**power / (X**power + X_ref**power)``

    Parameters
    ----------
    X : np.ndarray
        The (non-negative) input array corresponding to the positive mask elements

    X_ref : np.ndarray
        The (non-negative) array of reference or background elements.
        Must have the same shape as ``X``.

    power : number > 0 or np.inf
        If finite, returns the soft mask computed in a numerically stable way

        If infinite, returns a hard (binary) mask equivalent to ``X > X_ref``.
        Note: for hard masks, ties are always broken in favor of ``X_ref`` (``mask=0``).

    split_zeros : bool
        If `True`, entries where ``X`` and ``X_ref`` are both small (close to 0)
        will receive mask values of 0.5.

        Otherwise, the mask is set to 0 for these entries.

    Returns
    -------
    mask : np.ndarray, shape=X.shape
        The output mask array

    Raises
    ------
    ParameterError
        If ``X`` and ``X_ref`` have different shapes.

        If ``X`` or ``X_ref`` are negative anywhere

        If ``power <= 0``

    Examples
    --------
    >>> X = 2 * np.ones((3, 3))
    >>> X_ref = np.vander(np.arange(3.0))
    >>> X
    array([[ 2.,  2.,  2.],
           [ 2.,  2.,  2.],
           [ 2.,  2.,  2.]])
    >>> X_ref
    array([[ 0.,  0.,  1.],
           [ 1.,  1.,  1.],
           [ 4.,  2.,  1.]])
    >>> librosa.util.softmask(X, X_ref, power=1)
    array([[ 1.   ,  1.   ,  0.667],
           [ 0.667,  0.667,  0.667],
           [ 0.333,  0.5  ,  0.667]])
    >>> librosa.util.softmask(X_ref, X, power=1)
    array([[ 0.   ,  0.   ,  0.333],
           [ 0.333,  0.333,  0.333],
           [ 0.667,  0.5  ,  0.333]])
    >>> librosa.util.softmask(X, X_ref, power=2)
    array([[ 1. ,  1. ,  0.8],
           [ 0.8,  0.8,  0.8],
           [ 0.2,  0.5,  0.8]])
    >>> librosa.util.softmask(X, X_ref, power=4)
    array([[ 1.   ,  1.   ,  0.941],
           [ 0.941,  0.941,  0.941],
           [ 0.059,  0.5  ,  0.941]])
    >>> librosa.util.softmask(X, X_ref, power=100)
    array([[  1.000e+00,   1.000e+00,   1.000e+00],
           [  1.000e+00,   1.000e+00,   1.000e+00],
           [  7.889e-31,   5.000e-01,   1.000e+00]])
    >>> librosa.util.softmask(X, X_ref, power=np.inf)
    array([[ True,  True,  True],
           [ True,  True,  True],
           [False, False,  True]], dtype=bool)
    zShape mismatch: z!=r   z X and X_ref must be non-negativezpower must be strictly positiver   g      ?r   )rB   r   rC   rk   r\   r[   r]   float32maximumr   finfor2   r^   )
XX_refr  r  r\   Zbad_idxmaskref_maskgood_idxs
             rS   r0   r0     sY   ^ 	ww%++/y5;;-HII	vva!e}uqy)?@@z>?? GGE==,

 	

1e##E*A"((5/&&&GAgJ
 
{{5A%AI%'8X$x.8H+===DM K  DM
 K 5yKrT   c                   t        j                  |       } t        j                  | j                  t         j                        s.t        j                  | j                  t         j
                        r| j                  }n#t        j                  t         j                        }t        j                  |      j                  S )a  Compute the tiny-value corresponding to an input's data type.

    This is the smallest "usable" number representable in ``x.dtype``
    (e.g., float32).

    This is primarily useful for determining a threshold for
    numerical underflow in division or multiplication operations.

    Parameters
    ----------
    x : number or np.ndarray
        The array to compute the tiny-value for.
        All that matters here is ``x.dtype``

    Returns
    -------
    tiny_value : float
        The smallest positive usable number for the type of ``x``.
        If ``x`` is integer-typed, then the tiny value for ``np.float32``
        is returned instead.

    See Also
    --------
    numpy.finfo

    Examples
    --------
    For a standard double-precision floating point number:

    >>> librosa.util.tiny(1.0)
    2.2250738585072014e-308

    Or explicitly as double-precision

    >>> librosa.util.tiny(np.asarray(1e-5, dtype=np.float64))
    2.2250738585072014e-308

    Or complex numbers

    >>> librosa.util.tiny(1j)
    2.2250738585072014e-308

    Single-precision floating point:

    >>> librosa.util.tiny(np.asarray(1e-5, dtype=np.float32))
    1.1754944e-38

    Integer

    >>> librosa.util.tiny(5)
    1.1754944e-38
    )	rC   r   r[   r\   r]   complexfloatingr  r  r2   )rJ   r\   s     rS   r2   r2     su    l 	

1A 
}}QWWbkk*bmm	##/ $88E?rT   )r   c                  | j                   \  }}t        t        j                  |t        j                  | j                         z              }| j                   \  }}t        j
                  | j                   d   | j                   d   z
        }||k  r3t        j                  | ||z         }t        j                  | |       }n2t        j                  | |      }t        j                  | | |z
        }|| |<   || |<   y)a/  Set all cells of a matrix to a given ``value``
    if they lie outside a constraint region.

    In this case, the constraint region is the
    Sakoe-Chiba band which runs with a fixed ``radius``
    along the main diagonal.

    When ``x.shape[0] != x.shape[1]``, the radius will be
    expanded so that ``x[-1, -1] = 1`` always.

    ``x`` will be modified in place.

    Parameters
    ----------
    x : np.ndarray [shape=(N, M)]
        Input matrix, will be modified in place.
    radius : float
        The band radius (1/2 of the width) will be
        ``int(radius*min(x.shape))``
    value : float
        ``x[n, m] = value`` when ``(n, m)`` lies outside the band.

    Examples
    --------
    >>> x = np.ones((8, 8))
    >>> librosa.util.fill_off_diagonal(x, radius=0.25)
    >>> x
    array([[1, 1, 0, 0, 0, 0, 0, 0],
           [1, 1, 1, 0, 0, 0, 0, 0],
           [0, 1, 1, 1, 0, 0, 0, 0],
           [0, 0, 1, 1, 1, 0, 0, 0],
           [0, 0, 0, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 1, 1, 1, 0],
           [0, 0, 0, 0, 0, 1, 1, 1],
           [0, 0, 0, 0, 0, 0, 1, 1]])
    >>> x = np.ones((8, 12))
    >>> librosa.util.fill_off_diagonal(x, radius=0.25)
    >>> x
    array([[1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
           [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
           [0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
           [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
           [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1]])
    r   r   )kN)rB   rf   rC   roundr   r   triu_indices_fromtril_indices_from)rJ   radiusr   nxnyoffsetidx_uidx_ls           rS   r-   r-   W  s    ` WWFB &266!''?234FWWFBVVQWWQZ!''!*,.F	Bw$$Q&6/:$$Q6'2$$Q&1$$Q6'F*:; AeHAeHrT   
edge_orderr;   c                  dg| j                   z  }||f||<   t        j                  | |d      }t        j                  |||      }t	        d      g| j                   z  }t	        ||       ||<   |t        |         }|S )a.  Estimate the gradient of a function over a uniformly sampled,
    periodic domain.

    This is essentially the same as `np.gradient`, except that edge effects
    are handled by wrapping the observations (i.e. assuming periodicity)
    rather than extrapolation.

    Parameters
    ----------
    data : np.ndarray
        The function values observed at uniformly spaced positions on
        a periodic domain
    edge_order : {1, 2}
        The order of the difference approximation used for estimating
        the gradient
    axis : int
        The axis along which gradients are calculated.

    Returns
    -------
    grad : np.ndarray like ``data``
        The gradient of ``data`` taken along the specified axis.

    See Also
    --------
    numpy.gradient

    Examples
    --------
    This example estimates the gradient of cosine (-sine) from 64
    samples using direct (aperiodic) and periodic gradient
    calculation.

    >>> import matplotlib.pyplot as plt
    >>> x = 2 * np.pi * np.linspace(0, 1, num=64, endpoint=False)
    >>> y = np.cos(x)
    >>> grad = np.gradient(y)
    >>> cyclic_grad = librosa.util.cyclic_gradient(y)
    >>> true_grad = -np.sin(x) * 2 * np.pi / len(x)
    >>> fig, ax = plt.subplots()
    >>> ax.plot(x, true_grad, label='True gradient', linewidth=5,
    ...          alpha=0.35)
    >>> ax.plot(x, cyclic_grad, label='cyclic_gradient')
    >>> ax.plot(x, grad, label='np.gradient', linestyle=':')
    >>> ax.legend()
    >>> # Zoom into the first part of the sequence
    >>> ax.set(xlim=[0, np.pi/16], ylim=[-0.025, 0.025])
    rq   wrap)ro   r+  N)rI   rC   rt   gradientrH   rE   )ru   r,  r;   paddingdata_padgradrR   
grad_slices           rS   r3   r3     s    h h"G,GDMvvdG&1H ;;xJTBD Dk]TYY&Fj[1F4L!%-0JrT   factorr;   c                   |dk(  r| j                   } t        j                  |       }t        | j                  d         D ])  }t        j
                  | dd|f   ||z        |dd|f<   + |dk(  r|j                   }|S )z2Numba-accelerated shear for dense (ndarray) arraysr   r   N)TrC   r   rangerB   roll)r  r5  r;   X_shearr   s        rS   __shear_denser;    st     qyCCmmAG1771:!Q$!41  qy))NrT   c                  | j                   }|dk(  r| j                  } | j                  d      }t        j                  |t        j
                  |j                  d         z  t        j                  |j                              }t        j                  |j                  |z   |j                  d   |j                         |dk(  r|j                  }|j                  |      S )zFast shearing for sparse matrices

    Shearing is performed using CSC array indices,
    and the result is converted back to whatever sparse format
    the data was originally provided in.
    r   T)r?   r   )out)formatr7  tocscrC   repeatarangerB   diffindptrr   indicesasformat)r  r5  r;   r   r:  r9  s         rS   __shear_sparserF    s     ((CqyCC gg4g G
 99Vbiia(8992777>>;RSD FF7??T!7==#3Iqy)) C  rT   _ArrayOrSparseMatrix)boundc                    y r   r   r  r5  r;   s      rS   r+   r+         rT   c                    y r   r   rJ  s      rS   r+   r+     s     rT   c                   t        j                  t        |      t         j                        st	        d| d      t
        j                  j                  |       rt        | ||      S t        | ||      S )ae  Shear a matrix by a given factor.

    The column ``X[:, n]`` will be displaced (rolled)
    by ``factor * n``

    This is primarily useful for converting between lag and recurrence
    representations: shearing with ``factor=-1`` converts the main diagonal
    to a horizontal.  Shearing with ``factor=1`` converts a horizontal to
    a diagonal.

    Parameters
    ----------
    X : np.ndarray [ndim=2] or scipy.sparse matrix
        The array to be sheared
    factor : integer
        The shear factor: ``X[:, n] -> np.roll(X[:, n], factor * n)``
    axis : integer
        The axis along which to shear

    Returns
    -------
    X_shear : same type as ``X``
        The sheared matrix

    Examples
    --------
    >>> E = np.eye(3)
    >>> librosa.util.shear(E, factor=-1, axis=-1)
    array([[1., 1., 1.],
           [0., 0., 0.],
           [0., 0., 0.]])
    >>> librosa.util.shear(E, factor=-1, axis=0)
    array([[1., 0., 0.],
           [1., 0., 0.],
           [1., 0., 0.]])
    >>> librosa.util.shear(E, factor=1, axis=-1)
    array([[1., 0., 0.],
           [0., 0., 1.],
           [0., 1., 0.]])
    zfactor=z must be integer-valuedr4  )
rC   r[   r   rh   r   r   r   
isspmatrixrF  r;  rJ  s      rS   r+   r+     sb    V ==frzz2wvh.EFGG ||q!aT::QvD99rT   c                  | D ch c]  }|j                    }}t        |      dkD  rt        d      t        |      dk  rt        d      |j                         }|dk7  rt	        j
                  | |      S t        t        |       gt        |      z         }t	        j                  |  }t	        j                  ||d      }t	        j
                  | ||       |S c c}w )	a+  Stack one or more arrays along a target axis.

    This function is similar to `np.stack`, except that memory contiguity is
    retained when stacking along the first dimension.

    This is useful when combining multiple monophonic audio signals into a
    multi-channel signal, or when stacking multiple feature representations
    to form a multi-dimensional array.

    Parameters
    ----------
    arrays : list
        one or more `np.ndarray`
    axis : integer
        The target axis along which to stack.  ``axis=0`` creates a new first axis,
        and ``axis=-1`` creates a new last axis.

    Returns
    -------
    arr_stack : np.ndarray [shape=(len(arrays), array_shape) or shape=(array_shape, len(arrays))]
        The input arrays, stacked along the target dimension.

        If ``axis=0``, then ``arr_stack`` will be F-contiguous.
        Otherwise, ``arr_stack`` will be C-contiguous by default, as computed by
        `np.stack`.

    Raises
    ------
    ParameterError
        - If ``arrays`` do not all have the same shape
        - If no ``arrays`` are given

    See Also
    --------
    numpy.stack
    numpy.ndarray.flags
    frame

    Examples
    --------
    Combine two buffers into a contiguous arrays

    >>> y_left = np.ones(5)
    >>> y_right = -np.ones(5)
    >>> y_stereo = librosa.util.stack([y_left, y_right], axis=0)
    >>> y_stereo
    array([[ 1.,  1.,  1.,  1.,  1.],
           [-1., -1., -1., -1., -1.]])
    >>> y_stereo.flags
      C_CONTIGUOUS : False
      F_CONTIGUOUS : True
      OWNDATA : True
      WRITEABLE : True
      ALIGNED : True
      WRITEBACKIFCOPY : False
      UPDATEIFCOPY : False

    Or along the trailing axis

    >>> y_stereo = librosa.util.stack([y_left, y_right], axis=-1)
    >>> y_stereo
    array([[ 1., -1.],
           [ 1., -1.],
           [ 1., -1.],
           [ 1., -1.],
           [ 1., -1.]])
    >>> y_stereo.flags
      C_CONTIGUOUS : True
      F_CONTIGUOUS : False
      OWNDATA : True
      WRITEABLE : True
      ALIGNED : True
      WRITEBACKIFCOPY : False
      UPDATEIFCOPY : False
    r   z)all input arrays must have the same shapez3at least one input array must be provided for stackr   rm   r  )r\   r  )r;   r=  )
rB   r}   r   poprC   r,   rE   rF   result_typer	  )arraysr;   arrshapesshape_inrB   r\   results           rS   r,   r,   T  s    X $**6Ccii6F*
6{QHII	VqRSSzz|HqyxxT** s6{md8n45 ' %uC8 	d// +s   C)defaultc                  t        j                  t         j                        t         j                  t        j                  t         j                        t         j
                  t        j                  t              t        j                  t              j                  i}t        j                  |       }|j                  dk(  r|S t        j                  |j                  ||            S )a  Find the complex numpy dtype corresponding to a real dtype.

    This is used to maintain numerical precision and memory footprint
    when constructing complex arrays from real-valued data
    (e.g. in a Fourier transform).

    A `float32` (single-precision) type maps to `complex64`,
    while a `float64` (double-precision) maps to `complex128`.

    Parameters
    ----------
    d : np.dtype
        The real-valued dtype to convert to complex.
        If ``d`` is a complex type already, it will be returned.
    default : np.dtype, optional
        The default complex target type, if ``d`` does not match a
        known dtype

    Returns
    -------
    d_c : np.dtype
        The complex dtype

    See Also
    --------
    dtype_c2r
    numpy.dtype

    Examples
    --------
    >>> librosa.util.dtype_r2c(np.float32)
    dtype('complex64')

    >>> librosa.util.dtype_r2c(np.int16)
    dtype('complex64')

    >>> librosa.util.dtype_r2c(np.complex128)
    dtype('complex128')
    c)rC   r\   r  	complex64float64
complex128r   complexr   kindgetr@   rW  mappingdts       rS   r4   r4     s    R 	bll
bmm
'*//&G 
!B	ww#~	 88GKKG,--rT   c                  t        j                  t         j                        t         j                  t        j                  t         j                        t         j
                  t        j                  t              t        j                  t              j                  i}t        j                  |       }|j                  dk(  r|S t        j                  |j                  ||            S )a(  Find the real numpy dtype corresponding to a complex dtype.

    This is used to maintain numerical precision and memory footprint
    when constructing real arrays from complex-valued data
    (e.g. in an inverse Fourier transform).

    A `complex64` (single-precision) type maps to `float32`,
    while a `complex128` (double-precision) maps to `float64`.

    Parameters
    ----------
    d : np.dtype
        The complex-valued dtype to convert to real.
        If ``d`` is a real (float) type already, it will be returned.
    default : np.dtype, optional
        The default real target type, if ``d`` does not match a
        known dtype

    Returns
    -------
    d_r : np.dtype
        The real dtype

    See Also
    --------
    dtype_r2c
    numpy.dtype

    Examples
    --------
    >>> librosa.util.dtype_r2c(np.complex64)
    dtype('float32')

    >>> librosa.util.dtype_r2c(np.float32)
    dtype('float32')

    >>> librosa.util.dtype_r2c(np.int16)
    dtype('float32')

    >>> librosa.util.dtype_r2c(np.complex128)
    dtype('float64')
    f)rC   r\   rZ  r  r\  r[  r]  r   r   r^  r_  r`  s       rS   r5   r5     s    X 	



288E?//&G 
!B	ww#~	 88GKKG,--rT   c                J    t        j                  |       }|j                  d   S )zCount the number of unique values in an array.

    This function is a helper for `count_unique` and is not
    to be called directly.
    r   )rC   r   rB   rJ   uniquess     rS   __count_uniquerh  -	  s      iilG==rT   c               8    t        j                  t        ||       S )a  Count the number of unique values in a multi-dimensional array
    along a given axis.

    Parameters
    ----------
    data : np.ndarray
        The input array
    axis : int
        The target axis to count

    Returns
    -------
    n_uniques
        The number of unique values.
        This array will have one fewer dimension than the input.

    See Also
    --------
    is_unique

    Examples
    --------
    >>> x = np.vander(np.arange(5))
    >>> x
    array([[  0,   0,   0,   0,   1],
       [  1,   1,   1,   1,   1],
       [ 16,   8,   4,   2,   1],
       [ 81,  27,   9,   3,   1],
       [256,  64,  16,   4,   1]])
    >>> # Count unique values along rows (within columns)
    >>> librosa.util.count_unique(x, axis=0)
    array([5, 5, 5, 5, 1])
    >>> # Count unique values along columns (within rows)
    >>> librosa.util.count_unique(x, axis=-1)
    array([2, 1, 5, 5, 5])
    )rC   apply_along_axisrh  ru   r;   s     rS   r6   r6   8	  s    J ~tT::rT   c                d    t        j                  |       }|j                  d   | j                  k(  S )zDetermine if the input array has all unique values.

    This function is a helper for `is_unique` and is not
    to be called directly.
    r   )rC   r   rB   rv   rf  s     rS   __is_uniquerm  `	  s)     iilG==qvv%%rT   c               8    t        j                  t        ||       S )a  Determine if the input array consists of all unique values
    along a given axis.

    Parameters
    ----------
    data : np.ndarray
        The input array
    axis : int
        The target axis

    Returns
    -------
    is_unique
        Array of booleans indicating whether the data is unique along the chosen
        axis.
        This array will have one fewer dimension than the input.

    See Also
    --------
    count_unique

    Examples
    --------
    >>> x = np.vander(np.arange(5))
    >>> x
    array([[  0,   0,   0,   0,   1],
       [  1,   1,   1,   1,   1],
       [ 16,   8,   4,   2,   1],
       [ 81,  27,   9,   3,   1],
       [256,  64,  16,   4,   1]])
    >>> # Check uniqueness along rows
    >>> librosa.util.is_unique(x, axis=0)
    array([ True,  True,  True,  True, False])
    >>> # Check uniqueness along columns
    >>> librosa.util.is_unique(x, axis=-1)
    array([False, False,  True,  True,  True])
    )rC   rj  rm  rk  s     rS   r7   r7   k	  s    L {D$77rT   zfloat32(complex64)zfloat64(complex128))r   r   identityc                @    | j                   dz  | j                  dz  z   S )z*Efficiently compute abs2 on complex inputsr   )realimagri   s    rS   _cabs2rs  	  s    
 6619qvvqy  rT   znp.number[Any]_NumberOrArrayc                    t        j                  |       r t        |       }||S |j                  |      S t        j                  | d|      S )a  Compute the squared magnitude of a real or complex array.

    This function is equivalent to calling `np.abs(x)**2` but it
    is slightly more efficient.

    Parameters
    ----------
    x : np.ndarray or scalar, real or complex typed
        The input data, either real (float32, float64) or complex (complex64, complex128) typed
    dtype : np.dtype, optional
        The data type of the output array.
        If not provided, it will be inferred from `x`

    Returns
    -------
    p : np.ndarray or scale, real
        squared magnitude of `x`

    Examples
    --------
    >>> librosa.util.abs2(3 + 4j)
    25.0

    >>> librosa.util.abs2((0.5j)**np.arange(8))
    array([1.000e+00, 2.500e-01, 6.250e-02, 1.562e-02, 3.906e-03, 9.766e-04,
       2.441e-04, 6.104e-05])
    r   r   )rC   iscomplexobjrs  r   r  )rJ   r\   r`   s      rS   r8   r8   	  sF    8 
q1I=H88E?" xx1E**rT   zcomplex64(float32)zcomplex128(float64)c                ^    t        j                  |       dt        j                  |       z  z   S )Ny              ?)rC   cossinri   s    rS   _phasor_anglesrz  	  s#     66!9rBFF1I~%%rT   znp.integer[Any]znp.floating[Any])r   c                    y r   r   anglesr   s     rS   r9   r9   	  rK  rT   c                    y r   r   r|  s     rS   r9   r9   	  rK  rT   c               *    t        |       }|||z  }|S )a  Construct a complex phasor representation from angles.

    When `mag` is not provided, this is equivalent to:

        z = np.cos(angles) + 1j * np.sin(angles)

    or by Euler's formula:

        z = np.exp(1j * angles)

    When `mag` is provided, this is equivalent to:

        z = mag * np.exp(1j * angles)

    This function should be more efficient (in time and memory) than the equivalent'
    formulations above, but produce numerically identical results.

    Parameters
    ----------
    angles : np.ndarray or scalar, real-valued
        Angle(s), measured in radians

    mag : np.ndarray or scalar, optional
        If provided, phasor(s) will be scaled by `mag`.

        If not provided (default), phasors will have unit magnitude.

        `mag` must be of compatible shape to multiply with `angles`.

    Returns
    -------
    z : np.ndarray or scalar, complex-valued
        Complex number(s) z corresponding to the given angle(s)
        and optional magnitude(s).

    Examples
    --------
    Construct unit phasors at angles 0, pi/2, and pi:

    >>> librosa.util.phasor([0, np.pi/2, np.pi])
    array([ 1.000e+00+0.000e+00j,  6.123e-17+1.000e+00j,
           -1.000e+00+1.225e-16j])

    Construct a phasor with magnitude 1/2:

    >>> librosa.util.phasor(np.pi/2, mag=0.5)
    (3.061616997868383e-17+0.5j)

    Or arrays of angles and magnitudes:

    >>> librosa.util.phasor(np.array([0, np.pi/2]), mag=np.array([0.5, 1.5]))
    array([5.000e-01+0.j , 9.185e-17+1.5j])
    )rz  )r}  r   zs      rS   r9   r9   	  s"    t 	vA
	SHrT   )rJ   
np.ndarrayrK   rf   rL   rf   r;   rf   r<   r   r=   r   returnr  )r`   r  rW   zUnion[bool, Deprecated]r  r   )rJ   r   rb   z"Optional[Callable[[float], float]]r  rf   )rJ   r   r  r   )rl   r  r  r   )
ru   r  rv   rf   r;   rf   rw   r   r  r  )rJ   r  rI   rf   r   z1Union[int, slice, Sequence[int], Sequence[slice]]r  r  )
r   _SequenceLike[int]r   Optional[int]r   r  rt   r   r  r  )
r   r  r;   rf   r   zLiteral[False]r   Optional[Callable[..., Any]]r  r  )
r   r  r;   rf   r   zLiteral[True]r   r  r  zTuple[np.ndarray, np.ndarray])
r   r  r;   rf   r   r   r   r  r  z0Union[np.ndarray, Tuple[np.ndarray, np.ndarray]])r   r  r   zOptional[float]r;   r  r   zOptional[_FloatLike_co]r   zOptional[bool]r  r  )rJ   r  r;   rf   r  r  )rJ   r  r   rf   r   rf   r   rf   r   rf   r   r   r   rf   r   r   r;   rf   r  r  )rJ   r  r   r   r\   Optional[DTypeLike]r  zscipy.sparse.csr_matrix)rJ   r  r   rf   r\   r   r  r  )r   r  r   r  r   r  r   r  rt   r   r  zList[slice])ru   r  r   z%Union[Sequence[int], Sequence[slice]]r  r  rt   r   r;   rf   r  r  )
r  r  r  r  r  r   r  r   r  r  )rJ   zUnion[float, np.ndarray]r  r   )rJ   r  r%  r   r   r   r  None)ru   r  r,  zLiteral[1, 2]r;   rf   r  r  )r  r  r5  rf   r;   rf   r  r  )r  scipy.sparse.spmatrixr5  rf   r;   rf   r  r  )r  rG  r5  rf   r;   rf   r  rG  )rR  zList[np.ndarray]r;   rf   r  r  )r@   r   rW  zOptional[type]r  r   )ru   r  r;   rf   r  r  )rJ   r   r  r   r   )rJ   rt  r\   r  r  rt  )r  np.complex_)r}  r  r   zOptional[np.ndarray]r  r  )r}  _Realr   zOptional[_Number]r  r  )r}  zUnion[np.ndarray, _Real]r   z$Optional[Union[np.ndarray, _Number]]r  zUnion[np.ndarray, np.complex_])a__doc__
__future__r   scipy.ndimager   scipy.sparsenumpyrC   numbanumpy.lib.stride_tricksr   _cacher   
exceptionsr   deprecationr	   numpy.typingr
   r   typingr   r   r   r   r   r   r   r   r   r   r   typing_extensionsr   _typingr   r   r   r   __all__r   r    r!   r"   r#   r   r   r   r$   r%   r   r(   stencilr   r   guvectorizer   r   r&   r'   r   r)   r*   r  r1   r.   r/   r0   r2   r-   r3   jitr;  rF  rZ   r   spmatrixrG  r+   r,   rZ  r4   r5   rh  r6   rm  r7   	vectorizers  r]  _Numberrt  r8   rz  r   r  r9   r   rT   rS   <module>r     s    "     .  & # -    & C C  P cc c 	c
 c c c cL RBL, M M` GK @86 13G+
G+"G+*-G+>AG+G+TDDD'XDDP 138
8"8*-8>A88| VV V 	V
 
V Vr 
 *-  	
 (  
 
 *-  	
 ( # 
 *.a$a$ a$ 	a$
 (a$ 6a$H R FF)-dd d 	d
 'd d d dN + +
 + +
  

  

 ,- :z ,- ;~  !R {{ { 	{
 { { { { { { {| R(,4__ %_5H__ _F &'2::77"7/877D "!7W	7W 7W 	7W
 7W 
7W 7Wt R
 /3~
~	.~ ,	~
 
~ ~ ~ ~D 9:uss$s05sHLssl@ F GH AJ 67B?
?%2?>A??D D%24"  &" 02r!!),!9<!!> %

ELL4I4I(I"J 
 
*-3  
 
/2),:= 
 /0R3:3:(+3:7:3:3:l 45 cL :< 5.p :< 8.v D% & 35 %;P D%& && 02 &8R 01DWX!!
 ))
*)w

7J1KL%+P 01DWX&& 	e&(::; 
>A  
 
69  
 15?$? 
.? $	?rT   