Repository: librosa/librosa

Issue:
Clarify kwargs in feature functions
Some of our feature functions (melspectrogram, mfcc, etc) use kwargs to pass through parameters to core functions (stft, filter construction etc).  This isn't terribly well documented, and can be a little difficult for new users to navigate and understand what the options are.

At this point, it's probably worth replacing some of these kwargs, eg
https://github.com/librosa/librosa/blob/25538adb3aed3485a06e60b6dad88be3d540f0c2/librosa/feature/spectral.py#L1767-L1769
by
```python 
def mfcc(
    *, y=None, sr=22050, S=None, n_mfcc=20, dct_type=2, norm="ortho", lifter=0,
    n_mels=128, n_fft=2048, ...
):
```

Alternatively, if we don't want to make the API totally redundant, we could at least provide more documentation in the kwarg'ed functions' docstrings to better explain what options are available.


Discussion:
If no one has started working on this issue I'd like to give it a try!
Awesome, thanks!
@Embot2000 thank you for taking this :)

Is the plan to copy-paste the docstring of called functions or to have some sort of dynamic formatting? 

That's what we do in Kymatio: https://github.com/kymatio/kymatio/blob/main/kymatio/scattering2d/frontend/base_frontend.py#L109=
and it kinda works: https://www.kymat.io/codereference.html#module-kymatio.torch

The advantage is that it reduces duplicate documentation and thus is easier to maintain. The disadvantage is that it becomes more difficult to read the documentation directly from the Python source.


@lostanlen Huh, I didn't know that was possible.  I was figuring to just copy-paste these explicitly, since the parameters in question are pretty standard and have not changed in years.  But I'm open to more elegant solutions as well.
i'm OK for copy-pasting. as you said, it's not like we're going to need to rephrase these docs many times in the future; and i we ever needed to, we'll just have to remember to make a search-and-replace. i just wanted to mention the other solution for completeness
@lostanlen thanks for that! Honestly my plan was to copy and paste but I will take a look at this! 

I was going to ask if the preferred fix would be option 1 in the issue description or option 2. I was leaning towards just updating the docstrings and leaving the API as is. It sounds like that's what you guys were leaning towards as well?
Yeah, that sounds good to me!
@Embot2000 yes, option 1. "Simple is better than complex" 😊 

Dynamic formatting is a cool trick but having an MFCC docstring that reads like

```
...
{n_mels_definition}
{n_stft_definition}
{win_length_definition}
...
```

will cause immense frustration for people (like me) who like to read documentation directly from the source. A frustration that isn't justified by saving 15 minutes of a maintainer's time in the next 2 years 😅 

So, copy-paste it is.

OK good luck!
OK, I went through all of the feature functions and these are what I found:

`spectral.py`
1. `zero_crossing_rate()`
2. `chroma_stft()`
3. `tonnetz()`
4. `mfcc()`
5. `melspectrogram()`

`inverse.py`
1. `mel_to_stft()`
2. `mel_to_audio()`
3. `mfcc_to_audio()`

`utils.py`
1. `delta()`
2. `stack_memory()`

Please let me know if I missed any or if any of these are not necessary to change.
Thanks @Embot2000 - that looks like a good start.  I might hold off on the last two since they're kwargs to external functions in numpy and scipy.

On the feature side, I think you have it covered.  We could also look at some other parts of the package after that, eg effects and decompose, but let's get the feature parts done first.

Resolving patch:
diff --git a/librosa/feature/inverse.py b/librosa/feature/inverse.py
--- a/librosa/feature/inverse.py
+++ b/librosa/feature/inverse.py
@@ -30,9 +30,26 @@ def mel_to_stft(M, *, sr=22050, n_fft=2048, power=2.0, **kwargs):
         number of FFT components in the resulting STFT
     power : float > 0 [scalar]
         Exponent for the magnitude melspectrogram
-    **kwargs : additional keyword arguments
-        Mel filter bank parameters.
-        See `librosa.filters.mel` for details
+    **kwargs : additional keyword arguments for Mel filter bank parameters
+    n_mels : int > 0 [scalar]
+        number of Mel bands to generate
+    fmin : float >= 0 [scalar]
+        lowest frequency (in Hz)
+    fmax : float >= 0 [scalar]
+        highest frequency (in Hz).
+        If `None`, use ``fmax = sr / 2.0``
+    htk : bool [scalar]
+        use HTK formula instead of Slaney
+    norm : {None, 'slaney', or number} [scalar]
+        If 'slaney', divide the triangular mel weights by the width of
+        the mel band (area normalization).
+        If numeric, use `librosa.util.normalize` to normalize each filter
+        by to unit l_p norm. See `librosa.util.normalize` for a full
+        description of supported norm values (including `+-np.inf`).
+        Otherwise, leave all the triangles aiming for a peak value of 1.0
+    dtype : np.dtype
+        The data type of the output basis.
+        By default, uses 32-bit (single-precision) floating point.
 
     Returns
     -------
@@ -136,8 +153,23 @@ def mel_to_audio(
         samples.
     dtype : np.dtype
         Real numeric type for the time-domain signal.  Default is 32-bit float.
-    **kwargs : additional keyword arguments
-        Mel filter bank parameters
+    **kwargs : additional keyword arguments for Mel filter bank parameters
+    n_mels : int > 0 [scalar]
+        number of Mel bands to generate
+    fmin : float >= 0 [scalar]
+        lowest frequency (in Hz)
+    fmax : float >= 0 [scalar]
+        highest frequency (in Hz).
+        If `None`, use ``fmax = sr / 2.0``
+    htk : bool [scalar]
+        use HTK formula instead of Slaney
+    norm : {None, 'slaney', or number} [scalar]
+        If 'slaney', divide the triangular mel weights by the width of
+        the mel band (area normalization).
+        If numeric, use `librosa.util.normalize` to normalize each filter
+        by to unit l_p norm. See `librosa.util.normalize` for a full
+        description of supported norm values (including `+-np.inf`).
+        Otherwise, leave all the triangles aiming for a peak value of 1.0
 
     Returns
     -------
@@ -181,26 +213,19 @@ def mfcc_to_mel(mfcc, *, n_mels=128, dct_type=2, norm="ortho", ref=1.0, lifter=0
     ----------
     mfcc : np.ndarray [shape=(..., n_mfcc, n)]
         The Mel-frequency cepstral coefficients
-
     n_mels : int > 0
         The number of Mel frequencies
-
     dct_type : {1, 2, 3}
         Discrete cosine transform (DCT) type
         By default, DCT type-2 is used.
-
     norm : None or 'ortho'
         If ``dct_type`` is `2 or 3`, setting ``norm='ortho'`` uses an orthonormal
         DCT basis.
-
         Normalization is not supported for `dct_type=1`.
-
     ref : number or callable
         Reference power for (inverse) decibel calculation
-
     lifter : number >= 0
         If ``lifter>0``, apply inverse liftering (inverse cepstral filtering)::
-
             M[n, :] <- M[n, :] / (1 + sin(pi * (n + 1) / lifter) * lifter / 2)
 
     Returns
@@ -257,30 +282,56 @@ def mfcc_to_audio(
     ----------
     mfcc : np.ndarray [shape=(..., n_mfcc, n)]
         The Mel-frequency cepstral coefficients
-
     n_mels : int > 0
         The number of Mel frequencies
-
     dct_type : {1, 2, 3}
         Discrete cosine transform (DCT) type
         By default, DCT type-2 is used.
-
     norm : None or 'ortho'
         If ``dct_type`` is `2 or 3`, setting ``norm='ortho'`` uses an orthonormal
         DCT basis.
-
         Normalization is not supported for ``dct_type=1``.
-
     ref : number or callable
         Reference power for (inverse) decibel calculation
-
     lifter : number >= 0
         If ``lifter>0``, apply inverse liftering (inverse cepstral filtering)::
-
             M[n, :] <- M[n, :] / (1 + sin(pi * (n + 1) / lifter)) * lifter / 2
-
-    **kwargs : additional keyword arguments
-        Parameters to pass through to `mel_to_audio`
+    **kwargs : additional keyword arguments to pass through to `mel_to_audio`
+    M : np.ndarray [shape=(..., n_mels, n), non-negative]
+        The spectrogram as produced by `feature.melspectrogram`
+    sr : number > 0 [scalar]
+        sampling rate of the underlying signal
+    n_fft : int > 0 [scalar]
+        number of FFT components in the resulting STFT
+    hop_length : None or int > 0
+        The hop length of the STFT.  If not provided, it will default to ``n_fft // 4``
+    win_length : None or int > 0
+        The window length of the STFT.  By default, it will equal ``n_fft``
+    window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
+        A window specification as supported by `stft` or `istft`
+    center : boolean
+        If `True`, the STFT is assumed to use centered frames.
+        If `False`, the STFT is assumed to use left-aligned frames.
+    pad_mode : string
+        If ``center=True``, the padding mode to use at the edges of the signal.
+        By default, STFT uses zero padding.
+    power : float > 0 [scalar]
+        Exponent for the magnitude melspectrogram
+    n_iter : int > 0
+        The number of iterations for Griffin-Lim
+    length : None or int > 0
+        If provided, the output ``y`` is zero-padded or clipped to exactly ``length``
+        samples.
+    dtype : np.dtype
+        Real numeric type for the time-domain signal.  Default is 32-bit float.
+    **kwargs : additional keyword arguments for Mel filter bank parameters
+    fmin : float >= 0 [scalar]
+        lowest frequency (in Hz)
+    fmax : float >= 0 [scalar]
+        highest frequency (in Hz).
+        If `None`, use ``fmax = sr / 2.0``
+    htk : bool [scalar]
+        use HTK formula instead of Slaney
 
     Returns
     -------
diff --git a/librosa/feature/spectral.py b/librosa/feature/spectral.py
--- a/librosa/feature/spectral.py
+++ b/librosa/feature/spectral.py
@@ -71,47 +71,35 @@ def spectral_centroid(
     ----------
     y : np.ndarray [shape=(..., n,)] or None
         audio time series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         audio sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)] or None
         (optional) spectrogram magnitude
-
     n_fft : int > 0 [scalar]
         FFT window size
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     freq : None or np.ndarray [shape=(d,) or shape=(d, t)]
         Center frequencies for spectrogram bins.
         If `None`, then FFT bin center frequencies are used.
-
         Otherwise, it can be a single array of ``d`` center frequencies,
         or a matrix of center frequencies as constructed by
         `librosa.reassigned_spectrogram`
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length ``win_length`` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           `t` is centered at ``y[t * hop_length]``.
         - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
@@ -224,57 +212,42 @@ def spectral_bandwidth(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         audio sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)] or None
         (optional) spectrogram magnitude
-
     n_fft : int > 0 [scalar]
         FFT window size
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length ``win_length`` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           ``t`` is centered at ``y[t * hop_length]``.
         - If ``False``, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
-
     freq : None or np.ndarray [shape=(d,) or shape=(..., d, t)]
         Center frequencies for spectrogram bins.
-
         If `None`, then FFT bin center frequencies are used.
         Otherwise, it can be a single array of ``d`` center frequencies,
         or a matrix of center frequencies as constructed by
         `librosa.reassigned_spectrogram`
-
     centroid : None or np.ndarray [shape=(..., 1, t)]
         pre-computed centroid frequencies
-
     norm : bool
         Normalize per-frame spectral energy (sum to one)
-
     p : float > 0
         Power to raise deviation from spectral centroid.
 
@@ -405,63 +378,46 @@ def spectral_contrast(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time series. Multi-channel is supported.
-
     sr : number  > 0 [scalar]
         audio sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)] or None
         (optional) spectrogram magnitude
-
     n_fft : int > 0 [scalar]
         FFT window size
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length `win_length` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           ``t`` is centered at ``y[t * hop_length]``.
         - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
-
     freq : None or np.ndarray [shape=(d,)]
         Center frequencies for spectrogram bins.
-
         If `None`, then FFT bin center frequencies are used.
         Otherwise, it can be a single array of ``d`` center frequencies.
-
     fmin : float > 0
         Frequency cutoff for the first bin ``[0, fmin]``
         Subsequent bins will cover ``[fmin, 2*fmin]`, `[2*fmin, 4*fmin]``, etc.
-
     n_bands : int > 1
         number of frequency bands
-
     quantile : float in (0, 1)
         quantile for determining peaks and valleys
-
     linear : bool
         If `True`, return the linear difference of magnitudes:
         ``peaks - valleys``.
-
         If `False`, return the logarithmic difference:
         ``log(peaks) - log(valleys)``.
 
@@ -593,50 +549,37 @@ def spectral_rolloff(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         audio sampling rate of ``y``
-
     S : np.ndarray [shape=(d, t)] or None
         (optional) spectrogram magnitude
-
     n_fft : int > 0 [scalar]
         FFT window size
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length `win_length` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           ``t`` is centered at ``y[t * hop_length]``.
         - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
-
     freq : None or np.ndarray [shape=(d,) or shape=(..., d, t)]
         Center frequencies for spectrogram bins.
         If `None`, then FFT bin center frequencies are used.
         Otherwise, it can be a single array of ``d`` center frequencies,
-
         .. note:: ``freq`` is assumed to be sorted in increasing order
-
     roll_percent : float [0 < roll_percent < 1]
         Roll-off percentage.
 
@@ -757,43 +700,32 @@ def spectral_flatness(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time series. Multi-channel is supported.
-
     S : np.ndarray [shape=(..., d, t)] or None
         (optional) pre-computed spectrogram magnitude
-
     n_fft : int > 0 [scalar]
         FFT window size
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length `win_length` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           ``t`` is centered at ``y[t * hop_length]``.
         - If `False`, then frame `t` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
-
     amin : float > 0 [scalar]
         minimum threshold for ``S`` (=added noise floor for numerical stability)
-
     power : float > 0 [scalar]
         Exponent for the magnitude spectrogram.
         e.g., 1 for energy, 2 for power, etc.
@@ -880,22 +812,16 @@ def rms(
     y : np.ndarray [shape=(..., n)] or None
         (optional) audio time series. Required if ``S`` is not input.
         Multi-channel is supported.
-
     S : np.ndarray [shape=(..., d, t)] or None
         (optional) spectrogram magnitude. Required if ``y`` is not input.
-
     frame_length : int > 0 [scalar]
         length of analysis frame (in samples) for energy calculation
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     center : bool
         If `True` and operating on time-domain input (``y``), pad the signal
         by ``frame_length//2`` on either side.
-
         If operating on spectrogram input, this has no effect.
-
     pad_mode : str
         Padding mode for centered analysis.  See `numpy.pad` for valid
         values.
@@ -994,46 +920,34 @@ def poly_features(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         audio sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)] or None
         (optional) spectrogram magnitude
-
     n_fft : int > 0 [scalar]
         FFT window size
-
     hop_length : int > 0 [scalar]
         hop length for STFT. See `librosa.stft` for details.
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length `win_length` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           `t` is centered at ``y[t * hop_length]``.
         - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
-
     order : int > 0
         order of the polynomial to fit
-
     freq : None or np.ndarray [shape=(d,) or shape=(..., d, t)]
         Center frequencies for spectrogram bins.
         If `None`, then FFT bin center frequencies are used.
@@ -1135,24 +1049,30 @@ def zero_crossing_rate(y, *, frame_length=2048, hop_length=512, center=True, **k
     ----------
     y : np.ndarray [shape=(..., n)]
         Audio time series. Multi-channel is supported.
-
     frame_length : int > 0
         Length of the frame over which to compute zero crossing rates
-
     hop_length : int > 0
         Number of samples to advance for each frame
-
     center : bool
         If `True`, frames are centered by padding the edges of ``y``.
         This is similar to the padding in `librosa.stft`,
         but uses edge-value copies instead of zero-padding.
-
-    **kwargs : additional keyword arguments
-        See `librosa.zero_crossings`
-
+    **kwargs : additional keyword arguments to pass to `librosa.zero_crossings`
+    threshold : float > 0 or None
+        If specified, values where ``-threshold <= y <= threshold`` are
+        clipped to 0.
+    ref_magnitude : float > 0 or callable
+        If numeric, the threshold is scaled relative to ``ref_magnitude``.
+        If callable, the threshold is scaled relative to
+        ``ref_magnitude(np.abs(y))``.
+    zero_pos : boolean
+        If ``True`` then the value 0 is interpreted as having positive sign.
+        If ``False``, then 0, -1, and +1 all have distinct signs.
+    axis : int
+        Axis along which to compute zero-crossings.
         .. note:: By default, the ``pad`` parameter is set to `False`, which
-            differs from the default specified by
-            `librosa.zero_crossings`.
+        differs from the default specified by
+        `librosa.zero_crossings`.
 
     Returns
     -------
@@ -1218,59 +1138,56 @@ def chroma_stft(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)] or None
         power spectrogram
-
     norm : float or None
         Column-wise normalization.
         See `librosa.util.normalize` for details.
-
         If `None`, no normalization is performed.
-
     n_fft : int  > 0 [scalar]
         FFT window size if provided ``y, sr`` instead of ``S``
-
     hop_length : int > 0 [scalar]
         hop length if provided ``y, sr`` instead of ``S``
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length `win_length` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           ``t`` is centered at ``y[t * hop_length]``.
         - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
         By default, STFT uses zero padding.
-
     tuning : float [scalar] or None.
         Deviation from A440 tuning in fractional chroma bins.
         If `None`, it is automatically estimated.
-
     n_chroma : int > 0 [scalar]
         Number of chroma bins to produce (12 by default).
-
-    **kwargs : additional keyword arguments
-        Arguments to parameterize chroma filters.
-        See `librosa.filters.chroma` for details.
+    **kwargs : additional keyword arguments to parameterize chroma filters.
+    ctroct : float > 0 [scalar]
+    octwidth : float > 0 or None [scalar]
+        ``ctroct`` and ``octwidth`` specify a dominance window:
+        a Gaussian weighting centered on ``ctroct`` (in octs, A0 = 27.5Hz)
+        and with a gaussian half-width of ``octwidth``.
+        Set ``octwidth`` to `None` to use a flat weighting.
+    norm : float > 0 or np.inf
+        Normalization factor for each filter
+    base_c : bool
+        If True, the filter bank will start at 'C'.
+        If False, the filter bank will start at 'A'.
+    dtype : np.dtype
+        The data type of the output basis.
+        By default, uses 32-bit (single-precision) floating point.
 
     Returns
     -------
@@ -1373,47 +1290,33 @@ def chroma_cqt(
     ----------
     y : np.ndarray [shape=(..., n,)]
         audio time series. Multi-channel is supported.
-
     sr : number > 0
         sampling rate of ``y``
-
     C : np.ndarray [shape=(..., d, t)] [Optional]
         a pre-computed constant-Q spectrogram
-
     hop_length : int > 0
         number of samples between successive chroma frames
-
     fmin : float > 0
         minimum frequency to analyze in the CQT.
-
         Default: `C1 ~= 32.7 Hz`
-
     norm : int > 0, +-np.inf, or None
         Column-wise normalization of the chromagram.
-
     threshold : float
         Pre-normalization energy threshold.  Values below the
         threshold are discarded, resulting in a sparse chromagram.
-
     tuning : float
         Deviation (in fractions of a CQT bin) from A440 tuning
-
     n_chroma : int > 0
         Number of chroma bins to produce
-
     n_octaves : int > 0
         Number of octaves to analyze above ``fmin``
-
     window : None or np.ndarray
         Optional window parameter to `filters.cq_to_chroma`
-
     bins_per_octave : int > 0, optional
         Number of bins per octave in the CQT.
         Must be an integer multiple of ``n_chroma``.
         Default: 36 (3 bins per semitone)
-
         If `None`, it will match ``n_chroma``.
-
     cqt_mode : ['full', 'hybrid']
         Constant-Q transform mode
 
@@ -1531,47 +1434,33 @@ def chroma_cens(
     ----------
     y : np.ndarray [shape=(..., n,)]
         audio time series. Multi-channel is supported.
-
     sr : number > 0
         sampling rate of ``y``
-
     C : np.ndarray [shape=(d, t)] [Optional]
         a pre-computed constant-Q spectrogram
-
     hop_length : int > 0
         number of samples between successive chroma frames
-
     fmin : float > 0
         minimum frequency to analyze in the CQT.
         Default: `C1 ~= 32.7 Hz`
-
     norm : int > 0, +-np.inf, or None
         Column-wise normalization of the chromagram.
-
     tuning : float
         Deviation (in fractions of a CQT bin) from A440 tuning
-
     n_chroma : int > 0
         Number of chroma bins to produce
-
     n_octaves : int > 0
         Number of octaves to analyze above ``fmin``
-
     window : None or np.ndarray
         Optional window parameter to `filters.cq_to_chroma`
-
     bins_per_octave : int > 0
         Number of bins per octave in the CQT.
-
         Default: 36
-
     cqt_mode : ['full', 'hybrid']
         Constant-Q transform mode
-
     win_len_smooth : int > 0 or None
         Length of temporal smoothing window. `None` disables temporal smoothing.
         Default: 41
-
     smoothing_window : str, float or tuple
         Type of window function for temporal smoothing. See `librosa.filters.get_window` for possible inputs.
         Default: 'hann'
@@ -1674,18 +1563,40 @@ def tonnetz(*, y=None, sr=22050, chroma=None, **kwargs):
     ----------
     y : np.ndarray [shape=(..., n,)] or None
         Audio time series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         sampling rate of ``y``
-
     chroma : np.ndarray [shape=(n_chroma, t)] or None
         Normalized energy for each chroma bin at each frame.
-
         If `None`, a cqt chromagram is performed.
-
-    **kwargs
-        Additional keyword arguments to `chroma_cqt`, if ``chroma`` is not
-        pre-computed.
+    **kwargs : Additional keyword arguments to `chroma_cqt`,
+        if ``chroma`` is not pre-computed.
+    C : np.ndarray [shape=(..., d, t)] [Optional]
+        a pre-computed constant-Q spectrogram
+    hop_length : int > 0
+        number of samples between successive chroma frames
+    fmin : float > 0
+        minimum frequency to analyze in the CQT.
+        Default: `C1 ~= 32.7 Hz`
+    norm : int > 0, +-np.inf, or None
+        Column-wise normalization of the chromagram.
+    threshold : float
+        Pre-normalization energy threshold.  Values below the
+        threshold are discarded, resulting in a sparse chromagram.
+    tuning : float
+        Deviation (in fractions of a CQT bin) from A440 tuning
+    n_chroma : int > 0
+        Number of chroma bins to produce
+    n_octaves : int > 0
+        Number of octaves to analyze above ``fmin``
+    window : None or np.ndarray
+        Optional window parameter to `filters.cq_to_chroma`
+    bins_per_octave : int > 0, optional
+        Number of bins per octave in the CQT.
+        Must be an integer multiple of ``n_chroma``.
+        Default: 36 (3 bins per semitone)
+        If `None`, it will match ``n_chroma``.
+    cqt_mode : ['full', 'hybrid']
+        Constant-Q transform mode
 
     Returns
     -------
@@ -1778,37 +1689,65 @@ def mfcc(
     ----------
     y : np.ndarray [shape=(..., n,)] or None
         audio time series. Multi-channel is supported..
-
     sr : number > 0 [scalar]
         sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)] or None
         log-power Mel spectrogram
-
     n_mfcc : int > 0 [scalar]
         number of MFCCs to return
-
     dct_type : {1, 2, 3}
         Discrete cosine transform (DCT) type.
         By default, DCT type-2 is used.
-
     norm : None or 'ortho'
         If ``dct_type`` is `2 or 3`, setting ``norm='ortho'`` uses an ortho-normal
         DCT basis.
-
         Normalization is not supported for ``dct_type=1``.
-
     lifter : number >= 0
         If ``lifter>0``, apply *liftering* (cepstral filtering) to the MFCCs::
-
             M[n, :] <- M[n, :] * (1 + sin(pi * (n + 1) / lifter) * lifter / 2)
-
         Setting ``lifter >= 2 * n_mfcc`` emphasizes the higher-order coefficients.
         As ``lifter`` increases, the coefficient weighting becomes approximately linear.
-
-    **kwargs : additional keyword arguments
-        Arguments to `melspectrogram`, if operating
-        on time series input
+    **kwargs : additional keyword arguments to `melspectrogram`
+        if operating on time series input
+    n_fft : int > 0 [scalar]
+        length of the FFT window
+    hop_length : int > 0 [scalar]
+        number of samples between successive frames.
+        See `librosa.stft`
+    win_length : int <= n_fft [scalar]
+        Each frame of audio is windowed by `window()`.
+        The window will be of length `win_length` and then padded
+        with zeros to match ``n_fft``.
+        If unspecified, defaults to ``win_length = n_fft``.
+    window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
+        - a window specification (string, tuple, or number);
+        see `scipy.signal.get_window`
+        - a window function, such as `scipy.signal.windows.hann`
+        - a vector or array of length ``n_fft``
+        .. see also:: `librosa.filters.get_window`
+    center : boolean
+        - If `True`, the signal ``y`` is padded so that frame
+        ``t`` is centered at ``y[t * hop_length]``.
+        - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
+    pad_mode : string
+        If ``center=True``, the padding mode to use at the edges of the signal.
+        By default, STFT uses zero padding.
+    power : float > 0 [scalar]
+        Exponent for the magnitude melspectrogram.
+        e.g., 1 for energy, 2 for power, etc.
+    **kwargs : additional keyword arguments for Mel filter bank parameters
+    n_mels : int > 0 [scalar]
+        number of Mel bands to generate
+    fmin : float >= 0 [scalar]
+        lowest frequency (in Hz)
+    fmax : float >= 0 [scalar]
+        highest frequency (in Hz).
+        If `None`, use ``fmax = sr / 2.0``
+    htk : bool [scalar]
+        use HTK formula instead of Slaney
+    dtype : np.dtype
+        The data type of the output basis.
+        By default, uses 32-bit (single-precision) floating point.
 
     Returns
     -------
@@ -1934,53 +1873,56 @@ def melspectrogram(
     ----------
     y : np.ndarray [shape=(..., n)] or None
         audio time-series. Multi-channel is supported.
-
     sr : number > 0 [scalar]
         sampling rate of ``y``
-
     S : np.ndarray [shape=(..., d, t)]
         spectrogram
-
     n_fft : int > 0 [scalar]
         length of the FFT window
-
     hop_length : int > 0 [scalar]
         number of samples between successive frames.
         See `librosa.stft`
-
     win_length : int <= n_fft [scalar]
         Each frame of audio is windowed by `window()`.
         The window will be of length `win_length` and then padded
         with zeros to match ``n_fft``.
-
         If unspecified, defaults to ``win_length = n_fft``.
-
     window : string, tuple, number, function, or np.ndarray [shape=(n_fft,)]
         - a window specification (string, tuple, or number);
           see `scipy.signal.get_window`
         - a window function, such as `scipy.signal.windows.hann`
         - a vector or array of length ``n_fft``
-
         .. see also:: `librosa.filters.get_window`
-
     center : boolean
         - If `True`, the signal ``y`` is padded so that frame
           ``t`` is centered at ``y[t * hop_length]``.
         - If `False`, then frame ``t`` begins at ``y[t * hop_length]``
-
     pad_mode : string
         If ``center=True``, the padding mode to use at the edges of the signal.
-
         By default, STFT uses zero padding.
-
     power : float > 0 [scalar]
         Exponent for the magnitude melspectrogram.
         e.g., 1 for energy, 2 for power, etc.
-
-    **kwargs : additional keyword arguments
-        Mel filter bank parameters.
-
-        See `librosa.filters.mel` for details.
+    **kwargs : additional keyword arguments for Mel filter bank parameters
+    n_mels : int > 0 [scalar]
+        number of Mel bands to generate
+    fmin : float >= 0 [scalar]
+        lowest frequency (in Hz)
+    fmax : float >= 0 [scalar]
+        highest frequency (in Hz).
+        If `None`, use ``fmax = sr / 2.0``
+    htk : bool [scalar]
+        use HTK formula instead of Slaney
+    norm : {None, 'slaney', or number} [scalar]
+        If 'slaney', divide the triangular mel weights by the width of
+        the mel band (area normalization).
+        If numeric, use `librosa.util.normalize` to normalize each filter
+        by to unit l_p norm. See `librosa.util.normalize` for a full
+        description of supported norm values (including `+-np.inf`).
+        Otherwise, leave all the triangles aiming for a peak value of 1.0
+    dtype : np.dtype
+        The data type of the output basis.
+        By default, uses 32-bit (single-precision) floating point.
 
     Returns
     -------


Test patch: