@cache(level=30)
def hpss(S, kernel_size=31, power=2.0, mask=False, margin=1.0):
    'Median-filtering harmonic percussive source separation (HPSS).\n\n    If `margin = 1.0`, decomposes an input spectrogram `S = H + P`\n    where `H` contains the harmonic components,\n    and `P` contains the percussive components.\n\n    If `margin > 1.0`, decomposes an input spectrogram `S = H + P + R`\n    where `R` contains residual components not included in `H` or `P`.\n\n    This implementation is based upon the algorithm described by [1]_ and [2]_.\n\n    .. [1] Fitzgerald, Derry.\n        "Harmonic/percussive separation using median filtering."\n        13th International Conference on Digital Audio Effects (DAFX10),\n        Graz, Austria, 2010.\n\n    .. [2] Driedger, Müller, Disch.\n        "Extending harmonic-percussive separation of audio."\n        15th International Society for Music Information Retrieval Conference (ISMIR 2014),\n        Taipei, Taiwan, 2014.\n\n    Parameters\n    ----------\n    S : np.ndarray [shape=(d, n)]\n        input spectrogram. May be real (magnitude) or complex.\n\n    kernel_size : int or tuple (kernel_harmonic, kernel_percussive)\n        kernel size(s) for the median filters.\n\n        - If scalar, the same size is used for both harmonic and percussive.\n        - If tuple, the first value specifies the width of the\n          harmonic filter, and the second value specifies the width\n          of the percussive filter.\n\n    power : float > 0 [scalar]\n        Exponent for the Wiener filter when constructing soft mask matrices.\n\n    mask : bool\n        Return the masking matrices instead of components.\n\n        Masking matrices contain non-negative real values that\n        can be used to measure the assignment of energy from `S`\n        into harmonic or percussive components.\n\n        Components can be recovered by multiplying `S * mask_H`\n        or `S * mask_P`.\n\n\n    margin : float or tuple (margin_harmonic, margin_percussive)\n        margin size(s) for the masks (as described in [2]_)\n\n        - If scalar, the same size is used for both harmonic and percussive.\n        - If tuple, the first value specifies the margin of the\n          harmonic mask, and the second value specifies the margin\n          of the percussive mask.\n\n    Returns\n    -------\n    harmonic : np.ndarray [shape=(d, n)]\n        harmonic component (or mask)\n\n    percussive : np.ndarray [shape=(d, n)]\n        percussive component (or mask)\n\n\n    See Also\n    --------\n    util.softmask\n\n    Notes\n    -----\n    This function caches at level 30.\n\n    Examples\n    --------\n    Separate into harmonic and percussive\n\n    >>> y, sr = librosa.load(librosa.util.example_audio_file(), duration=15)\n    >>> D = librosa.stft(y)\n    >>> H, P = librosa.decompose.hpss(D)\n\n    >>> import matplotlib.pyplot as plt\n    >>> plt.figure()\n    >>> plt.subplot(3, 1, 1)\n    >>> librosa.display.specshow(librosa.amplitude_to_db(D,\n    ...                                                  ref=np.max),\n    ...                          y_axis=\'log\')\n    >>> plt.colorbar(format=\'%+2.0f dB\')\n    >>> plt.title(\'Full power spectrogram\')\n    >>> plt.subplot(3, 1, 2)\n    >>> librosa.display.specshow(librosa.amplitude_to_db(H,\n    ...                                                  ref=np.max),\n    ...                          y_axis=\'log\')\n    >>> plt.colorbar(format=\'%+2.0f dB\')\n    >>> plt.title(\'Harmonic power spectrogram\')\n    >>> plt.subplot(3, 1, 3)\n    >>> librosa.display.specshow(librosa.amplitude_to_db(P,\n    ...                                                  ref=np.max),\n    ...                          y_axis=\'log\')\n    >>> plt.colorbar(format=\'%+2.0f dB\')\n    >>> plt.title(\'Percussive power spectrogram\')\n    >>> plt.tight_layout()\n\n\n    Or with a narrower horizontal filter\n\n    >>> H, P = librosa.decompose.hpss(D, kernel_size=(13, 31))\n\n    Just get harmonic/percussive masks, not the spectra\n\n    >>> mask_H, mask_P = librosa.decompose.hpss(D, mask=True)\n    >>> mask_H\n    array([[  1.000e+00,   1.469e-01, ...,   2.648e-03,   2.164e-03],\n           [  1.000e+00,   2.368e-01, ...,   9.413e-03,   7.703e-03],\n           ...,\n           [  8.869e-01,   5.673e-02, ...,   4.603e-02,   1.247e-05],\n           [  7.068e-01,   2.194e-02, ...,   4.453e-02,   1.205e-05]], dtype=float32)\n    >>> mask_P\n    array([[  2.858e-05,   8.531e-01, ...,   9.974e-01,   9.978e-01],\n           [  1.586e-05,   7.632e-01, ...,   9.906e-01,   9.923e-01],\n           ...,\n           [  1.131e-01,   9.433e-01, ...,   9.540e-01,   1.000e+00],\n           [  2.932e-01,   9.781e-01, ...,   9.555e-01,   1.000e+00]], dtype=float32)\n\n    Separate into harmonic/percussive/residual components by using a margin > 1.0\n\n    >>> H, P = librosa.decompose.hpss(D, margin=3.0)\n    >>> R = D - (H+P)\n    >>> y_harm = librosa.core.istft(H)\n    >>> y_perc = librosa.core.istft(P)\n    >>> y_resi = librosa.core.istft(R)\n\n\n    Get a more isolated percussive component by widening its margin\n\n    >>> H, P = librosa.decompose.hpss(D, margin=(1.0,5.0))\n\n    '
    if np.iscomplexobj(S):
        (S, phase) = core.magphase(S)
    else:
        phase = 1
    if np.isscalar(kernel_size):
        win_harm = kernel_size
        win_perc = kernel_size
    else:
        win_harm = kernel_size[0]
        win_perc = kernel_size[1]
    if np.isscalar(margin):
        margin_harm = margin
        margin_perc = margin
    else:
        margin_harm = margin[0]
        margin_perc = margin[1]
    if ((margin_harm < 1) or (margin_perc < 1)):
        raise ParameterError('Margins must be >= 1.0. A typical range is between 1 and 10.')
    harm = np.empty_like(S)
    harm[:] = median_filter(S, size=(1, win_harm), mode='reflect')
    perc = np.empty_like(S)
    perc[:] = median_filter(S, size=(win_perc, 1), mode='reflect')
    split_zeros = ((margin_harm == 1) and (margin_perc == 1))
    mask_harm = util.softmask(harm, (perc * margin_harm), power=power, split_zeros=split_zeros)
    mask_perc = util.softmask(perc, (harm * margin_perc), power=power, split_zeros=split_zeros)
    if mask:
        return (mask_harm, mask_perc)
    return (((S * mask_harm) * phase), ((S * mask_perc) * phase))
Median-filtering harmonic percussive source separation (HPSS).

If `margin = 1.0`, decomposes an input spectrogram `S = H + P`
where `H` contains the harmonic components,
and `P` contains the percussive components.

If `margin > 1.0`, decomposes an input spectrogram `S = H + P + R`
where `R` contains residual components not included in `H` or `P`.

This implementation is based upon the algorithm described by [1]_ and [2]_.

.. [1] Fitzgerald, Derry.
    "Harmonic/percussive separation using median filtering."
    13th International Conference on Digital Audio Effects (DAFX10),
    Graz, Austria, 2010.

.. [2] Driedger, Müller, Disch.
    "Extending harmonic-percussive separation of audio."
    15th International Society for Music Information Retrieval Conference (ISMIR 2014),
    Taipei, Taiwan, 2014.

Parameters
----------
S : np.ndarray [shape=(d, n)]
    input spectrogram. May be real (magnitude) or complex.

kernel_size : int or tuple (kernel_harmonic, kernel_percussive)
    kernel size(s) for the median filters.

    - If scalar, the same size is used for both harmonic and percussive.
    - If tuple, the first value specifies the width of the
      harmonic filter, and the second value specifies the width
      of the percussive filter.

power : float > 0 [scalar]
    Exponent for the Wiener filter when constructing soft mask matrices.

mask : bool
    Return the masking matrices instead of components.

    Masking matrices contain non-negative real values that
    can be used to measure the assignment of energy from `S`
    into harmonic or percussive components.

    Components can be recovered by multiplying `S * mask_H`
    or `S * mask_P`.


margin : float or tuple (margin_harmonic, margin_percussive)
    margin size(s) for the masks (as described in [2]_)

    - If scalar, the same size is used for both harmonic and percussive.
    - If tuple, the first value specifies the margin of the
      harmonic mask, and the second value specifies the margin
      of the percussive mask.

Returns
-------
harmonic : np.ndarray [shape=(d, n)]
    harmonic component (or mask)

percussive : np.ndarray [shape=(d, n)]
    percussive component (or mask)


See Also
--------
util.softmask

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

Examples
--------
Separate into harmonic and percussive

>>> y, sr = librosa.load(librosa.util.example_audio_file(), duration=15)
>>> D = librosa.stft(y)
>>> H, P = librosa.decompose.hpss(D)

>>> import matplotlib.pyplot as plt
>>> plt.figure()
>>> plt.subplot(3, 1, 1)
>>> librosa.display.specshow(librosa.amplitude_to_db(D,
...                                                  ref=np.max),
...                          y_axis='log')
>>> plt.colorbar(format='%+2.0f dB')
>>> plt.title('Full power spectrogram')
>>> plt.subplot(3, 1, 2)
>>> librosa.display.specshow(librosa.amplitude_to_db(H,
...                                                  ref=np.max),
...                          y_axis='log')
>>> plt.colorbar(format='%+2.0f dB')
>>> plt.title('Harmonic power spectrogram')
>>> plt.subplot(3, 1, 3)
>>> librosa.display.specshow(librosa.amplitude_to_db(P,
...                                                  ref=np.max),
...                          y_axis='log')
>>> plt.colorbar(format='%+2.0f dB')
>>> plt.title('Percussive power spectrogram')
>>> plt.tight_layout()


Or with a narrower horizontal filter

>>> H, P = librosa.decompose.hpss(D, kernel_size=(13, 31))

Just get harmonic/percussive masks, not the spectra

>>> mask_H, mask_P = librosa.decompose.hpss(D, mask=True)
>>> mask_H
array([[  1.000e+00,   1.469e-01, ...,   2.648e-03,   2.164e-03],
       [  1.000e+00,   2.368e-01, ...,   9.413e-03,   7.703e-03],
       ...,
       [  8.869e-01,   5.673e-02, ...,   4.603e-02,   1.247e-05],
       [  7.068e-01,   2.194e-02, ...,   4.453e-02,   1.205e-05]], dtype=float32)
>>> mask_P
array([[  2.858e-05,   8.531e-01, ...,   9.974e-01,   9.978e-01],
       [  1.586e-05,   7.632e-01, ...,   9.906e-01,   9.923e-01],
       ...,
       [  1.131e-01,   9.433e-01, ...,   9.540e-01,   1.000e+00],
       [  2.932e-01,   9.781e-01, ...,   9.555e-01,   1.000e+00]], dtype=float32)

Separate into harmonic/percussive/residual components by using a margin > 1.0

>>> H, P = librosa.decompose.hpss(D, margin=3.0)
>>> R = D - (H+P)
>>> y_harm = librosa.core.istft(H)
>>> y_perc = librosa.core.istft(P)
>>> y_resi = librosa.core.istft(R)


Get a more isolated percussive component by widening its margin

>>> H, P = librosa.decompose.hpss(D, margin=(1.0,5.0))
@cache(level=30)
def hpss(S, kernel_size=31, power=2.0, mask=False, margin=1.0):
    'Median-filtering harmonic percussive source separation (HPSS).\n\n    If `margin = 1.0`, decomposes an input spectrogram `S = H + P`\n    where `H` contains the harmonic components,\n    and `P` contains the percussive components.\n\n    If `margin > 1.0`, decomposes an input spectrogram `S = H + P + R`\n    where `R` contains residual components not included in `H` or `P`.\n\n    This implementation is based upon the algorithm described by [1]_ and [2]_.\n\n    .. [1] Fitzgerald, Derry.\n        "Harmonic/percussive separation using median filtering."\n        13th International Conference on Digital Audio Effects (DAFX10),\n        Graz, Austria, 2010.\n\n    .. [2] Driedger, Müller, Disch.\n        "Extending harmonic-percussive separation of audio."\n        15th International Society for Music Information Retrieval Conference (ISMIR 2014),\n        Taipei, Taiwan, 2014.\n\n    Parameters\n    ----------\n    S : np.ndarray [shape=(d, n)]\n        input spectrogram. May be real (magnitude) or complex.\n\n    kernel_size : int or tuple (kernel_harmonic, kernel_percussive)\n        kernel size(s) for the median filters.\n\n        - If scalar, the same size is used for both harmonic and percussive.\n        - If tuple, the first value specifies the width of the\n          harmonic filter, and the second value specifies the width\n          of the percussive filter.\n\n    power : float > 0 [scalar]\n        Exponent for the Wiener filter when constructing soft mask matrices.\n\n    mask : bool\n        Return the masking matrices instead of components.\n\n        Masking matrices contain non-negative real values that\n        can be used to measure the assignment of energy from `S`\n        into harmonic or percussive components.\n\n        Components can be recovered by multiplying `S * mask_H`\n        or `S * mask_P`.\n\n\n    margin : float or tuple (margin_harmonic, margin_percussive)\n        margin size(s) for the masks (as described in [2]_)\n\n        - If scalar, the same size is used for both harmonic and percussive.\n        - If tuple, the first value specifies the margin of the\n          harmonic mask, and the second value specifies the margin\n          of the percussive mask.\n\n    Returns\n    -------\n    harmonic : np.ndarray [shape=(d, n)]\n        harmonic component (or mask)\n\n    percussive : np.ndarray [shape=(d, n)]\n        percussive component (or mask)\n\n\n    See Also\n    --------\n    util.softmask\n\n    Notes\n    -----\n    This function caches at level 30.\n\n    Examples\n    --------\n    Separate into harmonic and percussive\n\n    >>> y, sr = librosa.load(librosa.util.example_audio_file(), duration=15)\n    >>> D = librosa.stft(y)\n    >>> H, P = librosa.decompose.hpss(D)\n\n    >>> import matplotlib.pyplot as plt\n    >>> plt.figure()\n    >>> plt.subplot(3, 1, 1)\n    >>> librosa.display.specshow(librosa.amplitude_to_db(D,\n    ...                                                  ref=np.max),\n    ...                          y_axis=\'log\')\n    >>> plt.colorbar(format=\'%+2.0f dB\')\n    >>> plt.title(\'Full power spectrogram\')\n    >>> plt.subplot(3, 1, 2)\n    >>> librosa.display.specshow(librosa.amplitude_to_db(H,\n    ...                                                  ref=np.max),\n    ...                          y_axis=\'log\')\n    >>> plt.colorbar(format=\'%+2.0f dB\')\n    >>> plt.title(\'Harmonic power spectrogram\')\n    >>> plt.subplot(3, 1, 3)\n    >>> librosa.display.specshow(librosa.amplitude_to_db(P,\n    ...                                                  ref=np.max),\n    ...                          y_axis=\'log\')\n    >>> plt.colorbar(format=\'%+2.0f dB\')\n    >>> plt.title(\'Percussive power spectrogram\')\n    >>> plt.tight_layout()\n\n\n    Or with a narrower horizontal filter\n\n    >>> H, P = librosa.decompose.hpss(D, kernel_size=(13, 31))\n\n    Just get harmonic/percussive masks, not the spectra\n\n    >>> mask_H, mask_P = librosa.decompose.hpss(D, mask=True)\n    >>> mask_H\n    array([[  1.000e+00,   1.469e-01, ...,   2.648e-03,   2.164e-03],\n           [  1.000e+00,   2.368e-01, ...,   9.413e-03,   7.703e-03],\n           ...,\n           [  8.869e-01,   5.673e-02, ...,   4.603e-02,   1.247e-05],\n           [  7.068e-01,   2.194e-02, ...,   4.453e-02,   1.205e-05]], dtype=float32)\n    >>> mask_P\n    array([[  2.858e-05,   8.531e-01, ...,   9.974e-01,   9.978e-01],\n           [  1.586e-05,   7.632e-01, ...,   9.906e-01,   9.923e-01],\n           ...,\n           [  1.131e-01,   9.433e-01, ...,   9.540e-01,   1.000e+00],\n           [  2.932e-01,   9.781e-01, ...,   9.555e-01,   1.000e+00]], dtype=float32)\n\n    Separate into harmonic/percussive/residual components by using a margin > 1.0\n\n    >>> H, P = librosa.decompose.hpss(D, margin=3.0)\n    >>> R = D - (H+P)\n    >>> y_harm = librosa.core.istft(H)\n    >>> y_perc = librosa.core.istft(P)\n    >>> y_resi = librosa.core.istft(R)\n\n\n    Get a more isolated percussive component by widening its margin\n\n    >>> H, P = librosa.decompose.hpss(D, margin=(1.0,5.0))\n\n    '
    if np.iscomplexobj(S):
        (S, phase) = core.magphase(S)
    else:
        phase = 1
    if np.isscalar(kernel_size):
        win_harm = kernel_size
        win_perc = kernel_size
    else:
        win_harm = kernel_size[0]
        win_perc = kernel_size[1]
    if np.isscalar(margin):
        margin_harm = margin
        margin_perc = margin
    else:
        margin_harm = margin[0]
        margin_perc = margin[1]
    if ((margin_harm < 1) or (margin_perc < 1)):
        raise ParameterError('Margins must be >= 1.0. A typical range is between 1 and 10.')
    harm = np.empty_like(S)
    harm[:] = median_filter(S, size=(1, win_harm), mode='reflect')
    perc = np.empty_like(S)
    perc[:] = median_filter(S, size=(win_perc, 1), mode='reflect')
    split_zeros = ((margin_harm == 1) and (margin_perc == 1))
    mask_harm = util.softmask(harm, (perc * margin_harm), power=power, split_zeros=split_zeros)
    mask_perc = util.softmask(perc, (harm * margin_perc), power=power, split_zeros=split_zeros)
    if mask:
        return (mask_harm, mask_perc)
    return (((S * mask_harm) * phase), ((S * mask_perc) * phase))