
    PiU>                        d Z ddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZ ddlmZmZmZ g dZddd	ej        d
dddej        dej        dee         dee         dee         dededededej        fdZd
ddddej        dej        dededededej        fdZd
ddddej        dej        dej        dededededej        fdZdS )z3Harmonic calculations for frequency representations    N   )ParameterError)	is_unique)	ArrayLike)CallableOptionalSequence)salienceinterp_harmonicsf0_harmonicsTlinear)weights	aggregatefilter_peaks
fill_valuekindaxisSfreqs	harmonicsr   r   r   r   r   r   returnc                   |t           j        }|#t          j        t          |          f          }nt          j        |t
                    }t          | ||||          }	|t           j        u r ||	|dz
  |          }
n ||	|dz
            }
|r\t          j        	                    | |          }t          j
        | j                  }|                    |           |
|         ||<   |}
|
S )a  Harmonic salience function.

    Parameters
    ----------
    S : np.ndarray [shape=(..., d, n)]
        input time frequency magnitude representation (e.g. STFT or CQT magnitudes).
        Must be real-valued and non-negative.

    freqs : np.ndarray, shape=(S.shape[axis]) or shape=S.shape
        The frequency values corresponding to S's elements along the
        chosen axis.

        Frequencies can also be time-varying, e.g. as computed by
        `reassigned_spectrogram`, in which case the shape should
        match ``S``.

    harmonics : list-like, non-negative
        Harmonics to include in salience computation.  The first harmonic (1)
        corresponds to ``S`` itself. Values less than one (e.g., 1/2) correspond
        to sub-harmonics.

    weights : list-like
        The weight to apply to each harmonic in the summation. (default:
        uniform weights). Must be the same length as ``harmonics``.

    aggregate : function
        aggregation function (default: `np.average`)

        If ``aggregate=np.average``, then a weighted average is
        computed per-harmonic according to the specified weights.
        For all other aggregation functions, all harmonics
        are treated equally.

    filter_peaks : bool
        If true, returns harmonic summation only on frequencies of peak
        magnitude. Otherwise returns harmonic summation over the full spectrum.
        Defaults to True.

    fill_value : float
        The value to fill non-peaks in the output representation. (default:
        `np.nan`) Only used if ``filter_peaks == True``.

    kind : str
        Interpolation type for harmonic estimation.
        See `scipy.interpolate.interp1d`.

    axis : int
        The axis along which to compute harmonics

    Returns
    -------
    S_sal : np.ndarray
        ``S_sal`` will have the same shape as ``S``, and measure
        the overall harmonic energy at each frequency.

    See Also
    --------
    interp_harmonics

    Examples
    --------
    >>> y, sr = librosa.load(librosa.ex('trumpet'), duration=3)
    >>> S = np.abs(librosa.stft(y))
    >>> freqs = librosa.fft_frequencies(sr=sr)
    >>> harms = [1, 2, 3, 4]
    >>> weights = [1.0, 0.5, 0.33, 0.25]
    >>> S_sal = librosa.salience(S, freqs=freqs, harmonics=harms, weights=weights, fill_value=0)
    >>> print(S_sal.shape)
    (1025, 115)
    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots(nrows=2, sharex=True, sharey=True)
    >>> librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),
    ...                          sr=sr, y_axis='log', x_axis='time', ax=ax[0])
    >>> ax[0].set(title='Magnitude spectrogram')
    >>> ax[0].label_outer()
    >>> img = librosa.display.specshow(librosa.amplitude_to_db(S_sal,
    ...                                                        ref=np.max),
    ...                                sr=sr, y_axis='log', x_axis='time', ax=ax[1])
    >>> ax[1].set(title='Salience spectrogram')
    >>> fig.colorbar(img, ax=ax, format="%+2.0f dB")
    N)dtype)r   r   r   r      )r   r   r   )npaverageoneslenarrayfloatr   scipysignal	argrelmaxemptyshapefill)r   r   r   r   r   r   r   r   r   S_harmS_salS_peaksS_outs                i/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/librosa/core/harmonic.pyr
   r
      s    z J	'3y>>+,,(7%000au	SWXXXF BJ	&taxAAA	&tax000 ,(((66!!

:wgL    )r   r   r   xc          	         |j         dk    rt          |          | j        |         k    rxt          |d          st	          j        dd           t          j                            || |dd          }t          j
                            |          } ||          S |j        | j        k    rt          j        t          ||                    st	          j        dd           fd	}t          j        |d
          }	 |	|                    |d          |                     |d                                        d|                              d|dz
            S t          d|j         d| j                   )a  Compute the energy at harmonics of time-frequency representation.

    Given a frequency-based energy representation such as a spectrogram
    or tempogram, this function computes the energy at the chosen harmonics
    of the frequency axis.  (See examples below.)
    The resulting harmonic array can then be used as input to a salience
    computation.

    Parameters
    ----------
    x : np.ndarray
        The input energy
    freqs : np.ndarray, shape=(x.shape[axis]) or shape=x.shape
        The frequency values corresponding to x's elements along the
        chosen axis.
        Frequencies can also be time-varying, e.g. as computed by
        `reassigned_spectrogram`, in which case the shape should
        match ``x``.
    harmonics : list-like, non-negative
        Harmonics to compute as ``harmonics[i] * freqs``.
        The first harmonic (1) corresponds to ``freqs``.
        Values less than one (e.g., 1/2) correspond to sub-harmonics.
    kind : str
        Interpolation type.  See `scipy.interpolate.interp1d`.
    fill_value : float
        The value to fill when extrapolating beyond the observed
        frequency range.
    axis : int
        The axis along which to compute harmonics

    Returns
    -------
    x_harm : np.ndarray
        ``x_harm[i]`` will have the same shape as ``x``, and measure
        the energy at the ``harmonics[i]`` harmonic of each frequency.
        A new dimension indexing harmonics will be inserted immediately
        before ``axis``.

    See Also
    --------
    scipy.interpolate.interp1d

    Examples
    --------
    Estimate the harmonics of a time-averaged tempogram

    >>> y, sr = librosa.load(librosa.ex('sweetwaltz'))
    >>> # Compute the time-varying tempogram and average over time
    >>> tempi = np.mean(librosa.feature.tempogram(y=y, sr=sr), axis=1)
    >>> # We'll measure the first five harmonics
    >>> harmonics = [1, 2, 3, 4, 5]
    >>> f_tempo = librosa.tempo_frequencies(len(tempi), sr=sr)
    >>> # Build the harmonic tensor; we only have one axis here (tempo)
    >>> t_harmonics = librosa.interp_harmonics(tempi, freqs=f_tempo, harmonics=harmonics, axis=0)
    >>> print(t_harmonics.shape)
    (5, 384)

    >>> # And plot the results
    >>> import matplotlib.pyplot as plt
    >>> fig, ax = plt.subplots()
    >>> librosa.display.specshow(t_harmonics, x_axis='tempo', sr=sr, ax=ax)
    >>> ax.set(yticks=np.arange(len(harmonics)),
    ...        yticklabels=['{:.3g}'.format(_) for _ in harmonics],
    ...        ylabel='Harmonic', xlabel='Tempo (BPM)')

    We can also compute frequency harmonics for spectrograms.
    To calculate sub-harmonic energy, use values < 1.

    >>> y, sr = librosa.load(librosa.ex('trumpet'), duration=3)
    >>> harmonics = [1./3, 1./2, 1, 2, 3, 4]
    >>> S = np.abs(librosa.stft(y))
    >>> fft_freqs = librosa.fft_frequencies(sr=sr)
    >>> S_harm = librosa.interp_harmonics(S, freqs=fft_freqs, harmonics=harmonics, axis=0)
    >>> print(S_harm.shape)
    (6, 1025, 646)

    >>> fig, ax = plt.subplots(nrows=3, ncols=2, sharex=True, sharey=True)
    >>> for i, _sh in enumerate(S_harm):
    ...     img = librosa.display.specshow(librosa.amplitude_to_db(_sh,
    ...                                                      ref=S.max()),
    ...                              sr=sr, y_axis='log', x_axis='time',
    ...                              ax=ax.flat[i])
    ...     ax.flat[i].set(title='h={:.3g}'.format(harmonics[i]))
    ...     ax.flat[i].label_outer()
    >>> fig.colorbar(img, ax=ax, format="%+2.f dB")
    r   r   r   OFrequencies are not unique. This may produce incorrect harmonic interpolations.r   
stacklevelF)r   bounds_errorcopyr   r   c                     t           j                            | |dd          } |t          j                            |                     S )NF)r4   r5   r   r   )r#   interpolateinterp1dr   multiplyouter)_a_binterpr   r   r   s      r-   	_f_interpz#interp_harmonics.<locals>._f_interp  sQ    &//BUTj 0  F 6"+++B	::;;;r.   z(f),(f)->(f,h)	signaturer   freqs.shape=" is incompatible with input shape=)ndimr    r'   r   warningswarnr#   r7   r8   r   r9   r:   all	vectorizeswapaxesr   )
r/   r   r   r   r   r   f_interpf_outr>   xfuncs
     ```     r-   r   r      s   ~ zQ3u::66
 Q''' 	Ma   
 $--! . 
 
 !!)U33 x			viD11122 	Ma   	< 	< 	< 	< 	< 	< 	< Y2BCCC E%..r**AJJtR,@,@AAX 
 Xq 	
 S5;SS!'SS
 
 	
r.   f0c                   j         dk    rt                    | j        |         k    rt          d          st	          j        dd           t          j                  fd}t          j        |d	          } || 	                    |d
          t          j
                            ||                    	                    |d
          }	nj        | j        k    rt          j        t          |                    st	          j        dd           fd}
t          j        |
d	          } || 	                    |d
          	                    |d
          t          j
                            ||                    	                    |d
          }	nt          dj         d| j                   t          j        |	d          S )a  Compute the energy at selected harmonics of a time-varying
    fundamental frequency.

    This function can be used to reduce a `frequency * time` representation
    to a `harmonic * time` representation, effectively normalizing out for
    the fundamental frequency.  The result can be used as a representation
    of timbre when f0 corresponds to pitch, or as a representation of
    rhythm when f0 corresponds to tempo.

    This function differs from `interp_harmonics`, which computes the
    harmonics of *all* frequencies.

    Parameters
    ----------
    x : np.ndarray [shape=(..., frequencies, n)]
        The input array (e.g., STFT magnitudes)
    f0 : np.ndarray [shape=(..., n)]
        The fundamental frequency (f0) of each frame in the input
        Shape should match ``x.shape[-1]``
    freqs : np.ndarray, shape=(x.shape[axis]) or shape=x.shape
        The frequency values corresponding to X's elements along the
        chosen axis.
        Frequencies can also be time-varying, e.g. as computed by
        `reassigned_spectrogram`, in which case the shape should
        match ``x``.
    harmonics : list-like, non-negative
        Harmonics to compute as ``harmonics[i] * f0``
        Values less than one (e.g., 1/2) correspond to sub-harmonics.
    kind : str
        Interpolation type.  See `scipy.interpolate.interp1d`.
    fill_value : float
        The value to fill when extrapolating beyond the observed
        frequency range.
    axis : int
        The axis corresponding to frequency in ``x``

    Returns
    -------
    f0_harm : np.ndarray [shape=(..., len(harmonics), n)]
        Interpolated energy at each specified harmonic of the fundamental
        frequency for each time step.

    See Also
    --------
    interp_harmonics
    librosa.feature.tempogram_ratio

    Examples
    --------
    This example estimates the fundamental (f0), and then extracts the first
    12 harmonics

    >>> y, sr = librosa.load(librosa.ex('trumpet'))
    >>> f0, voicing, voicing_p = librosa.pyin(y=y, sr=sr, fmin=200, fmax=700)
    >>> S = np.abs(librosa.stft(y))
    >>> freqs = librosa.fft_frequencies(sr=sr)
    >>> harmonics = np.arange(1, 13)
    >>> f0_harm = librosa.f0_harmonics(S, freqs=freqs, f0=f0, harmonics=harmonics)

    >>> import matplotlib.pyplot as plt
    >>> fig, ax =plt.subplots(nrows=2, sharex=True)
    >>> librosa.display.specshow(librosa.amplitude_to_db(S, ref=np.max),
    ...                          x_axis='time', y_axis='log', ax=ax[0])
    >>> times = librosa.times_like(f0)
    >>> for h in harmonics:
    ...     ax[0].plot(times, h * f0, label=f"{h}*f0")
    >>> ax[0].legend(ncols=4, loc='lower right')
    >>> ax[0].label_outer()
    >>> librosa.display.specshow(librosa.amplitude_to_db(f0_harm, ref=np.max),
    ...                          x_axis='time', ax=ax[1])
    >>> ax[1].set_yticks(harmonics-1)
    >>> ax[1].set_yticklabels(harmonics)
    >>> ax[1].set(ylabel='Harmonics')
    r   r   r   r1   r   r2   c           
          t           j                                     |          dddd          } ||          S Nr   F)r   r4   r5   assume_sortedr   r   )r#   r7   r8   )datafr=   r   r   idxr   s      r-   
_f_interpsz f0_harmonics.<locals>._f_interps  sP    &//c
S	"#% 0 	 	F 6!99r.   z(f),(h)->(h)r?   rA   c           
          t          j        |          }t          j                            ||         | |         dddd          } ||          S rP   )r   isfiniter#   r7   r8   )rR   frequenciesrS   rT   r=   r   r   s        r-   
_f_interpdz f0_harmonics.<locals>._f_interpd  s`    +k**C&//C S	"#% 0 	 	F 6!99r.   z(f),(f),(h)->(h)rB   rC   F)r5   nan)rD   r    r'   r   rE   rF   r   rW   rH   rI   r9   r:   rG   r   
nan_to_num)r/   rM   r   r   r   r   r   rU   rL   resultrY   rT   s     ` ``     @r-   r   r   /  s   j zQ3u::66Q''' 	Ma    k%  	 	 	 	 	 	 	 	 Z>BBBqzz$++R[->->r9-M-MNNWW"
 
 
		viD11122 	Ma   	 	 	 	 	 	 Z3EFFFJJtR  NN4$$Kb),,
 
 (4

	 	 S5;SS!'SS
 
 	
 =e<<<<r.   )__doc__rE   numpyr   scipy.interpolater#   scipy.signalutil.exceptionsr   utilr   numpy.typingr   typingr   r   r	   __all__rZ   ndarrayr"   boolstrintr
   r   r    r.   r-   <module>rk      sn   : 9              , , , , , ,       " " " " " " / / / / / / / / / /
:
:
: $($(u u u	zu :u 	u
 i u !u u u u u Zu u u uz b
 b
 b
	zb
 :b
 	b

 b
 b
 b
 Zb
 b
 b
 b
V S= S= S=	zS= 	
S= :	S=
 S= S= S= S= ZS= S= S= S= S= S=r.   