ShortTimeFFT#
- class scipy.signal.ShortTimeFFT(win, hop, fs, *, fft_mode='onesided', mfft=None, dual_win=None, scale_to=None, phase_shift=0)[Quelle]#
Bietet eine parametrisierte diskrete Kurzzeit-Fourier-Transformation (stft) und ihre Inverse (istft).
Die stft berechnet sequentielle FFTs, indem ein Fenster (
win) mithop-Inkrementen über ein Eingangssignal gleitet. Sie kann verwendet werden, um die Änderung des Spektrums über die Zeit zu quantifizieren.Die stft wird durch eine komplexwertige Matrix S[q,p] dargestellt, wobei die p-te Spalte eine FFT mit dem um die Zeit t[p] = p *
delta_t= p *hop*Tzentrierte FFT repräsentiert, wobeiTdas Abtastintervall des Eingangssignals ist. Die q-te Zeile repräsentiert die Werte bei der Frequenz f[q] = q *delta_f, wobeidelta_f= 1 / (mfft*T) die Bündelbreite der FFT ist.Die inverse STFT istft wird durch Umkehrung der Schritte der STFT berechnet: Nimm die IFFT des p-ten Slices von S[q,p] und multipliziere das Ergebnis mit dem sogenannten dualen Fenster (siehe
dual_win). Verschiebe das Ergebnis um p *delta_tund addiere das Ergebnis zu den vorherigen verschobenen Ergebnissen, um das Signal zu rekonstruieren. Wenn nur das duale Fenster bekannt ist und die STFT invertierbar ist, kannfrom_dualverwendet werden, um diese Klasse zu instanziieren.Standardmäßig wird das sogenannte kanonische duale Fenster verwendet. Dies ist das Fenster mit der minimalen Energie unter allen möglichen dualen Fenstern.
from_win_equals_dualundclosest_STFT_dual_windowbieten Möglichkeiten, alternative duale Fenster zu nutzen. Beachten Sie, dasswinimmer auch ein duales Fenster vondual_winist.Aufgrund der Konvention, dass die Zeit t = 0 am ersten Sample des Eingangssignals liegt, haben die STFT-Werte typischerweise negative Zeitschlitze. Daher bedeuten negative Indizes wie
p_minoderk_minnicht das Zurückzählen vom Ende eines Arrays wie bei der Standard-Python-Indizierung, sondern das Links-Sein von t = 0.Detailliertere Informationen finden Sie im Abschnitt Short-Time Fourier Transform im SciPy User Guide.
Beachten Sie, dass alle Parameter des Initialisierers, mit Ausnahme von
scale_to(dasscalingverwendet), identisch benannte Attribute haben.- Parameter:
- winnp.ndarray
Das Fenster muss ein reelles oder komplexes 1D-Array sein.
- hopint
Der Schritt in Samples, um den das Fenster bei jedem Schritt verschoben wird.
- fsfloat
Abtastfrequenz des Eingangssignals und des Fensters. Ihre Beziehung zum Abtastintervall
TistT = 1 / fs.- fft_mode‘twosided’, ‘centered’, ‘onesided’, ‘onesided2X’
Modus der zu verwendenden FFT (Standard 'onesided'). Siehe Eigenschaft
fft_modefür Details.- mfft: int | None
Länge der FFT, wenn eine Null-Padding-FFT gewünscht wird. Wenn
None(Standard), wird die Länge des Fensterswinverwendet.- dual_winnp.ndarray | None
Das duale Fenster von
win. Wenn aufNonegesetzt, wird es bei Bedarf berechnet.- scale_to‘magnitude’, ‘psd’ | None
Wenn nicht
None(Standard) wird die Fensterfunktion skaliert, sodass jede STFT-Spalte entweder ein 'magnitude'-Spektrum oder ein Leistungsspektraldichtespektrum ('psd') darstellt. Dieser Parameter setzt die Eigenschaftscalingauf denselben Wert. Siehe die Methodescale_tofür Details.- phase_shiftint | None
Wenn gesetzt, fügt es eine lineare Phase
phase_shift/mfft*fzu jeder Frequenzfhinzu. Der Standardwert von 0 stellt sicher, dass keine Phasenverschiebung auf dem Null-Slice (in dem t=0 zentriert ist) angewendet wird. Siehe die Eigenschaftphase_shiftfür weitere Details.
- Attribute:
TAbtastintervall des Eingangssignals und des Fensters.
delta_fBreite der Frequenzbins der STFT.
delta_tZeitinkrement der STFT.
dual_winDuales Fenster (standardmäßig kanonisches duales Fenster).
fFrequenzwerte der STFT.
f_ptsAnzahl der Punkte entlang der Frequenzachse.
fac_magnitudeFaktor, mit dem die STFT-Werte multipliziert werden, um jedes Frequenz-Slice auf ein Magnitudenspektrum zu skalieren.
fac_psdFaktor, mit dem die STFT-Werte multipliziert werden, um jedes Frequenz-Slice auf eine Leistungsspektraldichte (PSD) zu skalieren.
fft_modeModus der verwendeten FFT ('twosided', 'centered', 'onesided' oder 'onesided2X').
fsAbtastfrequenz des Eingangssignals und des Fensters.
hopZeitinkrement in Signalabtastwerten für das gleitende Fenster.
invertierbarPrüft, ob die STFT invertierbar ist.
k_minDer kleinstmögliche Signalindex der STFT.
unterer_rand_endeErster Signalindex und erster Slice-Index, die von der Vor-Pufferung unberührt bleiben.
m_numAnzahl der Abtastwerte im Fenster
win.m_num_midZentraler Index des Fensters
win.mfftLänge der Eingabe für die verwendete FFT – kann größer sein als die Fensterlänge
m_num.onesided_fftGibt True zurück, wenn eine einseitige FFT verwendet wird.
p_minDer kleinstmögliche Slice-Index.
phase_shiftWenn gesetzt, fügt es eine lineare Phase
phase_shift/mfft*fzu jedem FFT-Slice der Frequenzfhinzu.scalingNormalisierung, die auf die Fensterfunktion angewendet wird ('magnitude', 'psd', 'unitary' oder
None).winFensterfunktion als reell- oder komplexwertiges 1D-Array.
Methoden
extent(n[, axes_seq, center_bins])Gibt die minimalen und maximalen Zeit-Frequenz-Werte zurück.
from_dual(dual_win, hop, fs, *[, fft_mode, ...])Instanziiert eine ShortTimeFFT, indem nur ein duales Fenster bereitgestellt wird.
from_win_equals_dual(desired_win, hop, fs, *)Erstellt eine Instanz, bei der das Fenster und sein Dual bis auf einen Skalierungsfaktor gleich sind.
from_window(win_param, fs, nperseg, noverlap, *)Instanziiert ShortTimeFFT mithilfe von get_window.
istft(S[, k0, k1, f_axis, t_axis])Inverse Kurzzeit-Fourier-Transformation.
k_max(n)Erster Sample-Index nach dem Signalende, der nicht von einem Zeitslice berührt wird.
nearest_k_p(k[, left])Gibt den nächsten Sample-Index k_p zurück, für den t[k_p] == t[p] gilt.
p_max(n)Index des ersten nicht überlappenden oberen Zeit-Slices für eine n-Sample-Eingabe.
p_num(n)Anzahl der Zeit-Slices für ein Eingangssignal mit n Samples.
p_range(n[, p0, p1])Berechnet und validiert den Bereich der Slice-Indizes.
scale_to(scaling)Skaliert das Fenster, um 'magnitude'- oder 'psd'-Skalierung für die STFT zu erhalten.
spectrogram(x[, y, detr, p0, p1, k_offset, ...])Berechnet das Spektrogramm oder Kreuzspektrogramm.
stft(x[, p0, p1, k_offset, padding, axis])Führt die Kurzzeittransformation durch.
stft_detrend(x, detr[, p0, p1, k_offset, ...])Berechnet die Kurzzeit-Fourier-Transformation, wobei zuvor ein Trend von jedem Segment subtrahiert wird.
t(n[, p0, p1, k_offset])Zeiten der STFT für ein Eingangssignal mit n Samples.
Erster Signalindex und erster Slice-Index, die von der Nach-Pufferung betroffen sind.
Hinweise
Eine typische STFT-Anwendung ist die Erstellung verschiedener Arten von Zeit-Frequenz-Plots, die oft unter dem Begriff „Spektrogramm“ zusammengefasst werden. Beachten Sie, dass dieser Begriff auch verwendet wird, um explizit das absolute Quadrat einer STFT zu bezeichnen [11], wie in
spectrogram.Die STFT kann auch zum Filtern und für Filterbänke verwendet werden, wie in [12] erläutert.
Referenzen
[11]Karlheinz Gröchenig: „Foundations of Time-Frequency Analysis“, Birkhäuser Boston 2001, 10.1007/978-1-4612-0003-1
[12]Julius O. Smith III, „Spectral Audio Signal Processing“, Online-Buch, 2011, https://www.dsprelated.com/freebooks/sasp/
Beispiele
Das folgende Beispiel zeigt die Magnitude der STFT eines Sinus mit variabler Frequenz \(f_i(t)\) (im Diagramm durch eine rote gestrichelte Linie markiert)
>>> import numpy as np >>> import matplotlib.pyplot as plt >>> from scipy.signal import ShortTimeFFT >>> from scipy.signal.windows import gaussian ... >>> T_x, N = 1 / 20, 1000 # 20 Hz sampling rate for 50 s signal >>> t_x = np.arange(N) * T_x # time indexes for signal >>> f_i = 1 * np.arctan((t_x - t_x[N // 2]) / 2) + 5 # varying frequency >>> x = np.sin(2*np.pi*np.cumsum(f_i)*T_x) # the signal
Das verwendete Gaußsche Fenster ist 50 Samples oder 2,5 s lang. Der Parameter
mfft=200in ShortTimeFFT bewirkt eine Übersampling des Spektrums um einen Faktor von 4.>>> g_std = 8 # standard deviation for Gaussian window in samples >>> w = gaussian(50, std=g_std, sym=True) # symmetric Gaussian window >>> SFT = ShortTimeFFT(w, hop=10, fs=1/T_x, mfft=200, scale_to='magnitude') >>> Sx = SFT.stft(x) # perform the STFT
Im Diagramm ist die zeitliche Ausdehnung des Signals x durch vertikale gestrichelte Linien markiert. Beachten Sie, dass die SFT Werte außerhalb des Zeitbereichs von x erzeugt. Die schattierten Bereiche links und rechts deuten auf Randeffekte hin, die durch die Fenster-Slices in diesem Bereich verursacht werden, die nicht vollständig innerhalb des Zeitbereichs von x liegen.
>>> fig1, ax1 = plt.subplots(figsize=(6., 4.)) # enlarge plot a bit >>> t_lo, t_hi = SFT.extent(N)[:2] # time range of plot >>> ax1.set_title(rf"STFT ({SFT.m_num*SFT.T:g}$\,s$ Gaussian window, " + ... rf"$\sigma_t={g_std*SFT.T}\,$s)") >>> ax1.set(xlabel=f"Time $t$ in seconds ({SFT.p_num(N)} slices, " + ... rf"$\Delta t = {SFT.delta_t:g}\,$s)", ... ylabel=f"Freq. $f$ in Hz ({SFT.f_pts} bins, " + ... rf"$\Delta f = {SFT.delta_f:g}\,$Hz)", ... xlim=(t_lo, t_hi)) ... >>> im1 = ax1.imshow(abs(Sx), origin='lower', aspect='auto', ... extent=SFT.extent(N), cmap='viridis') >>> ax1.plot(t_x, f_i, 'r--', alpha=.5, label='$f_i(t)$') >>> fig1.colorbar(im1, label="Magnitude $|S_x(t, f)|$") ... >>> # Shade areas where window slices stick out to the side: >>> for t0_, t1_ in [(t_lo, SFT.lower_border_end[0] * SFT.T), ... (SFT.upper_border_begin(N)[0] * SFT.T, t_hi)]: ... ax1.axvspan(t0_, t1_, color='w', linewidth=0, alpha=.2) >>> for t_ in [0, N * SFT.T]: # mark signal borders with vertical line: ... ax1.axvline(t_, color='y', linestyle='--', alpha=0.5) >>> ax1.legend() >>> fig1.tight_layout() >>> plt.show()
Die Rekonstruktion des Signals mit der istft ist unkompliziert, beachten Sie jedoch, dass die Länge von x1 angegeben werden muss, da die STFT-Länge in
hop-Schritten zunimmt.>>> SFT.invertible # check if invertible True >>> x1 = SFT.istft(Sx, k1=N) >>> np.allclose(x, x1) True
Es ist möglich, die STFT von Signalteilen zu berechnen
>>> N2 = SFT.nearest_k_p(N // 2) >>> Sx0 = SFT.stft(x[:N2]) >>> Sx1 = SFT.stft(x[N2:])
Beim Zusammenfügen sequentieller STFT-Teile muss die Überlappung berücksichtigt werden
>>> p0_ub = SFT.upper_border_begin(N2)[1] - SFT.p_min >>> p1_le = SFT.lower_border_end[1] - SFT.p_min >>> Sx01 = np.hstack((Sx0[:, :p0_ub], ... Sx0[:, p0_ub:] + Sx1[:, :p1_le], ... Sx1[:, p1_le:])) >>> np.allclose(Sx01, Sx) # Compare with SFT of complete signal True
Es ist auch möglich, die itsft für Signalteile zu berechnen
>>> y_p = SFT.istft(Sx, N//3, N//2) >>> np.allclose(y_p, x[N//3:N//2]) True