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

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

ただいまの
回答率

88.91%

【python】matplotlib? 音の信号をスペクトログラムで表示させたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 365
退会済みユーザー

退会済みユーザー

前提・実現したいこと

yに入れた信号をスペクトログラムで表示させたいのですが、
最後の行で下のようなエラーが出てしまいます。
どのようにしたら問題なくスペクトログラムを表示させられるでしょうか?
教えてください!

発生している問題・エラーメッセージ

Traceback (most recent call last):
  File "ans1.py", line 43, in <module>
    Sxx, f, t, im = plt.specgram(y, cmap='jet')
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/pyplot.py", line 2845, in specgram
    is not None else {}), **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/__init__.py", line 1565, in inner
    return func(ax, *map(sanitize_sequence, args), **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/matplotlib/axes/_axes.py", line 7602, in specgram
    pad_xextent = (NFFT-noverlap) / Fs / 2
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

該当のソースコード

# -*- coding: utf-8 -*-

import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt

Amp = 1.0

def GenFreq(Fc, Fs, dur):
    # 長さ dur 秒間,周波数 Fc[Hz] のデータを
    # サンプリング周波数 Fs[Hz] で生成する.
    # 正弦波関数を用いる
    # この関数を実装しなさい.(定義は変えてもOK)
    delta = 1./Fs  # サンプリング間隔
    Nmax = Fs * dur   # サンプル点の数
    t = np.arange(Nmax) * delta
    x = Amp * np.sin(2. * np.pi * Fc * t)
    x *= 32767              # windows標準のプレイヤーで再生できなかったので追加
    x = x.astype(np.int16)  # windows標準のプレイヤーで再生できなかったので追加
    return x




# 以下に GenFreq を用いて "CDEFGAB" の音階を各 dur 秒間
# 生成するスクリプトコードを書く

Fs = 22100.        # サンプリング周波数
Fcs = (262, 294, 330, 349, 392, 440, 494, 523)

y = GenFreq(Fcs[0], Fs, 3)

for i in [1,2,3,4,5,6,7]:
    y = np.append(y, GenFreq(Fcs[i], Fs, 3))


# y に音声波形を入れたものとしてファイルを保存
fname = 'MkSnd4Test.wav'
write(fname, int(Fs), y)


#スペクトログラムで確認
Sxx, f, t, im = plt.specgram(y, cmap='jet')

plt.figure(figsize=(8,6))
plt.pcolormesh(t, f, np.log(Sxx), cmap='jet')
plt.xlim(0, 2.0e5)

試したこと

調べたところplt.specgramというのがあったので使用してみました。

補足情報(FW/ツールのバージョンなど)

実行環境はGoogle Colabです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

matplotlibのspecgramにてパラメータを確認したうえで、サンプル周波数(単位時間あたりのサンプル数)を与えてあげるとエラーが出なくなりました。
また、元コードだと空のグラフ画面が余計に出ていたので、描画部分もコードを書き換えると、それらしい画像が得られました。

#スペクトログラムで確認
fig = plt.figure(figsize=(8,6))
Sxx, f, t, im = plt.specgram(y, Fs = int(Fs), cmap='jet')
plt.pcolormesh(t, f, np.log(Sxx), cmap='jet') # ★
#plt.xlim(0, 2.0e5)
plt.show()

★あり

イメージ説明

★なし

イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/19 13:42

    できました!
    ファイルからは実行できないんですね。
    これは別の質問になるのですが、縦軸の数値を決めている部分はどこに当たるのでしょうか?
    もう少し狭い範囲(例えば0~600まで)としたいのですが。。

    キャンセル

  • 2020/07/19 14:01

    specgramは使ったことないのでちょっと分かりません。
    もしかしたらパラメータで指定できるかもしれませんが。

    キャンセル

  • 2020/07/19 14:37

    わかりました。ありがとうございました!

    キャンセル

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

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る