pythonで音声の解析を行う

pythonで音声の解析を行う
import librosa
import numpy as np
import matplotlib.pyplot as plt
import librosa.display

# 音階名を取得する関数
def freq_to_note(freq):
    if freq == 0:
        return "N/A"
    A4 = 440.0
    C0 = A4 * np.power(2, -4.75)
    h = round(12 * np.log2(freq / C0))
    octave = h // 12
    n = h % 12
    note_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
    return note_names[n] + str(octave)

# WAVファイルのパス
file_path = '/Users/haru/Downloads/|かえるの合唱|アカペラ|歌ってみた|人気童謡|童謡|こどもの歌|.wav'

# WAVファイルを読み込む
y, sr = librosa.load(file_path)

# 短時間フーリエ変換 (STFT)
D = librosa.stft(y)

# 振幅スペクトログラム
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)

# 時間軸
times = librosa.times_like(S_db, sr=sr)

# 周波数軸
frequencies = librosa.fft_frequencies(sr=sr)

# dB値の閾値
db_threshold = -1000

# 周波数成分の抽出
peak_frequencies = []
peak_times = []
peak_db = []
for i, time in enumerate(times):
    magnitude_spectrum = np.abs(D[:, i])
    db_spectrum = S_db[:, i]
    if np.max(db_spectrum) > db_threshold:
        peak_index = np.argmax(db_spectrum)
        if db_spectrum[peak_index] > db_threshold:
            peak_frequency = frequencies[peak_index]
            peak_db_value = db_spectrum[peak_index]
            peak_frequencies.append(peak_frequency)
            peak_times.append(time)
            peak_db.append(peak_db_value)
            note = freq_to_note(peak_frequency)
            print(f"Time: {time:.2f}s, Frequency: {peak_frequency:.2f} Hz, dB: {peak_db_value:.2f}, Note: {note}")

# 線で繋いでプロット
plt.figure(figsize=(12, 6))
plt.plot(peak_times, peak_frequencies, color='b', marker='o', linestyle='-', label='Peak Frequency')
plt.xlabel('Time (s)')
plt.ylabel('Frequency (Hz)')
plt.title('Peak Frequency over Time')
plt.grid(True)
plt.legend()
plt.show()

# スペクトログラムをプロット
plt.figure(figsize=(12, 8))
# -30dB以下の部分をNaNにしてプロット
S_db[S_db < db_threshold] = np.nan
librosa.display.specshow(S_db, sr=sr, x_axis='time', y_axis='log', cmap='coolwarm')
plt.colorbar(format='%+2.0f dB')
plt.title('Spectrogram (Filtered, dB > -30)')
plt.xlabel('Time (s)')
plt.ylabel('Frequency (Hz)')
plt.show()

Comments

No comments yet. Why don’t you start the discussion?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です