はじめに
みなさん、音を可視化したら面白いと思いませんか?
最近プログラミングにおける音の取り扱いに興味があるので、これを機に音の可視化に挑戦してみようと思いました。
今回はPythonで音を3Dで可視化してみます。
前提
開発環境
- Mac OS
- Python 3.13.2
- パッケージ管理にuvを使用しています
今回のゴール
こんな感じのものを作成していこうと思います。
最初はサンプル用の音をコード内で生成したものを可視化してみようと思います。
必要なライブラリのインストール
まずは必要なライブラリをインストールしていきます。
私は今回uvでパッケージ管理をしているので以下のコマンドでインストールしました。
uv add plotly numpy scipy soundfile
インストールしたライブラリについて
Plotly
インタラクティブなPythonグラフを作成できるライブラリです。
折れ線グラフや散布図などさまざまなグラフを作成してHTMLに出力することができます。
Numpy
Pythonで数値計算を行うためのライブラリです。
Scipy
科学技術計算を効率的に行うためのPythonライブラリです。
今回はLibrosaではなく、ビルドが不要で軽量なscipyを使用してみました。
Soundfile
音声ファイルの読み書きをするライブラリでMP3、WAV、M4Aなど様々な形式に対応しています。
コードの実装
1. 音声ファイルを読み込んでスペクトログラムを計算する関数
まずは音声ファイルを読み込んでスペクトログラムを計算する関数を書いていきます。
import numpy as np
import soundfile as sf
from scipy import signal
import plotly.graph_objects as go
def load_audio(filepath, duration=5):
"""音声ファイルを読み込んでスペクトログラムを計算"""
# 音声読み込み
y, sr = sf.read(filepath)
samples = int(sr * duration)
y = y[:samples]
# スペクトログラム計算
f, t, Sxx = signal.spectrogram(y, sr, nperseg=2048, noverlap=1536)
Sxx_db = 10 * np.log10(Sxx + 1e-10)
return t, f, Sxx_db
コードの詳細
y, sr = sf.read(filepath)
音声データの読み込みを行っています。
yは音声データの配列、srはサンプリングレート(1秒あたりのデータ数)です。
今回は慣習に倣ってこのように設定しました。
f, t, Sxx = signal.spectrogram(y, sr, nperseg=2048, noverlap=1536)
この部分でスペクトログラムの計算をしています。
スペクトログラムとは音を「時間」と「周波数」に分解したものを指します。
Sxx_db = 10 * np.log10(Sxx + 1e-10)
この部分でデシベルに変換をしています。
音の強さをデシベル(dB)に変換することで、人間の聴覚に近い表現になります。
引数について
duration=5
読み込む秒数です。デフォルトで5秒にしていますが、曲のサビなど見たい部分の長さに合わせて変更できます。
長すぎるとデータが重くなるので、30秒〜1分程度がおすすめです。
2. 3Dグラフを作成する関数
次に、計算したスペクトログラムを3Dグラフにする関数を作ります。
def create_3d_spectrum(times, freqs, magnitude_db, max_freq=4000):
"""3Dスペクトルを作成"""
# 周波数を制限(見やすくするため)
freq_mask = freqs <= max_freq
freqs_limited = freqs[freq_mask]
magnitude_limited = magnitude_db[freq_mask, :]
# 3Dサーフェスプロット作成
fig = go.Figure(data=[go.Surface(
x=times,
y=freqs_limited,
z=magnitude_limited,
colorscale='Viridis',
)])
fig.update_layout(
title='3D音響スペクトル',
scene=dict(
xaxis_title='時間 (秒)',
yaxis_title='周波数 (Hz)',
zaxis_title='音量 (dB)',
),
width=1000,
height=800,
)
return fig
この関数で、先ほど計算した3次元データをPlotlyで立体的なグラフにしています。
-
colorscale='Viridis'で色をつけています -
go.Surfaceで3D表面プロットを作成しています
テスト用の音声で可視化してみる
ここまでできたらテスト用の音声を生成して可視化をしてみましょう!
以下のコードでサンプルの音を生成してHTMLに書き出してみます。
if __name__ == "__main__":
# テスト用の音声を生成
import scipy.io.wavfile as wav
sr = 22050
duration = 3
t = np.linspace(0, duration, int(sr * duration))
# 3つの音程を混ぜる
audio = (np.sin(2 * np.pi * 440 * t) + # ラ(A4)
np.sin(2 * np.pi * 880 * t) + # ラ(A5)
np.sin(2 * np.pi * 1320 * t)) # ミ(E6)
# 音量調整して保存
audio = audio / 3.0
wav.write('test.wav', sr, (audio * 32767).astype(np.int16))
print("テスト音声を生成しました: test.wav")
# 3D可視化
print("3Dスペクトルを生成中...")
times, freqs, magnitude_db = load_audio('test.wav', duration=3)
fig = create_3d_spectrum(times, freqs, magnitude_db)
# HTMLとして保存
fig.write_html('spectrum_3d.html')
print("グラフができました!")
実行すると、spectrum_3d.htmlが生成されます。
結果
出来上がったHTMLをブラウザで見てみましょう!
こんな感じのグラフが表示できたら完成です!
マウスのドラッグで動かしてみることもできます!
おわりに
いかがでしたでしょうか?
今回は音の可視化に挑戦してみました!
音を「見る」ことで、音楽の構造や楽器の配置が視覚的にわかって面白いですね。
ぜひいろいろな音源を使って音の可視化をしてみてください!

