o
    ۷i0                     @   s2  d 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	gZ
ejd
d
ddejdejfddZejd
d
ddd Zejd
d
d	
d!dejdejdedejfddZ	
d!dejdejdedejfddZ	
	
d"de	de	dededejf
dd	Zejd
d
d	
	
d"dejdejdejdedef
dd ZdS )#zMatching functions    N   )ParameterError)valid_intervals   )_SequenceLikematch_intervalsmatch_eventsT)nopythoncacheint_aint_bc                 C   s   | d |d g}|d |d k r|   | d |d g}|d |d k r(|   |d |d  }|dk r6d}|d |d  }|dkrF|| S dS )zJaccard similarity between two intervals

    Parameters
    ----------
    int_a, int_b : np.ndarrays, shape=(2,)

    Returns
    -------
    Jaccard similarity between intervals
    r   r   g        )reverse)r   r   endsstartsintersectionunion r   K/home/ubuntu/vllm_env/lib/python3.10/site-packages/librosa/util/matching.py	__jaccard   s   r   c                 C   s6   d}d}|D ]}t | || }||kr||}}q|S )z4Find the best Jaccard match from query to candidates)r   )queryintervals_to
candidates
best_scorebest_idxidxscorer   r   r   __match_interval_overlaps/   s   
r   intervals_fromr   strictreturnc                 C   s  t |dddf }t |dddf }||df }||df }t j|| dddf dd}t j|| dddf dd}t jt| tjd}	tt| D ]x}
| |
 }||
 }||
 }t|d| t||d @ }t|dkr{t	||||	|
< qN|rt
t j}t j}||
 dkr|d |||
 d   }||
 d t|k r|||
 d  |d  }||k r|||
 d  |	|
< qN|||
 d  |	|
< qN|	S )z.Numba-accelerated interval matching algorithm.Nr   r   right)sideleftdtype)npargsortsearchsortedemptylennumbauint32rangesetr   r   inf)r   r   r   start_index	end_indexstart_sorted
end_sortedsearch_endssearch_startsoutputir   after_querybefore_queryr   dist_before
dist_afterr   r   r   __match_intervals<   s4    r<   c              
   C   sj   t | dkst |dkrtdt|  t| zt| ||dW S  ty4 } ztd| |d}~ww )a
  Match one set of time intervals to another.

    This can be useful for tasks such as mapping beat timings
    to segments.

    Each element ``[a, b]`` of ``intervals_from`` is matched to the
    element ``[c, d]`` of ``intervals_to`` which maximizes the
    Jaccard similarity between the intervals::

        max(0, |min(b, d) - max(a, c)|) / |max(d, b) - min(a, c)|

    In ``strict=True`` mode, if there is no interval with positive
    intersection with ``[a,b]``, an exception is thrown.

    In ``strict=False`` mode, any interval ``[a, b]`` that has no
    intersection with any element of ``intervals_to`` is instead
    matched to the interval ``[c, d]`` which minimizes::

        min(|b - c|, |a - d|)

    that is, the disjoint interval [c, d] with a boundary closest
    to [a, b].

    .. note:: An element of ``intervals_to`` may be matched to multiple
       entries of ``intervals_from``.

    Parameters
    ----------
    intervals_from : np.ndarray [shape=(n, 2)]
        The time range for source intervals.
        The ``i`` th interval spans time ``intervals_from[i, 0]``
        to ``intervals_from[i, 1]``.
        ``intervals_from[0, 0]`` should be 0, ``intervals_from[-1, 1]``
        should be the track duration.
    intervals_to : np.ndarray [shape=(m, 2)]
        Analogous to ``intervals_from``.
    strict : bool
        If ``True``, intervals can only match if they intersect.
        If ``False``, disjoint intervals can match.

    Returns
    -------
    interval_mapping : np.ndarray [shape=(n,)]
        For each interval in ``intervals_from``, the
        corresponding interval in ``intervals_to``.

    See Also
    --------
    match_events

    Raises
    ------
    ParameterError
        If either array of input intervals is not the correct shape

        If ``strict=True`` and some element of ``intervals_from`` is disjoint from
        every element of ``intervals_to``.

    Examples
    --------
    >>> ints_from = np.array([[3, 5], [1, 4], [4, 5]])
    >>> ints_to = np.array([[0, 2], [1, 3], [4, 5], [6, 7]])
    >>> librosa.util.match_intervals(ints_from, ints_to)
    array([2, 1, 2], dtype=uint32)
    >>> # [3, 5] => [4, 5]  (ints_to[2])
    >>> # [1, 4] => [1, 3]  (ints_to[1])
    >>> # [4, 5] => [4, 5]  (ints_to[2])

    The reverse matching of the above is not possible in ``strict`` mode
    because ``[6, 7]`` is disjoint from all intervals in ``ints_from``.
    With ``strict=False``, we get the following:

    >>> librosa.util.match_intervals(ints_to, ints_from, strict=False)
    array([1, 1, 2, 2], dtype=uint32)
    >>> # [0, 2] => [1, 4]  (ints_from[1])
    >>> # [1, 3] => [1, 4]  (ints_from[1])
    >>> # [4, 5] => [4, 5]  (ints_from[2])
    >>> # [6, 7] => [4, 5]  (ints_from[2])
    r   z'Attempting to match empty interval list)r   z&Unable to match intervals with strict=N)r*   r   r   r<   )r   r   r   excr   r   r   r   r   s   Revents_from	events_tor#   r!   c                 C   s   t | dkst |dkrtd|s!|s!tt| |s!td|s/t|t| k r/td|s=t|t| kr=tdtj| tjd}t	|| |||S )a  Match one set of events to another.

    This is useful for tasks such as matching beats to the nearest
    detected onsets, or frame-aligned events to the nearest zero-crossing.

    .. note:: A target event may be matched to multiple source events.

    Examples
    --------
    >>> # Sources are multiples of 7
    >>> s_from = np.arange(0, 100, 7)
    >>> s_from
    array([ 0,  7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91,
           98])
    >>> # Targets are multiples of 10
    >>> s_to = np.arange(0, 100, 10)
    >>> s_to
    array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
    >>> # Find the matching
    >>> idx = librosa.util.match_events(s_from, s_to)
    >>> idx
    array([0, 1, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 8, 9, 9])
    >>> # Print each source value to its matching target
    >>> zip(s_from, s_to[idx])
    [(0, 0), (7, 10), (14, 10), (21, 20), (28, 30), (35, 30),
     (42, 40), (49, 50), (56, 60), (63, 60), (70, 70), (77, 80),
     (84, 80), (91, 90), (98, 90)]

    Parameters
    ----------
    events_from : ndarray [shape=(n,)]
        Array of events (eg, times, sample or frame indices) to match from.
    events_to : ndarray [shape=(m,)]
        Array of events (eg, times, sample or frame indices) to
        match against.
    left : bool
    right : bool
        If ``False``, then matched events cannot be to the left (or right)
        of source events.

    Returns
    -------
    event_mapping : np.ndarray [shape=(n,)]
        For each event in ``events_from``, the corresponding event
        index in ``events_to``::

            event_mapping[i] == arg min |events_from[i] - events_to[:]|

    See Also
    --------
    match_intervals

    Raises
    ------
    ParameterError
        If either array of input events is not the correct shape
    r   z$Attempting to match empty event listzWCannot match events with left=right=False and events_from is not contained in events_tozICannot match events with left=False and max(events_to) < max(events_from)zJCannot match events with right=False and min(events_to) > min(events_from)r$   )
r*   r   r&   allisinmaxmin
empty_likeint32__match_events_helper)r>   r?   r#   r!   r6   r   r   r   r      s    ?r6   c                 C   sx  t |}|| }t |}|| }t ||}	t|	D ]\}
}d}d}d}t|	}d}d}d}|	|
 }||
 }|t|krB|d8 }|rN|dkrN|d }d}|r^|t|d k r^|d }d}t|| | }|rr|rrt|| | }|r~|r~t|| | }|r|s|| |ks|s||k s||k r||k r|| | |
< q|r||k r|| | |
< q|| | |
< qt | }| ||< |S )NFr   r   r   T)r&   r'   r(   	enumerater*   absrD   )r6   r>   r?   r#   r!   from_idxsorted_fromto_idx	sorted_tomatching_indicesind
middle_ind	left_flag
right_flagleft_ind	right_ind	left_diff
right_diffmid_diffsorted_from_num	solutionsr   r   r   rF   4  sV   
	

rF   )T)TT)__doc__numpyr&   r+   
exceptionsr   utilsr   _typingr   __all__jitndarrayr   r   boolr<   r   r   rF   r   r   r   r   <module>   sv   
6
c
b