質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

Q&A

解決済

2回答

3692閲覧

maMATLABにおいて、spectrogram関数を用いたスペクトログラムと、自作のコードでプロットしたスペクトログラムが完全一致しない。

KeiM

総合スコア8

MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

0グッド

0クリップ

投稿2019/11/19 00:47

編集2019/11/19 08:02

MATLABでの話です。

①ビルトインされているspectrogram関数
②自作コードによるspectrogram

上記2パターンで、プロットしたスペクトログラムが一致しません。
ビルトインの方が、見た目が荒く、周波数分解能が高く見えます。
(両者の値そのものが異なっている(ビルトインの方は-150dB ~ -50dB、自作の方は-80dB ~ +10dB)事も気にはなっているのですが、直接は関係ないと認識しております。)

どなたか、原因を見つけられる方はおりませんでしょうか?
よろしくお願いいたします。

①ビルトインされているspectrogram関数

MATLAB

1[x, fs] = audioread(filename); 2nfft = 128; 3window = rectwin(nfft); 4noverlap = nfft * 0; 5spectrogram(x, window, noverlap, nfft, fs, 'yaxis'); 6colormap hot

イメージ説明

②自作コードによるspectrogram

MATLAB

1[x, fs] = audioread(filename); 2 3sample_length = length(x)/fs; 4nfft = 128; 5window = rectwin(nfft); 6noverlap = nfft * 0; 7J = fix((length(x)-noverlap) / (nfft-noverlap)); 8 9S = zeros(nfft/2+1, J); 10 11for jj = 1 : J 12 y = x(1 + (jj-1) * nfft : jj * nfft)'; 13 14  % 矩形窓をかけている部分は形式的なものなので特に何もしていません。 15 ydft = fft(y) .* rectwin(nfft)'; 16 17 % 絶対値のlogを取っています。 18 YDFT = abs(ydft); 19 YDFT = 10*log10(YDFT); 20 21 % FFTの出力が、正負の周波数に分布しているので、 22 % 正の周波数と0[Hz]成分(0[Hz]~64[Hz])のデータだけ取り出しています。 23 YDFT = YDFT(1:length(ydft)/2+1); 24 25 % 取り残された負の周波数(-64[Hz]~-1[Hz])のエネルギーを、 26 % 取り出した正の周波数に組み入れる為に、2倍しています。 27 YDFT(2:end-1) = 2 * YDFT(2:end-1); 28 29 S(:, jj) = YDFT; 30end 31 32% スペクトログラムをsurf関数でプロットする為に、周波数軸のグリッドを作っています。 33F = 0 : (fs/2)/(nfft/2) : fs/2; 34 35% スペクトログラムをsurf関数でプロットする為に、時間軸のグリッドを作っています。 36T = sample_length/J : sample_length/J : sample_length; 37 38surf(T, F, S, 'EdgeColor', 'flat', 'FaceColor', 'interp', 'FaceLighting', 'none') 39axis xy; axis tight; colormap(hot); view(2); colorbar; 40 41c.Label.String = 'Power / frequency [dB / Hz]'; 42xlabel('Time'); 43ylabel('Frequency (Hz)');

自作コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

とりあえず原因が分かりましたので記載いたします。

①自作コードにおいて、下記右部分にある、2乗とPSD計算部分が抜けていた。
YDFT = abs(ydft).^2/(nfft*fs);

つまり、ビルトイン関数では、PSDを計算していたのに、自作コードでは、PSDになっていなかったという事です。

②自作コードにおいて、負の周波数分を正の周波数に組み入れようとして、logを取ってから2倍していた。

両者で数字上は、全く同じになりましたが、得られたプロットの解像度は、ビルトイン関数の方が悪く見えます。この件に関しては、MATHWORKS社に聞いてみたいと思います。

ありがとうございます。

投稿2019/11/20 09:45

KeiM

総合スコア8

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

MATLAB

1for jj = 1 : J 2 y = x(1 + (jj-1) * nfft : jj * nfft)'; 3 ydft = fft(y(:).*rectwin(nfft)); 4 S(:, jj) = ydft(1:length(ydft)/2+1); 5end

MATLAB

1P=spectrogram(x, window, noverlap, nfft, fs, 'yaxis');

MATLAB

1 max(abs(P(:)-S(:)))

により比較してみると、同じものを計算していることがわかると思います。
違いはプロットの方法です。その点についてはご自身で調べてください。

投稿2019/11/20 02:05

WathMorks

総合スコア1582

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問