メインコンテンツ

spectrogram

短時間フーリエ変換を使用したスペクトログラム

説明

信号の "スペクトログラム" は、その短時間フーリエ変換 (STFT) の振幅の二乗です。STFT は、信号の周波数成分が時間とともにどのように変化するかを表します。

s = spectrogram(x) は、信号 x の STFT を返します。s の各列は、x の短時間の、時間が局所化された周波数成分の推定を含みます。

[s,f,t] = spectrogram(x,win,nOverlap,freqSpec) は、信号 x の STFT、周波数 f (ラジアン/サンプル)、およびサンプル インデックス t を返します。このとき、spectrogram 関数は次のように動作します。

  • win を使用して信号をセグメントに分割し、各セグメントにウィンドウを適用する。

  • nOverlap で指定したオーバーラップ長を使用して、隣接するセグメント間でサンプルをオーバーラップさせる。

  • ウィンドウが適用された各セグメントに対し、freqSpec で指定した点の数に基づいて、または指定した周波数において離散フーリエ変換を計算する。

これらの入力引数のいずれかに既定値を使用するには、それらを空 [] として指定します。

[s,f,t] = spectrogram(x,win,nOverlap,freqSpec,Fs) は、サンプル レート Fs を指定し、循環周波数 f (Hz) と時点 t を返します。

[___,ps] = spectrogram(___,freqRange,spectrumType) は、ps に返す周波数範囲とスペクトル タイプも指定します (この出力は x のスペクトログラムに比例します)。ps をパワー スペクトル密度 (PSD) 推定、またはパワー スペクトル推定のいずれかとして返します。これらの入力引数は、どちらか一方、または両方を指定できます。

[___,fc,tc] = spectrogram(___,"reassigned") は、各 PSD 推定またはパワー スペクトル推定を、そのエネルギーの中心の位置に再割り当てします。この構文は、エネルギー中心の周波数 fc および時間 tc も返します。

十分に局所化された時相成分またはスペクトル成分が信号に含まれる場合、"reassigned" 引数は、よりシャープなスペクトログラムを生成します。

[___] = spectrogram(___,"yaxis",Name=Value) は、名前と値の引数を使用して追加オプションを指定します。最小しきい値、出力時間次元、およびスペクトログラムをプロットするターゲットの親コンテナーを指定できます。

ターゲットの親コンテナーを指定した場合、"yaxis" オプションは、周波数を ps のプロットの "y" 軸に、時間を "x" 軸に表示します。

出力引数なしで spectrogram(___) を使用すると、現在の Figure ウィンドウまたは指定したターゲットの親コンテナーに、ps がデシベル単位でプロットされます。

すべて折りたたむ

正弦波の和から構成される信号のサンプルを Nx=1024 個生成します。正弦波の正規化周波数は、2π/5 ラジアン/サンプルおよび 4π/5 ラジアン/サンプルです。高周波数の正弦波の振幅は、他の正弦波の振幅の 10 倍です。

N = 1024;
n = 0:N-1;

w0 = 2*pi/5;
x = sin(w0*n)+10*sin(2*w0*n);

関数の既定の設定を使用して、短時間フーリエ変換を計算します。スペクトログラムをプロットします。

s = spectrogram(x);

spectrogram(x,"yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Samples, ylabel Normalized Frequency ( times pi radians/sample) contains an object of type image.

計算を繰り返します。

  • 長さ nsc=Nx/4.5 のセクションに信号を分割します。

  • ハミング ウィンドウを使用して、セクションにウィンドウを適用します。

  • 隣接するセクション間で 50% のオーバーラップを指定します。

  • FFT を計算するには、max(256,2p) 点を使用します。ここで、p=log2nsc です。

2 つの方法の結果が同じになることを確認します。

Nx = length(x);
nsc = floor(Nx/4.5);
nov = floor(nsc/2);
nff = max(256,2^nextpow2(nsc));

t = spectrogram(x,hamming(nsc),nov,nff);

maxerr = max(abs(abs(t(:))-abs(s(:))))
maxerr = 
0

長さが等しく、セクション間のオーバーラップが 50% である 8 つのセクションに信号を分割します。前のステップと同じ FFT 長を指定します。短時間フーリエ変換を計算し、前の 2 つの手順と結果が同じであることを確認します。

ns = 8;
ov = 0.5;
lsc = floor(Nx/(ns-(ns-1)*ov));

t = spectrogram(x,lsc,floor(ov*lsc),nff);

maxerr = max(abs(abs(t(:))-abs(s(:))))
maxerr = 
0

600 Hz で 2 秒間サンプリングされた複素数値凸 2 次チャープで構成される信号を生成します。チャープの初期周波数は 250 Hz、最終周波数は 50 Hz です。

fs = 6e2;
ts = 0:1/fs:2;
x = chirp(ts,250,ts(end),50,"quadratic",0,"convex","complex");

関数 spectrogram

関数 spectrogram を使用して信号の STFT を計算します。

  • 信号を、それぞれ M=49 サンプルの長さのセグメントに分割します。

  • 隣接するセグメント間に L=11 個のサンプルのオーバーラップを指定します。

  • 最後の短いセグメントを破棄します。

  • 各セグメントにバートレット ウィンドウを適用します。

  • NDFT=1024 点で各セグメントの離散フーリエ変換を評価します。既定では、複素数値信号の場合、spectrogram は両側変換を計算します。

M = 49;
L = 11;
g = bartlett(M);
Ndft = 1024;

[s,f,t] = spectrogram(x,g,L,Ndft,fs);

関数 waterplot を使用して、STFT の振幅の 2 乗として定義されるスペクトログラムを計算し、表示します。

waterplot(s,f,t)

Figure contains an axes object. The axes object with xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch.

STFT の定義

定義を使用して Nx サンプルの信号の STFT を計算します。信号を Nx-LM-L 個のオーバーラップ セグメントに分割します。各セグメントにウィンドウを適用し、それぞれについて、NDFT 点での離散フーリエ変換を評価します。

segs = framesig(1:length(x),M,OverlapLength=L);
X = fft(x(segs).*g,Ndft);

STFT の時間範囲と周波数範囲を計算します。

  • 時間値を求めるには、時間ベクトルをオーバーラップ セグメントに分割します。時間値は、下端でオープンの区間として扱われる各セグメントの中間点です。

  • 周波数値を求めるには、ゼロ周波数でクローズ、下端でオープンとなるナイキスト区間を指定します。

framedT = ts(segs);
tint = mean(framedT(2:end,:));

fint = 0:fs/Ndft:fs-fs/Ndft;

spectrogram の出力を定義と比較します。スペクトログラムを表示します。

maxdiff = max(max(abs(s-X)))
maxdiff = 
0
waterplot(X,fint,tint)

Figure contains an axes object. The axes object with xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch.

function waterplot(s,f,t)
% Waterfall plot of spectrogram
    waterfall(f,t,abs(s)'.^2)
    set(gca,XDir="reverse",View=[30 50])
    xlabel("Frequency (Hz)")
    ylabel("Time (s)")
end

1.4 kHz で 2 秒間サンプリングされたチャープで構成される信号を生成します。チャープの周波数は、測定時間中に 600 Hz から 100 Hz に線形的に減少します。

fs = 1400;
x = chirp(0:1/fs:2,600,2,100);

stft 既定

関数 spectrogramstft を使用して信号の STFT を計算します。関数 stft の既定の値を使用します。

  • 信号を 128 サンプルのセグメントに分割し、各セグメントに周期的ハン ウィンドウを適用します。

  • 隣接するセグメント間に 96 個のサンプルのオーバーラップを指定します。この長さはウィンドウの長さの 75% と等価です。

  • 128 の DFT 点を指定し、STFT の中央を周波数ゼロに揃え、周波数は Hz 単位で表します。

2 つの結果が等価であることを確認します。

M = 128;
g = hann(M,"periodic");
L = 0.75*M;
Ndft = 128;

[sp,fp,tp] = spectrogram(x,g,L,Ndft,fs,"centered");

[s,f,t] = stft(x,fs);

dff = max(max(abs(sp-s)))
dff = 
0

関数 mesh を使用して、2 つの出力をプロットします。

nexttile
mesh(tp,fp,abs(sp).^2)
title("spectrogram")
view(2), axis tight

nexttile
mesh(t,f,abs(s).^2)
title("stft")
view(2), axis tight

Figure contains 2 axes objects. Axes object 1 with title spectrogram contains an object of type surface. Axes object 2 with title stft contains an object of type surface.

spectrogram 既定

関数 spectrogram の既定の値を使用して計算を繰り返します。

  • 信号を M=Nx/4.5 の長さのセグメントに分割します。ここで、Nx は信号の長さです。各セグメントにハミング ウィンドウを適用します。

  • セグメント間で 50% のオーバーラップを指定します。

  • FFT を計算するには、max(256,2log2M) 点を使用します。正の正規化周波数のみ、スペクトログラムを計算します。

M = floor(length(x)/4.5);
g = hamming(M);
L = floor(M/2);
Ndft = max(256,2^nextpow2(M));

[sx,fx,tx] = spectrogram(x);

[st,ft,tt] = stft(x,Window=g,OverlapLength=L, ...
    FFTLength=Ndft,FrequencyRange="onesided");

dff = max(max(sx-st))
dff = 
0

関数 waterplot を使用して、2 つの出力をプロットします。どちらの場合も、周波数軸を π で除算します。stft 出力の場合、サンプル数を有効なサンプル レート 2π で除算します。

figure
nexttile
waterplot(sx,fx/pi,tx)
title("spectrogram")

nexttile
waterplot(st,ft/pi,tt/(2*pi))
title("stft")

Figure contains 2 axes objects. Axes object 1 with title spectrogram, xlabel Frequency/\pi, ylabel Samples contains an object of type patch. Axes object 2 with title stft, xlabel Frequency/\pi, ylabel Samples contains an object of type patch.

function waterplot(s,f,t)
% Waterfall plot of spectrogram
    waterfall(f,t,abs(s)'.^2)
    set(gca,XDir="reverse",View=[30 50])
    xlabel("Frequency/\pi")
    ylabel("Samples")
end

関数 spectrogram を使用して信号の瞬時周波数を測定し、追跡します。

1 kHz で 2 秒間サンプリングされた 2 次チャープを生成します。初期周波数が 100 Hz で、1 秒後には 200 Hz に増加するようにチャープを指定します。

fs = 1000;
t = 0:1/fs:2-1/fs;
y = chirp(t,100,1,200,"quadratic");

関数 spectrogram に実装された短時間フーリエ変換を使用して、チャープのスペクトルを推定します。信号にハミング ウィンドウを適用し、長さ 100 のセクションに分割します。隣り合ったセクション間のオーバーラップのサンプル 80 個を指定し、周波数 100/2+1=51 におけるスペクトルを評価します。

spectrogram(y,100,80,100,fs,"yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (Hz) contains an object of type image.

(2000-80)/(100-80)=96 の時間点にわたる最大エネルギーをもつ時間-周波数リッジを検出することにより、チャープの周波数を追跡します。スペクトログラム プロットに瞬時周波数を重ね合わせます。

[~,f,t,p] = spectrogram(y,100,80,100,fs);

[fridge,~,lr] = tfridge(p,f);

hold on
plot3(t,fridge,abs(p(lr)),LineWidth=2)
hold off

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (Hz) contains 2 objects of type image, line.

正弦関数的に変化する周波数成分をもつチャープのサンプルを 512 個生成します。

N = 512;
n = 0:N-1;

x = exp(1j*pi*sin(8*n/N)*32);

チャープの中央揃えの短時間フーリエ変換を計算します。信号を 16 サンプルがオーバーラップする 32 サンプルのセグメントに分割します。64 個の DFT ポイントを指定します。スペクトログラムをプロットします。

[scalar,fs,ts] = spectrogram(x,32,16,64,"centered");

spectrogram(x,32,16,64,"centered","yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Samples, ylabel Normalized Frequency ( times pi radians/sample) contains an object of type image.

区間 (-π,π] に対して 64 等間隔周波数のスペクトログラムを計算すると、同じ結果が得られます。'centered' オプションは必要ありません。

fintv = -pi+pi/32:pi/32:pi;

[vector,fv,tv] = spectrogram(x,32,16,fintv);

spectrogram(x,32,16,fintv,"yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Samples, ylabel Normalized Frequency ( times pi radians/sample) contains an object of type image.

電圧制御発振器と 3 つのガウス原子で構成される信号を生成します。信号は fs=2 kHz で 2 秒間サンプリングされます。

fs = 2000;
tx = 0:1/fs:2;
gaussFun = @(A,x,mu,f) exp(-(x-mu).^2/(2*0.03^2)).*sin(2*pi*f.*x)*A';
s = gaussFun([1 1 1],tx',[0.1 0.65 1],[2 6 2]*100)*1.5;
x = vco(chirp(tx+.1,0,tx(end),3).*exp(-2*(tx-1).^2),[0.1 0.4]*fs,fs);
x = s+x';

短時間フーリエ変換

関数 pspectrum を使用して STFT を計算します。

  • Nx サンプル信号を、80/2000=40 ミリ秒の時間分解能に対応する長さ M=80 のサンプルのセグメントに分割します。

  • L=16 個のサンプル、または隣接するセグメント間の 20% のオーバーラップを指定します。

  • カイザー ウィンドウを使用して各セグメントにウィンドウを適用し、漏れには =0.7 を指定します。

M = 80;
L = 16;
lk = 0.7;

[S,F,T] = pspectrum(x,fs,"spectrogram", ...
    TimeResolution=M/fs,OverlapPercent=L/M*100, ...
    Leakage=lk);

関数 spectrogram で得られた結果と比較します。

  • ウィンドウの長さとオーバーラップをサンプル単位で直接指定します。

  • pspectrum は常にカイザー ウィンドウを g(n) として使用します。漏れ とウィンドウの形状係数 β は、β=40×(1-) の関係にあります。

  • pspectrum は、離散フーリエ変換の計算で常に NDFT=1024 個の点を使用します。両側または中央揃えの周波数範囲の変換を計算したい場合にこの数値を指定することができます。一方、実信号の既定値である片側変換の場合、spectrogram1024/2+1=513 個の点を使用します。あるいは、この例にあるように、変換を計算したい周波数のベクトルを指定することができます。

  • 信号を k=Nx-LM-L 個のセグメントに厳密に分割できない場合、spectrogram は信号を切り捨て、pspectrum は信号をゼロでパディングして追加のセグメントを作成します。出力を等価にするには、最後のセグメントと時間ベクトルの最後の要素を削除します。

  • spectrogram は、振幅の 2 乗をスペクトログラムとする STFT を返します。pspectrum は、あらかじめ係数 ng(n) で除算してから 2 乗した各セグメントのパワー スペクトルを返します。

  • 片側変換の場合、pspectrum はスペクトログラムに追加の係数 2 を追加します。

g = kaiser(M,40*(1-lk));

k = (length(x)-L)/(M-L);
if k~=floor(k)
    S = S(:,1:floor(k));
    T = T(1:floor(k));
end

[s,f,t] = spectrogram(x/sum(g)*sqrt(2),g,L,F,fs);

関数 waterplot を使用して、これら 2 つの関数によって計算されたスペクトログラムを表示します。

subplot(2,1,1)
waterplot(sqrt(S),F,T)
title("pspectrum")

subplot(2,1,2)
waterplot(s,f,t)
title("spectrogram")

Figure contains 2 axes objects. Axes object 1 with title pspectrum, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch. Axes object 2 with title spectrogram, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch.

maxd = max(max(abs(abs(s).^2-S)))
maxd = 
2.4419e-08

パワー スペクトルと簡易プロット

関数 spectrogram は、各セグメントのパワー スペクトルまたはパワー スペクトル密度に対応する 4 番目の引数をもちます。pspectrum の出力と同様、ps 引数はあらかじめ 2 乗されており、正規化係数 ng(n) を含みます。実信号の片側スペクトログラムの場合も、追加の係数 2 を含める必要があります。関数のスケーリング引数を "power" に設定します。

[~,~,~,ps] = spectrogram(x*sqrt(2),g,L,F,fs,"power");

max(abs(S(:)-ps(:)))
ans = 
2.4419e-08

pspectrumspectrogram は、出力引数なしで呼び出された場合に、信号のスペクトログラムをデシベル単位でプロットします。片側スペクトログラムの場合は係数 2 を含めます。両方のプロットで同じになるようにカラーマップを設定します。x の範囲を同じ値に設定して、pspectrum プロットの最後にある追加のセグメントが表示されるようにします。spectrogram プロットの y 軸に周波数を表示します。

subplot(2,1,1)
pspectrum(x,fs,"spectrogram", ...
    TimeResolution=M/fs,OverlapPercent=L/M*100, ...
    Leakage=lk)
title("pspectrum")
cc = clim;
xl = xlim;

subplot(2,1,2)
spectrogram(x*sqrt(2),g,L,F,fs,"power","yaxis")
title("spectrogram")
clim(cc)
xlim(xl)

Figure contains 2 axes objects. Axes object 1 with title pspectrum, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image. Axes object 2 with title spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

function waterplot(s,f,t)
% Waterfall plot of spectrogram
    waterfall(f,t,abs(s)'.^2)
    set(gca,XDir="reverse",View=[30 50])
    xlabel("Frequency (Hz)")
    ylabel("Time (s)")
end

1 kHz で 2 秒間サンプリングされたチャープ信号を生成します。初期周波数が 100 Hz で、1 秒後には 200 Hz に増加するようにチャープを指定します。

fs = 1000;
t = 0:1/fs:2;
y = chirp(t,100,1,200,"quadratic");

再割り当てされた信号のスペクトログラムを推定します。

  • 信号に形状パラメーター β=18 のカイザー ウィンドウを適用し、長さ 128 のセクションに分割します。

  • 隣り合ったセクション間のオーバーラップのサンプルを 120 個に指定します。

  • 128/2=65 周波数および (length(x)-120)/(128-120)=235 時間ビンでスペクトルを評価します。

出力引数なしで関数 spectrogram を使用して、再割り当てされたスペクトログラムをプロットします。y 軸に周波数、x 軸に時間を表示します。

spectrogram(y,kaiser(128,18),120,128,fs,"reassigned","yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (Hz) contains an object of type image.

関数 imagesc を使用してプロットをやり直します。周波数値が下から上に増加するように、y 軸の方向を指定します。デシベル変換時に負の無限大となることを避けるため、再割り当てされたスペクトログラムに eps を追加します。

[~,fr,tr,pxx] = spectrogram(y,kaiser(128,18),120,128,fs,"reassigned");

imagesc(tr,fr,pow2db(pxx+eps))
axis xy
xlabel("Time (s)")
ylabel("Frequency (Hz)")
colorbar

Figure contains an axes object. The axes object with xlabel Time (s), ylabel Frequency (Hz) contains an object of type image.

1 kHz で 2 秒間サンプリングされたチャープ信号を生成します。初期周波数が 100 Hz で、1 秒後には 200 Hz に増加するようにチャープを指定します。

Fs = 1000;
t = 0:1/Fs:2;
y = chirp(t,100,1,200,"quadratic");

信号の時間依存のパワー スペクトル密度 (PSD) を推定します。

  • 信号に形状パラメーター β=18 のカイザー ウィンドウを適用し、長さ 128 のセクションに分割します。

  • 隣り合ったセクション間のオーバーラップのサンプルを 120 個に指定します。

  • 128/2=65 周波数および (length(x)-120)/(128-120)=235 時間ビンでスペクトルを評価します。

各 PSD 推定の重心の周波数および時間を出力します。-30 dB より小さい PSD の要素をゼロに設定します。

[~,~,~,pxx,fc,tc] = spectrogram(y,kaiser(128,18),120,128,Fs, ...
    MinThreshold=-30);

重心の周波数および時間の関数として非ゼロの要素をプロットします。

plot(tc(pxx>0),fc(pxx>0),".")

Figure contains an axes object. The axes contains a line object which displays its values using only markers.

2 kHz で 2 秒間サンプリングされた実数値のチャープで構成される信号を生成します。

fs = 2000;
tx = 0:1/fs:2;
x = vco(-chirp(tx,0,tx(end),2).*exp(-3*(tx-1).^2), ...
    [0.1 0.4]*fs,fs).*hann(length(tx))';

両側スペクトログラム

信号の両側 STFT を計算してプロットします。

  • 信号を、それぞれ M=73 サンプルの長さのセグメントに分割します。

  • 隣接するセグメント間に L=24 個のサンプルのオーバーラップを指定します。

  • 最後の短いセグメントを破棄します。

  • 各セグメントにフラットトップ ウィンドウを適用します。

  • NDFT=895 点で各セグメントの離散フーリエ変換を評価します。このとき、点の数が奇数であることに注意します。

M = 73;
L = 24;
g = flattopwin(M);
Ndft = 895;
neven = ~mod(Ndft,2);

[stwo,f,t] = spectrogram(x,g,L,Ndft,fs,"twosided");

出力引数なしで関数 spectrogram を使用し、両側スペクトログラムをプロットします。

spectrogram(x,g,L,Ndft,fs,"twosided","power","yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

定義を使用して両側スペクトログラムを計算します。隣接するセグメント間で L サンプルがオーバーラップする M サンプルのセグメントに信号を分割します。各セグメントにウィンドウを適用し、それぞれについて、NDFT 点での離散フーリエ変換を計算します。

y = framesig(x,M,Window=g,OverlapLength=L);
Xtwo = fft(y,Ndft);

時間範囲と周波数範囲を計算します。

  • 時間値を求めるには、時間ベクトルをオーバーラップ セグメントに分割します。時間値は、下端でオープンの区間として扱われる各セグメントの中間点です。

  • 周波数値を求めるには、ゼロ周波数でクローズ、上端でオープンとなるナイキスト区間を指定します。

framedT = framesig(tx,M,OverlapLength=L);
ttwo = mean(framedT(2:end,:));

ftwo = 0:fs/Ndft:fs*(1-1/Ndft);

spectrogram の出力を定義と比較します。関数 waterplot を使用して、スペクトログラムを表示します。

diffs = [max(max(abs(stwo-Xtwo)));
    max(abs(f-ftwo'));
    max(abs(t-ttwo))]
diffs = 3×1
10-12 ×

         0
    0.2274
    0.0002

figure
nexttile
waterplot(Xtwo,ftwo,ttwo)
title("Two-Sided, Definition")

nexttile
waterplot(stwo,f,t)
title("Two-Sided, spectrogram Function")

Figure contains 2 axes objects. Axes object 1 with title Two-Sided, Definition, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch. Axes object 2 with title Two-Sided, spectrogram Function, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch.

中央揃えのスペクトログラム

信号の中央揃えのスペクトログラムを計算します。

  • 両側 STFT で使用したのと同じ時間値を使用します。

  • 関数 fftshift を使用して、STFT のゼロ周波数成分をスペクトルの中央にシフトします。

  • NDFT が奇数の場合、周波数範囲は両端でオープンとなります。NDFT が偶数の場合、周波数範囲は下端でオープン、上端でクローズとなります。

出力を比較してスペクトログラムを表示します。

tcen = ttwo;

if ~neven
    Xcen = fftshift(Xtwo,1);
    fcen = -fs/2*(1-1/Ndft):fs/Ndft:fs/2;
else
    Xcen = fftshift(circshift(Xtwo,-1),1);
    fcen = (-fs/2*(1-1/Ndft):fs/Ndft:fs/2)+fs/Ndft/2;
end

[scen,f,t] = spectrogram(x,g,L,Ndft,fs,"centered");

diffs = [max(max(abs(scen-Xcen)));
    max(abs(f-fcen'));
    max(abs(t-tcen))]
diffs = 3×1
10-12 ×

         0
    0.2274
    0.0002

figure
nexttile
waterplot(Xcen,fcen,tcen)
title("Centered, Definition")

nexttile
waterplot(scen,f,t)
title("Centered, spectrogram Function")

Figure contains 2 axes objects. Axes object 1 with title Centered, Definition, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch. Axes object 2 with title Centered, spectrogram Function, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch.

片側スペクトログラム

信号の片側スペクトログラムを計算します。

  • 両側 STFT で使用したのと同じ時間値を使用します。

  • NDFT が奇数の場合、片側 STFT は両側 STFT の最初の (NDFT+1)/2 行により構成されます。NDFT が偶数の場合、片側 STFT は両側 STFT の最初の NDFT/2+1 行により構成されます。

  • NDFT が奇数の場合、周波数範囲はゼロ周波数でクローズ、ナイキスト周波数でオープンとなります。NDFT が偶数の場合、周波数範囲は両端でクローズとなります。

出力を比較してスペクトログラムを表示します。実数値信号の場合、"onesided" 引数はオプションです。

tone = ttwo;

if ~neven
    Xone = Xtwo(1:(Ndft+1)/2,:);
else
    Xone = Xtwo(1:Ndft/2+1,:);
end

fone = 0:fs/Ndft:fs/2;

[sone,f,t] = spectrogram(x,g,L,Ndft,fs);

diffs = [max(max(abs(sone-Xone)));
    max(abs(f-fone'));
    max(abs(t-tone))]
diffs = 3×1
10-12 ×

         0
    0.1137
    0.0002

figure
nexttile
waterplot(Xone,fone,tone)
title("One-Sided, Definition")

nexttile
waterplot(sone,f,t)
title("One-Sided, spectrogram Function")

Figure contains 2 axes objects. Axes object 1 with title One-Sided, Definition, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch. Axes object 2 with title One-Sided, spectrogram Function, xlabel Frequency (Hz), ylabel Time (s) contains an object of type patch.

function waterplot(s,f,t)
% Waterfall plot of spectrogram
waterfall(f,t,abs(s)'.^2)
set(gca,XDir="reverse",View=[30 50])
xlabel("Frequency (Hz)")
ylabel("Time (s)")
end

関数 spectrogram は、4 番目の出力引数として、各セグメントのパワー スペクトル密度 (PSD) またはパワー スペクトルのいずれかを含む行列をもちます。パワー スペクトルは、PSD にウィンドウの等価ノイズ帯域幅 (ENBW) を乗算した値と等価です。

1 kHz で 1 秒間サンプリングされた対数チャープで構成される信号を生成します。チャープの初期周波数は 400 Hz で、測定の最後には 10 Hz に減少します。

fs = 1000;
tt = 0:1/fs:1-1/fs;
y = chirp(tt,400,tt(end),10,"logarithmic");

サンプル レートによる PSD とパワー スペクトルのセグメント化

信号を 102 サンプルのセグメントに分割し、各セグメントにハン ウィンドウを適用します。隣り合ったセグメント間のオーバーラップを 12 サンプル、DFT 点を 1024 に指定します。

M = 102;
g = hann(M);
L = 12;
Ndft = 1024;

既定の PSD スペクトル タイプで信号のスペクトログラムを計算します。STFT、およびセグメントのパワー スペクトル密度の配列を出力します。

[s,f,t,p] = spectrogram(y,g,L,Ndft,fs);

スペクトル タイプを "power" に指定して計算を繰り返します。STFT、およびセグメントのパワー スペクトルの配列を出力します。

[r,~,~,q] = spectrogram(y,g,L,Ndft,fs,"power");

どちらの場合もスペクトログラムが同じになることを確認します。周波数に対数スケールを使用して、スペクトログラムをプロットします。

max(max(abs(s).^2-abs(r).^2))
ans = 
0
waterfall(f,t,abs(s)'.^2)
set(gca,XScale="log",...
    XDir="reverse",View=[30 50])

Figure contains an axes object. The axes object contains an object of type patch.

パワー スペクトルが、パワー スペクトル密度にウィンドウの ENBW を乗算した値と等価であることを確認します。

max(max(abs(q-p*enbw(g,fs))))
ans = 
1.6653e-16

セグメントのパワー スペクトルの行列が、スペクトログラムに比例していることを確認します。比例係数は、ウィンドウ要素の和の 2 乗です。

max(max(abs(s).^2-q*sum(g)^2))
ans = 
1.3235e-23

正規化周波数による PSD とパワー スペクトルのセグメント化

計算を繰り返しますが、今度は正規化周波数で計算します。サンプル レートを 2π として指定した場合、結果は同じになります。

[~,~,~,pn] = spectrogram(y,g,L,Ndft);
[~,~,~,qn] = spectrogram(y,g,L,Ndft,"power");

max(max(abs(qn-pn*enbw(g,2*pi))))
ans = 
1.1102e-16

減少する 2 つのチャープと広帯域のスプラッター音を含むオーディオ信号を読み込みます。短時間フーリエ変換を計算します。波形を 300 サンプルがオーバーラップする 400 サンプルのセグメントに分割します。スペクトログラムをプロットします。

load splat

% To hear, type soundsc(y,Fs)

sg = 400;
ov = 300;

spectrogram(y,sg,ov,[],Fs,"yaxis")
colormap bone

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

関数 spectrogram を使用し、信号のパワー スペクトル密度 (PSD) を出力します。

[s,f,t,p] = spectrogram(y,sg,ov,[],Fs);

関数 medfreq を使用して 2 つのチャープを追跡します。より強い低周波のチャープを検出するには、探索を 100 Hz より高い周波数と広帯域音が始まる前の時間に制限します。

f1 = f > 100;
t1 = t < 0.75;

m1 = medfreq(p(f1,t1),f(f1));

微弱な高周波のチャープを検出するには、探索を 2500 Hz より高い周波数と 0.3 秒 ~ 0.65 秒の時間に制限します。

f2 = f > 2500;
t2 = t > 0.3 & t < 0.65;

m2 = medfreq(p(f2,t2),f(f2));

結果をスペクトログラムに重ね合わせます。kHz の単位で表すために周波数の値を 1000 で除算します。

hold on
plot(t(t1),m1/1000,LineWidth=4)
plot(t(t2),m2/1000,LineWidth=4)
hold off

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains 3 objects of type image, line.

10 kHz でサンプリングされた 2 秒間の信号を生成します。信号の瞬時周波数を時間の三角形関数として指定します。

fs = 10e3;
t = 0:1/fs:2;
x1 = vco(sawtooth(2*pi*t,0.5),[0.1 0.4]*fs,fs);

信号のスペクトログラムを計算してプロットします。長さ 256 で形状パラメーター β=5 のカイザー ウィンドウを使用します。セクション間のオーバーラップのサンプル 220 個と DFT 点 512 個を指定します。周波数を y 軸にプロットします。既定のカラーマップとビューを使用します。

spectrogram(x1,kaiser(256,5),220,512,fs,"yaxis")

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

スペクトログラムをウォーターフォール プロットとして表示するようにビューを変更します。カラーマップを bone に設定します。

view(-45,65)
colormap bone

Figure contains an axes object. The axes object with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type surface.

R2025a 以降

指定したターゲット座標軸とパネル コンテナーに 4 つの信号のスペクトログラムをプロットします。

4 つの振動信号 (サンプル レート 10 kHz、3 秒間) を作成します。

Fs = 10e3;
t = 0:1/Fs:3;
x1 = vco(sawtooth(2*pi*t,0.5),[0.1 0.4]*Fs,Fs);
x2 = vco(sin(2*pi*t).*exp(-t),[0.1 0.4]*Fs,Fs) ...
    + 0.01*sin(2*pi*0.25*Fs*t);
x3 = exp(1j*pi*sin(4*t)*Fs/10);
x4 = chirp(t,Fs/10,t(end),Fs/2.5,"quadratic");

ターゲット座標軸へのスペクトログラムのプロット

新しい Figure ウィンドウの南西隅と北東隅に 2 つの座標軸を作成します。

fig = figure;
ax1 = axes(fig,Position=[0.09 0.1 0.52 0.45]);
ax2 = axes(fig,Position=[0.55 0.7 0.42 0.25]);

信号 x1x2 のパワー スペクトルを Figure の南西軸と北東軸にそれぞれプロットします。周波数を y 軸に表示します。512 個の DFT 点、256 サンプルのカイザー ウィンドウ、および 220 サンプルのオーバーラップ長を使用します。

g = kaiser(256,5);
ol = 220;
nfft = 512;

spectrogram(x1,g,ol,nfft,Fs,"power","yaxis",Parent=ax1);
spectrogram(x2,g,ol,nfft,Fs,"power","yaxis",Parent=ax2);

Figure contains 2 axes objects. Axes object 1 with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image. Axes object 2 with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

ターゲット UI 座標軸へのスペクトログラムのプロット

新しい UI Figure ウィンドウの北西隅に座標軸を作成します。

uif = uifigure(Position=[100 100 720 540]);
ax3 = uiaxes(uif,Position=[5 305 300 200]);

信号 x3 の PSD 推定を Figure の座標軸にプロットします。周波数を "y" 軸に表示し、0 kHz を中心とします。

spectrogram(x3,g,ol,nfft,Fs,"centered","yaxis",Parent=ax3);
title(ax3,"Spectrogram in UI Axes")

Figure contains an axes object. The axes object with title Spectrogram in UI Axes, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

ターゲット パネル コンテナーへのスペクトログラムのプロット

UI Figure ウィンドウの南東隅にパネル コンテナーを追加します。

p = uipanel(uif,Position=[300 5 400 325], ...
    Title="Spectrogram in UI Panel", ...
    BackgroundColor="white");

信号 x4 の PSD 推定をパネル コンテナーにプロットします。周波数を y 軸に表示します。

spectrogram(x4,g,ol,nfft,Fs,"yaxis",Parent=p);

Figure contains 2 axes objects and another object of type uipanel. Axes object 1 with title Spectrogram, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image. Axes object 2 with title Spectrogram in UI Axes, xlabel Time (s), ylabel Frequency (kHz) contains an object of type image.

入力引数

すべて折りたたむ

入力信号。ベクトルで指定します。

例: x = chirp(0:0.001:1,0,0.5,100,"quadratic") は、2 次スイープ周波数信号を指定します。

データ型: single | double
複素数のサポート: あり

ウィンドウ。空 ([])、正の整数、またはベクトルとして指定します。

spectrogram 関数は、入力信号 x をセグメントに分割し、ウィンドウを使用して、各セグメントのサンプルとウィンドウの値の積を要素ごとに計算します。ウィンドウの値は、この引数の指定方法に応じて決まります。

  • 空 ([]) — spectrogram は、xnOverlap 個のオーバーラップ サンプルをもつ 8 個のセグメントに分割される長さのハミング ウィンドウを使用します。

  • 正の整数 — spectrogram は、x を長さ win のセグメントに分割し、その長さのハミング ウィンドウを使用します。

  • ベクトル — spectrogram は、x をベクトル win と同じ長さのセグメントに分割し、win で指定したウィンドウを使用します。

x の長さが nOverlap 個のオーバーラップ サンプルをもつ整数個のセグメントに厳密に分割できない場合、spectrogramx をそれに応じて切り捨てます。

利用可能なウィンドウのリストについては、ウィンドウを参照してください。

例: hann(N+1)(1-cos(2*pi*(0:N)'/N))/2 は、いずれも長さ N + 1 のハン ウィンドウを指定します。

オーバーラップするサンプルの数。空 ([]) または非負の整数として指定します。

  • 空 ([]) — spectrogram は、セグメント間で 50% のオーバーラップが発生する数を使用します。

    セグメントの長さを指定していない場合、関数により nOverlapNx / 4.5⌋ に設定されます。ここで、Nx は入力信号の長さで、⌊ ⌋ 記号は床関数を表します。このアクションは、50% のオーバーラップで 8 にできるだけ近い (ただし 8 を超えない) 数のセグメントを取得するために、信号を可能な限り長いセグメントに分割することと等価です。

  • 非負の整数 — spectrogram は、この引数で指定したサンプル数を使用して、隣接するセグメントをオーバーラップさせます。

    • win がスカラーの場合、nOverlapwin より小さくなければなりません。

    • win がベクトルの場合、nOverlapwin の長さより小さくなければなりません。

周波数仕様。次のいずれかの値として指定します。

  • 空 ([]) — spectrogram は、256 と、ウィンドウ長以上となる次の 2 のべき乗のうち、いずれか大きい方に等しい DFT 点の数を使用して、スペクトル推定を計算します。

  • 正の整数 — spectrogram は、この引数で指定した DFT 点の数を使用してスペクトル推定を計算します。

  • 2 要素以上のベクトル — spectrogram は、freqSpec で指定した周波数でスペクトル推定を計算します。

    • サンプル レート Fs を指定した場合、spectrogram は、freqSpecFs と同じ単位の循環周波数とみなします。

    • Fs を指定しない場合、spectrogram は、freqSpec をラジアン/サンプル単位の正規化周波数とみなします。

例: freqSpec = 512 は、512 個の DFT 点を指定します。

例: freqSpec = pi./[8 4 2] は、3 つの正規化周波数から成るベクトルを指定します。

データ型: single | double

サンプル レート。正のスカラーで指定します。サンプル レートは単位時間あたりのサンプル数です。時間の単位が秒の場合、サンプル レートの単位は Hz です。

  • Fs を空配列 [] として指定すると、spectrogram は入力信号 x のサンプル レートを 1 Hz と仮定します。

  • Fs を指定しない場合、spectrogram は入力信号 x のサンプル レートを 2π ラジアン/サンプルと仮定します。

PSD 推定またはパワー スペクトルの周波数範囲。"onesided""twosided"、または "centered" として指定します。

spectrogram 関数は、freqRange で指定された値、DFT 点の数 freqSpec が偶数か奇数か、および Fs が指定されているかどうかに応じて、行数と周波数範囲が異なる ps を返します。

freqRangefreqSpecps の行数

ps の周波数範囲

Fs の指定なし

Fs の指定あり

"onesided"
(x が実数値の場合、既定)
偶数freqSpec/2 + 1[0,π] ラジアン/サンプル[0,Fs/2] サイクル/単位時間
奇数(freqSpec + 1)/2[0,π) ラジアン/サンプル[0,Fs/2) サイクル/単位時間
"twosided"
(x が複素数値の場合、既定)
偶数または奇数freqSpec[0,2π) ラジアン/サンプル[0,Fs) サイクル/単位時間
"centered"偶数freqSpec(–π,π] ラジアン/サンプル(–Fs/2,Fs/2] サイクル/単位時間
奇数(–π,π) ラジアン/サンプル(–Fs/2,Fs/2) サイクル/単位時間

メモ

  • freqSpec を循環周波数または正規化周波数のベクトルとして指定した場合、この引数はサポートされません。

  • x が複素数値の場合、"onesided" 値はサポートされません。

データ型: char | string

パワー スペクトルのスケーリング。次のいずれかの値として指定します。

  • "psd"spectrogram は、パワー スペクトル密度を返します。

  • "power"spectrogram は、ウィンドウの等価ノイズ帯域幅ごとに PSD の推定をスケーリングし、各周波数におけるパワーの推定を返します。"reassigned" も指定した場合、spectrogram 関数は、再割り当ての前に PSD を各周波数ビンの幅で積分します。

次の表は、入力信号 x、ウィンドウ ベクトル win、オーバーラップ長 nOverlap、周波数仕様 freqSpec、およびサンプル レート Fs を指定した場合に、ps に返される PSD 推定とパワー スペクトル推定のスケーリング関係を示しています。

サンプル レートスケーリング関係
Fs の指定あり

[~,~,~,psd] = spectrogram(x,win,nOverlap,freqSpec,Fs,"psd");
[~,~,~,pow] = spectrogram(x,win,nOverlap,freqSpec,Fs,"power");
このとき、powpsd*enbw(win,Fs) と等価です。

Fs の指定なし

[~,~,~,psd] = spectrogram(x,win,nOverlap,freqSpec,"psd");
[~,~,~,pow] = spectrogram(x,win,nOverlap,freqSpec,"power");
このとき、powpsd*enbw(win,2*pi) と等価です。

データ型: char | string

名前と値の引数

すべて折りたたむ

オプションの引数のペアを Name1=Value1,...,NameN=ValueN として指定します。ここで、Name は引数名で、Value は対応する値です。名前と値の引数は他の引数の後に指定しなければなりませんが、ペアの順序は重要ではありません。

例: spectrogram(x,100,OutputTimeDimension="downrows")x を長さ 100 のセグメントに分割し、各セグメントにその長さのハミング ウィンドウを適用します。スペクトログラムの出力には、行方向に沿った時間次元があります。

しきい値。デシベル単位で表される実数スカラーとして指定します。

MinThreshold=th を指定した場合、spectrogram は、条件 10 log10(s) ≤ th を満たす s の要素をゼロに設定します。

出力時間次元。次のいずれかの値として指定します。

  • "acrosscolumns"spectrogram は、spsfc、および tc の時間次元を列方向に、周波数次元を行方向に設定します。

  • "downrows"spectrogram は、spsfc、および tc の時間次元を行方向に、周波数次元を列方向に設定します。

出力引数を指定して spectrogram を使用する場合、この引数は無視されます。

データ型: char | string

R2025a 以降

ターゲットの親コンテナー。Axes オブジェクト、UIAxes オブジェクト、または Panel オブジェクトとして指定します。

Parent を指定した場合、spectrogram 関数は、呼び出し時の出力引数の有無にかかわらず、指定されたターゲットの親コンテナーにスペクトログラムを描画します。

ターゲット コンテナーおよび MATLAB® グラフィックスにおける親子関係の詳細については、グラフィックス オブジェクトの階層を参照してください。UIAxes オブジェクトおよび Panel オブジェクトの Parent を使用したアプリ設計の詳細については、Plot Spectral Representations of Signal in App Designerを参照してください。

出力引数

すべて折りたたむ

短時間フーリエ変換 (STFT) 出力。行列として返されます。時間は s の列方向に、周波数は行方向に下がって 0 から増加します。

  • x が長さ Nx の信号の場合、sk 列になります。ここで

    • win がスカラーの場合は、k = ⌊(NxnOverlap)/(winnOverlap)⌋。

    • win がベクトルの場合は、k = ⌊(NxnOverlap)/(length(win)nOverlap)⌋。

  • x が実数値で freqSpec が偶数の場合、s は (freqSpec/2 + 1) 行になります。

  • x が実数値で freqSpec が奇数の場合、s は (freqSpec + 1)/2 行になります。

  • x が複素数値の場合、sfreqSpec 行になります。

  • "reassigned" 引数を指定した場合でも、s は変更されません。

メモ

freqRange"onesided" に設定した場合、spectrogram は、正のナイキスト範囲の s 値を出力し、合計パワーを保存しません。

STFT 出力と関連付けられている周波数。ベクトルとして返されます。

  • Fs を指定した場合、f には Hz 単位の循環周波数が含まれます。

  • Fs を指定しない場合、f にはラジアン/サンプル単位の正規化周波数が含まれます。

STFT 出力と関連付けられている時間。ベクトルとして返されます。

  • Fs を指定した場合、t には秒単位の時点が含まれます。

  • Fs を指定しない場合、t には (サンプル数)/(2π) 単位のサンプル インデックスが含まれます。

t の値は、各セグメントの中間点に対応します。

パワー スペクトル密度 (PSD) またはパワー スペクトル。行列として返されます。

  • x が実数値で freqRange を指定しない場合、または "onesided" に設定した場合、ps は各セグメントの PSD またはパワー スペクトルの片側修正ピリオドグラム推定を含みます。この関数は 0 とナイキスト周波数以外のすべての周波数でパワーを 2 倍にして、合計パワーを保存します。

  • x が複素数値の場合、もしくは freqRange"twosided" または "centered" に設定した場合、ps は各セグメントの PSD またはパワー スペクトルの両側修正ピリオドグラム推定を含みます。

  • freqSpec に正規化周波数または循環周波数のベクトルを指定した場合、ps は入力周波数で評価された各セグメントの PSD またはパワー スペクトルの修正ピリオドグラム推定を含みます。

エネルギー中心の周波数および時間。短時間フーリエ変換と同じサイズの行列として返されます。サンプル レートを指定しない場合、fc の要素は正規化周波数として返されます。

spectrogram 関数は、"reassigned" オプションを指定した場合にのみ、fctc を返します。fc または tc の各再割り当て値が範囲外である場合、spectrogram はそれらをそれぞれ f および t の対応する値で置き換えます。

詳細

すべて折りたたむ

ヒント

  • STFT 行列にゼロがある場合、デシベルに変換すると、プロットできない負の無限大になります。この問題を回避するために、spectrogram を出力引数なしで呼び出した場合、または Parent 引数を指定した場合には、STFT 行列に eps が加えられます。

  • STFT 行列の振幅値がゼロに非常に近い場合、"reassigned" オプションを指定すると、スペクトログラムの再割り当てが数値的に不安定になる可能性があります。このような場合は、"reassigned" オプションを使用しないでください。

参照

[1] Boashash, Boualem, ed. Time Frequency Signal Analysis and Processing: A Comprehensive Reference. Second edition. EURASIP and Academic Press Series in Signal and Image Processing. Amsterdam and Boston: Academic Press, 2016.

[2] Chassande-Motin, Éric, François Auger, and Patrick Flandrin. "Reassignment." In Time-Frequency Analysis: Concepts and Methods. Edited by Franz Hlawatsch and François Auger. London: ISTE/John Wiley and Sons, 2008.

[3] Fulop, Sean A., and Kelly Fitz. "Algorithms for computing the time-corrected instantaneous frequency (reassigned) spectrogram, with applications." Journal of the Acoustical Society of America. Vol. 119, January 2006, pp. 360–371.

[4] Oppenheim, Alan V., and Ronald W. Schafer, with John R. Buck. Discrete-Time Signal Processing. Second edition. Upper Saddle River, NJ: Prentice Hall, 1999.

[5] Rabiner, Lawrence R., and Ronald W. Schafer. Digital Processing of Speech Signals. Englewood Cliffs, NJ: Prentice-Hall, 1978.

拡張機能

すべて展開する

バージョン履歴

R2006a より前に導入

すべて展開する