Python 実践 データ加工/可視化 100本ノック に挑戦 ノック77 ノック78

ノック77 :周波数スペクトルを表示してみよう

 

一般的に高い音は周波数が大きく周期が短く、低い音は周波数が小さく周期が長くなります。

波形は様々な周波数のあつまりで、複数の周波数を分解する方法として

フール絵変換があります。

audo1をフーリエ変換します。

np.fft.fftフーリエ変換が実行されます。

fftの値には複素数も含まれています。振幅スペクトルを表示するためには、np.abs(fft)で複素数の値を絶対値に変換します。

横軸は周波数となります。np.fft.fftfreqで取得します。

import librosa
import numpy as np

audio1,sr1 = librosa.load('data/音声.mp3'         ,sr=None,offset=0,duration=1)
audio2,sr2 = librosa.load('data/携帯電話着信音.mp3',sr=None,offset=0,duration=1)

#フーリエ変換結果をfft変数に代入
fft  = np.fft.fft(audio1)
n    = fft.size
amp  = np.abs(fft)
freq = np.fft.fftfreq(n,d=1/sr1)

print(amp.shape)
print(freq.shape)
print(amp.max())
print(amp.min())
print(freq.max())
print(freq.min())

 

実行結果

(44100,)
(44100,)
479.5421053865585
2.649061305061189e-05
22049.0
-22050.0

 

matplotlibを使用して表示します。

//2で2で割ることを表しています。(少数は切り捨て)

振幅の半分は符号が異なるだけで同じデータなので2で割っています。

import matplotlib.pyplot as plt

plt.figure(figsize=(10,5))
plt.plot(freq[:n//2],amp[:n//2])
plt.xlabel("Frequency[Hz")
plt.ylabel("Amplitude")
plt.show()

 

 

実行結果

振幅スペクトル

1000Hz以下のデータが大半であることがわかります。

 

2で割らなかったらどうなるかというと、

振幅スペクトル ±

 

 

ノック78 :スペクトログラムを可視化してみよう

 

スペクトログラムデータの作成を行います。

2048標本点をフレーム長とし,フレーム長の4分の1に相当する512標本点をフレーム周期とし,フレーム処理を行います。

stft = librosa.stft(audio1)
amps = np.abs(stfs)
spectrogram = librosa.amplitude_to_db(amps)

print(stft.shape)
print(amps.shape)
print(spectrogram.shape)

 

実行結果

(1025, 87)
(1025, 87)
(1025, 87)

 

どの値も以下のように算出した値となります。

2048÷2=1024+1=1025

44100Hz÷512(サンプリング幅)=86+1=87

 

スペクトログラムを可視化してみます。

import librosa.display

plt.figure(figsize=(10,5))
librosa.display.specshow(spectrogram,sr=sr1,x_axis='time',y_axis='hz',cmap='magma')
bar=plt.colorbar()
bar.ax.set_ylabel('db')
plt.show()

 

 

実行結果

スペクトログラム

縦軸がHzです。1000Hz以下がとくに音のデータが多いことがわかります。

色はdb(デシベル)表記です。dbは音の大きさを表す単位です。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

/* -----codeの行番号----- */