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

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

ただいまの
回答率

88.92%

各wavfileデータごとに周波数分布図を出力したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 170

karita

score 15

現状

jupyter notebookであるディレクトリ内の複数のステレオ音wavfileを繰り返してフーリエ変換しているところです。
ここで、縦軸を振幅、横軸を周波数とした分布図を出力しましたが、全ファイルのデータが混ざった状態になっているようです。

個々のwavファイルのフーリエ変換結果に対して、1つずつ分布図を出力する方法はあるのでしょうか?

該当の分布図を貼り付けたかったのですが、できなかったので省略しています。
ご回答のほど、よろしくお願いいたします。

該当のコード

import wave
from pydub import AudioSegment
import glob
import os
import struct
from scipy import fromstring, int32
import numpy as np
from pylab import *
%matplotlib inline

os.chdir('C://Users//karita//sound//data//wav') #パス指定

for file in glob.glob("*.wav"):
    wavfile = open(file, "rb")#サンプルwavファイル
    wr = wave.open(wavfile, "rb") #wavファイルの読み込み
    ch = wr.getnchannels() # モノラルなら1,ステレオなら2
    width = wr.getsampwidth() # サンプル長(1byte=8bit)
    fr = wr.getframerate() #サンプリンググレート(サンプリング周波数)
    fn = wr.getnframes() # 全体のオーディオフレーム数(全データ点数)⇒サンプリング周波数で割れば時間

    N = 48000 #サンプリングレート"fr"の半分の値
    span =4 #フーリエ変換の回数

    print(wavfile)
    print('サンプル数',N)
    print('チャンネル', ch)
    print('サンプル長(bytes)', width)
    print('サンプリンググレート', fr)
    print('全オーディオフレーム数', fn)
    print('サンプル時間',fn/fr,'秒')
    print('N*span時間', 1.0 * N * span / fr, '秒')

    origin = wr.readframes(wr.getnframes()) #メソッドreadframes(n)でnデータ点数を読み込む、ここでは全データ点数の読み込み
    data = origin[:N * span * ch * width] #"origin"から要素の範囲[ ]を指定
    wr.close()

    print('現配列長', len(origin)) #"origin"の要素数
    print('サンプル配列長: ', len(data)) #"data"の要素数

    X = np.frombuffer(data, dtype="int16")#"data"をバイナリ表記から16bitsの整数数列に変換

    # ステレオ前提、左右音に分ける ※モノラルは単に1つおきにデータを読みこむため、必要ない工程 
    left = X[::2] #"0から2番目おき"に要素を得る
    right = X[1::2] #"1から2番目おき"に要素を得る

    print(X)
    print(len(X))
    print(left)
    print(len(left))
    print(right)
    print(len(right))

    #各サンプル区間ごとの周波数分布を配列で返してきます
    def fourier (x, n, w): #x:データ成分、n:個数、w:次元
        K = []
        for i in range(0, w-2): 
            sample = x[i * n:( i + 1) * n] #i~(i+1)番目の要素を得る
            partial = np.fft.fft(sample) #"sample"をフーリエ変換
            K.append(partial) #"K"に"partial"を追加

        return K

    #周波数分布をもとに、実空間での波形を生成しています
    def inverse_fourier (k):
        ret = []
        for sample in k:
            inv = np.fft.ifft(sample) #"sample"を逆フーリエ変換
            ret.extend(inv.real) #"inv.real"を"ret"に追加

        print (len(sample))
        return ret

    Kl = fourier(left, N, span)
    Kr = fourier(right, N, span)
    #周波数リスト
    freqlist = np.fft.fftfreq(N, d=1/fr)
    #振幅スペクトル #実部と虚部を取り出すには、".real" と ".imag" を使用
    #kl[1]は要素数2以上必要⇒spanは4以上
    amp = [np.sqrt(c.real ** 2 + c.imag ** 2) for c in Kl[1]] 
    plot(freqlist, amp, marker= 'o', linestyle='-') #周波数リスト、振幅スペクトル、点、線スタイル
    axis([0, 48000, 0, 100000])

    amp = [np.sqrt(c.real ** 2 + c.imag ** 2) for c in Kr[1]]
    plot(freqlist, amp, marker= 'o', linestyle='-')



    for i, file in enumerate(glob.glob("*.wav")):
    # 出力CSVファイル名
        csv_path = os.path.splitext(os.path.basename(file))[0] + '.csv'    # 元のファイル名をそのままつける

        np.savetxt( csv_path, [amp], fmt="%.0f",delimiter=",")

    print('==============================================================================================================================')


<_io.BufferedReader name='000000000.wav'>
サンプル数 48000
チャンネル 2
サンプル長(bytes) 4
サンプリンググレート 96000
全オーディオフレーム数 192000
サンプル時間 2.0 秒
N*span時間 2.0 秒
現配列長 1536000
サンプル配列長:  1536000
[ 6656  6144 -7681 ...  4864  1791    -1]
768000
[ 6656 -7681 -6656 ... 15103 32000  1791]
384000
[6144   -1 6191 ...   -1 4864   -1]
384000

==============================================================================================================================
<_io.BufferedReader name='000001000.wav'>
サンプル数 48000
チャンネル 2
サンプル長(bytes) 4
サンプリンググレート 96000
全オーディオフレーム数 192000
サンプル時間 2.0 秒
N*span時間 2.0 秒
現配列長 1536000
サンプル配列長:  1536000
[ 6656  6144 -7681 ...  4864  1791    -1]
768000
[ 6656 -7681 -6656 ... 15103 32000  1791]
384000
[6144   -1 6191 ...   -1 4864   -1]
384000

==============================================================================================================================
<_io.BufferedReader name='000002000.wav'>
サンプル数 48000
チャンネル 2
サンプル長(bytes) 4
サンプリンググレート 96000
全オーディオフレーム数 192000
サンプル時間 2.0 秒
N*span時間 2.0 秒
現配列長 1536000
サンプル配列長:  1536000
[ 6656  6144 -7681 ...  4864  1791    -1]
768000
[ 6656 -7681 -6656 ... 15103 32000  1791]
384000
[6144   -1 6191 ...   -1 4864   -1]
384000

==============================================================================================================================



(各wavファイルの情報の出力後、一番下に分布図出力される)

補足情報

windows10
python3.7.4

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

1つずつ分布図を出力する方法はあるのでしょうか?

plot()のあとにshow()を入れてください。

import numpy as np
from pylab import *
%matplotlib inline

x = np.array([i for i in range(10)])
for g in range(2):
    c = 'red' if g == 0 else 'blue'
    plot(x, x * 2 + g*3, c)
    #show() # これを入れる

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/13 11:21

    show()で望んだ出力ができました。
    ありがとうございます。

    キャンセル

0

全ファイルのデータが混ざった状態になっているようです。

原因: ループが二重になっているからではないでしょうか。
保存時の処理の後にログを出力し、意図通りのファイルへ保存されているか確認しましょう。

for file in glob.glob("*.wav"):

    # 略

    for i, file in enumerate(glob.glob("*.wav")):
        csv_path = os.path.splitext(os.path.basename(file))[0] + '.csv'    # 元のファイル名をそのままつける
        np.savetxt( csv_path, [amp], fmt="%.0f",delimiter=",")

修正方法: 保存時、全ファイルに対して書き込んでいるのを辞める

for file in glob.glob("*.wav"):

    # 略

    csv_path = os.path.splitext(os.path.basename(file))[0] + '.csv'    # 元のファイル名をそのままつける
    np.savetxt( csv_path, [amp], fmt="%.0f",delimiter=",")

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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