o
    ٷi>                     @   s
  d Z ddlmZmZmZmZmZmZ ddlm	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 ed
d$ZedZe
jeddZW d   n1 sUw   Y  W d   n1 sdw   Y  edddddddededeeee f dedededejfddZedddddeded e	d dejfd!d"Z eddd#deded e	d deeeef  fd$d"Z edddddeded edeejeeeef  f fd%d"Z edddddddeded edeejeeeef  f fd&d"Z d'd( Z!d)d* Z"eddddd+ededed e	d dejf
d,d-Z#eddd#d+ededed e	d deeeef  f
d.d-Z#eddddd+ededed edeejeeeef  f f
d/d-Z#eddddddd+ededed edeejeeeef  f f
d0d-Z#dS )1z#Functions for interval construction    )
CollectionDictListUnionoverloadIterable)LiteralN)	ArrayLike   )cache)_FloatLike_co)_resource_filezlibrosa.corezintervals.msgpackrbF)strict_map_key
   )level           T)bins_per_octavetuningsortn_binsfmin	intervalsr   r   r   returnc          	      C   s   t |trL|dkrd|tjd|td |  }n=|dkr#t||d}n2|dkr0tdg||d	}n%|d
kr>tddg||d	}n|dkrKtg d||d	}n	t|}t|}t	| | }tj
dt| | d|  }|rut|}|| S )a  Construct a set of frequencies from an interval set

    Parameters
    ----------
    n_bins : int
        The number of frequencies to generate

    fmin : float > 0
        The minimum frequency

    intervals : str or array of floats in [1, 2)
        If `str`, must be one of the following:
        - `'equal'` - equal temperament
        - `'pythagorean'` - Pythagorean intervals
        - `'ji3'` - 3-limit just intonation
        - `'ji5'` - 5-limit just intonation
        - `'ji7'` - 7-limit just intonation

        Otherwise, an array of intervals in the range [1, 2) can be provided.

    bins_per_octave : int > 0
        If `intervals` is a string specification, how many bins to
        generate per octave.
        If `intervals` is an array, then this parameter is ignored.

    tuning : float
        Deviation from A440 tuning in fractional bins.
        This is only used when `intervals == 'equal'`

    sort : bool
        Sort the intervals in ascending order.

    Returns
    -------
    frequencies : array of float
        The frequencies

    Examples
    --------
    Generate two octaves of Pythagorean intervals starting at 55Hz

    >>> librosa.interval_frequencies(24, fmin=55, intervals="pythagorean", bins_per_octave=12)
    array([ 55.   ,  58.733,  61.875,  66.075,  69.609,  74.334,  78.311,
            82.5  ,  88.099,  92.812,  99.112, 104.414, 110.   , 117.466,
           123.75 , 132.149, 139.219, 148.668, 156.621, 165.   , 176.199,
           185.625, 198.224, 208.828])

    Generate two octaves of 5-limit intervals starting at 55Hz

    >>> librosa.interval_frequencies(24, fmin=55, intervals="ji5", bins_per_octave=12)
    array([ 55.   ,  58.667,  61.875,  66.   ,  68.75 ,  73.333,  77.344,
            82.5  ,  88.   ,  91.667,  99.   , 103.125, 110.   , 117.333,
           123.75 , 132.   , 137.5  , 146.667, 154.687, 165.   , 176.   ,
           183.333, 198.   , 206.25 ])

    Generate three octaves using only three intervals

    >>> intervals = [1, 4/3, 3/2]
    >>> librosa.interval_frequencies(9, fmin=55, intervals=intervals)
    array([ 55.   ,  73.333,  82.5  , 110.   , 146.667, 165.   , 220.   ,
       293.333, 330.   ])
    equalg       @r   dtypepythagoreanr   r   ji3   )primesr   r   ji5   ji7)r!   r$      N)
isinstancestrnparangefloatpythagorean_intervalsplimit_intervalsarraylenceilmultiplyouterflattenr   )	r   r   r   r   r   r   ratios	n_octaves
all_ratios r7   J/home/ubuntu/.local/lib/python3.10/site-packages/librosa/core/intervals.pyinterval_frequencies   s:   
H



r9   .r   r   return_factorsr;   c                 C      d S Nr7   r:   r7   r7   r8   r,      s   r,   r   c                 C   r<   r=   r7   r:   r7   r7   r8   r,         c                 C   r<   r=   r7   r:   r7   r7   r8   r,      r>   c                    s   t | t t d \} |dk }||  d7  <  |  d7  <  t |r6t |}|| }nt| }|rHt fdd|D S t 	d|S )a  Pythagorean intervals

    Intervals are constructed by stacking ratios of 3/2 (i.e.,
    just perfect fifths) and folding down to a single octave::

        1, 3/2, 9/8, 27/16, 81/64, ...

    Note that this differs from 3-limit just intonation intervals
    in that Pythagorean intervals only use positive powers of 3
    (ascending fifths) while 3-limit intervals use both positive
    and negative powers (descending fifths).

    Parameters
    ----------
    bins_per_octave : int
        The number of intervals to generate
    sort : bool
        If `True` then intervals are returned in ascending order.
        If `False`, then intervals are returned in circle-of-fifths order.
    return_factors : bool
        If `True` then return a list of dictionaries encoding the prime factorization
        of each interval as `{2: p2, 3: p3}` (meaning `3**p3 * 2**p2`).
        If `False` (default), return intervals as an array of floating point numbers.

    Returns
    -------
    intervals : np.ndarray or list of dictionaries
        The constructed interval set. All intervals are mapped
        to the range [1, 2).

    See Also
    --------
    plimit_intervals

    Examples
    --------
    Generate the first 12 intervals

    >>> librosa.pythagorean_intervals(bins_per_octave=12)
    array([1.      , 1.067871, 1.125   , 1.201355, 1.265625, 1.351524,
           1.423828, 1.5     , 1.601807, 1.6875  , 1.802032, 1.898437])
    >>> # Compare to the 12-tone equal temperament intervals:
    >>> 2**(np.arange(12)/12)
    array([1.      , 1.059463, 1.122462, 1.189207, 1.259921, 1.33484 ,
           1.414214, 1.498307, 1.587401, 1.681793, 1.781797, 1.887749])

    Or the first 7, in circle-of-fifths order

    >>> librosa.pythagorean_intervals(bins_per_octave=7, sort=False)
    array([1.      , 1.5     , 1.125   , 1.6875  , 1.265625, 1.898437,
           1.423828])

    Generate the first 7, in circle-of-fifths other and factored form

    >>> librosa.pythagorean_intervals(bins_per_octave=7, sort=False, return_factors=True)
    [
        {2: 0, 3: 0},
        {2: -1, 3: 1},
        {2: -3, 3: 2},
        {2: -4, 3: 3},
        {2: -6, 3: 4},
        {2: -7, 3: 5},
        {2: -9, 3: 6}
    ]
    r!   r      c                 3   s$    | ]} |  | d V  qdS ))r
   r!   Nr7   ).0ipow2pow3r7   r8   	<genexpr>   s   " z(pythagorean_intervals.<locals>.<genexpr>r
   )
r)   r*   modflog2astypeintargsortrangelistpower)r   r   r;   
log_ratios	too_smallidxr7   rB   r8   r,      s   
F


c                 C   sr   t |}t |}t |d}|| }t |d}|| }t ||t || }t | || d|  dS )u  Compute the harmonic distance between ratios a and b.

    Harmonic distance is defined as `log2(a * b) - 2*log2(gcd(a, b))` [#]_.

    Here we are expressing a and b as prime factorization exponents,
    and the prime basis are provided in their log2 form.

    .. [#] Tenney, James.
        "On ‘Crystal Growth’ in harmonic space (1993–1998)."
        Contemporary Music Review 27.1 (2008): 47-56.
    r   r
      )r)   r.   maximumminimumarounddot)logsaba_numa_denb_numb_dengcdr7   r7   r8   __harmonic_distance  s   

r^   c                 C   s    | t| | t|k S )z-Given two tuples of prime powers, break ties.)rU   r)   abs)rW   rX   rV   r7   r7   r8   _crystal_tie_break"  s    r`   r"   c                 C   r<   r=   r7   r"   r   r   r;   r7   r7   r8   r-   '     r-   c                 C   r<   r=   r7   ra   r7   r7   r8   r-   2  rb   c                 C   r<   r=   r7   ra   r7   r7   r8   r-   =  rb   c                 C   s  t | } t j| t jd}g }tt| D ]}dgt|  }d||< |t| d||< |t| q| }t	 }	t
 }
tdgt|  }|
| t|
|k rt j}d}t|D ]C\}}d}|
D ]$}||f|	vrt||||	||f< |	||f |	||f< ||	||f 7 }qd||k st ||rt||| |r|}|}q\||}|
| |D ]}tt |t | }||
vr||vr|| qt|
|k sSt jt
|
td}t ||\}}|dk }||  d7  < ||  d8  < |t}|rt |}|| }nt|}|r=g }|D ](}t	 }|| dkr%||  |d< |dd t| || D  || q|S t d|S )	u
  Construct p-limit intervals for a given set of prime factors.

    This function is based on the "harmonic crystal growth" algorithm
    of [#1]_ [#2]_.

    .. [#1] Tenney, James.
        "On ‘Crystal Growth’ in harmonic space (1993–1998)."
        Contemporary Music Review 27.1 (2008): 47-56.

    .. [#2] Sabat, Marc, and James Tenney.
        "Three crystal growth algorithms in 23-limit constrained harmonic space."
        Contemporary Music Review 27, no. 1 (2008): 57-78.

    Parameters
    ----------
    primes : array of odd primes
        Which prime factors are to be used
    bins_per_octave : int
        The number of intervals to construct
    sort : bool
        If `True` then intervals are returned in ascending order.
        If `False`, then intervals are returned in crystal growth order.
    return_factors : bool
        If `True` then return a list of dictionaries encoding the prime factorization
        of each interval as `{2: p2, 3: p3, ...}` (meaning `3**p3 * 2**p2`).
        If `False` (default), return intervals as an array of floating point numbers.

    Returns
    -------
    intervals : np.ndarray or list of dictionaries
        The constructed interval set. All intervals are mapped
        to the range [1, 2).

    See Also
    --------
    pythagorean_intervals

    Examples
    --------
    Compare 3-limit tuning to Pythagorean tuning and 12-TET

    >>> librosa.plimit_intervals(primes=[3], bins_per_octave=12)
    array([1.        , 1.05349794, 1.125     , 1.18518519, 1.265625  ,
           1.33333333, 1.40466392, 1.5       , 1.58024691, 1.6875    ,
           1.77777778, 1.8984375 ])
    >>> # Pythagorean intervals:
    >>> librosa.pythagorean_intervals(bins_per_octave=12)
    array([1.        , 1.06787109, 1.125     , 1.20135498, 1.265625  ,
           1.35152435, 1.42382812, 1.5       , 1.60180664, 1.6875    ,
           1.80203247, 1.8984375 ])
    >>> # 12-TET intervals:
    >>> 2**(np.arange(12)/12)
    array([1.        , 1.05946309, 1.12246205, 1.18920712, 1.25992105,
           1.33483985, 1.41421356, 1.49830708, 1.58740105, 1.68179283,
           1.78179744, 1.88774863])

    Create a 7-bin, 5-limit interval set

    >>> librosa.plimit_intervals(primes=[3, 5], bins_per_octave=7)
    array([1.        , 1.125     , 1.25      , 1.33333333, 1.5       ,
           1.66666667, 1.875     ])

    The same example, but now in factored form

    >>> librosa.plimit_intervals(primes=[3, 5], bins_per_octave=7,
    ...                          return_factors=True)
    [
        {},
        {2: -3, 3: 2},
        {2: -2, 5: 1},
        {2: 2, 3: -1},
        {2: -1, 3: 1},
        {3: -1, 5: 1},
        {2: -3, 3: 1, 5: 1}
    ]
    r   r   r?   r   r
   c                 S   s"   i | ]\}}|d kr|t |qS )r   )rI   )r@   prM   r7   r7   r8   
<dictcomp>  s   " z$plimit_intervals.<locals>.<dictcomp>)r)   
atleast_1drG   float64rK   r/   appendtuplecopydictrL   inf	enumerater^   iscloser`   popr.   r+   rF   rU   rH   rI   rJ   updateziprM   )r"   r   r   r;   rV   seedsrA   seedfrontier	distancesr   rootscorebest_ffpointHDs	new_point_new_seedpowsrN   rC   rO   rP   factorsvr7   r7   r8   r-   H  sx   
T







)$__doc__typingr   r   r   r   r   r   typing_extensionsr   msgpacknumpyr)   numpy.typingr	   _cacher   _typingr   
util.filesr   imsgpackopen_fdescload	INTERVALSrI   r(   r+   boolndarrayr9   r,   r^   r`   r-   r7   r7   r7   r8   <module>   s   l	g 


