Skip to content

Features | latest | spectral-kurtosis

Spectral kurtosis

Spectral kurtosis is a measure of the "tailedness" or peakedness of the power spectrum around its mean, the spectral centroid fcentroid. It indicates how much of the spectrum's power is concentrated in the tails of the distribution compared to the center:

  • High kurtosis: Indicates a spectrum with heavy tails and a sharp peak (leptokurtic), where spectral energy is concentrated in a few dominant frequencies far from the mean.
  • Low kurtosis: Indicates a flatter spectrum (platykurtic), where spectral energy is more evenly distributed across frequencies.
  • Normal kurtosis: A kurtosis value of 3 corresponds to a normal distribution (mesokurtic).

Spectral kurtosis is computed from the power spectrum Xp=|X|2RM using the following formula:

SpectralKurtosis=m4m22,

where:

  • mk is the k-th central moment of the spectrum:

    mk=m=0M1(f(m)fcentroid)kp(m),
  • f(m) is the frequency corresponding to bin m:

    f(m)=mfs2(M1),
  • p(m) is the normalized power at bin m:

    p(m)=Xp[m]k=0M1Xp[k].

References

Code

INFO

The following snippet is written in a generic and unoptimized manner. The code aims to be comprehensible to programmers familiar with various programming languages and may not represent the most efficient or idiomatic Python practices. Please refer to implementations for optimized implementations in different programming languages.

py
import numpy as np


def _spectral_centroid(spectrum: np.ndarray, samplerate: float):
    ps = np.abs(spectrum) ** 2
    ps_sum = 0.0
    ps_sum_weighted = 0.0
    for i, magnitude in enumerate(ps):
        ps_sum += magnitude
        ps_sum_weighted += magnitude * i
    return 0.5 * samplerate / (len(ps) - 1) * (ps_sum_weighted / ps_sum)


def spectral_kurtosis(spectrum: np.ndarray, samplerate: float):
    f_centroid = _spectral_centroid(spectrum, samplerate)
    ps = np.abs(spectrum) ** 2
    ps_sum = 0.0
    ps_sum_weighted_2 = 0.0
    ps_sum_weighted_4 = 0.0
    for i, magnitude in enumerate(ps):
        f = 0.5 * samplerate / (len(ps) - 1) * i
        ps_sum += magnitude
        ps_sum_weighted_2 += magnitude * (f - f_centroid) ** 2
        ps_sum_weighted_4 += magnitude * (f - f_centroid) ** 4
    return (ps_sum_weighted_4 / ps_sum) / np.sqrt(ps_sum_weighted_2 / ps_sum) ** 4
Run in playground