14
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで音を3D可視化してみた

14
Last updated at Posted at 2025-12-12

はじめに

みなさん、音を可視化したら面白いと思いませんか?

最近プログラミングにおける音の取り扱いに興味があるので、これを機に音の可視化に挑戦してみようと思いました。

今回はPythonで音を3Dで可視化してみます。

前提

開発環境

  • Mac OS
  • Python 3.13.2
  • パッケージ管理にuvを使用しています

今回のゴール

スクリーンショット 2025-12-11 18.34.21.png

こんな感じのものを作成していこうと思います。

最初はサンプル用の音をコード内で生成したものを可視化してみようと思います。

必要なライブラリのインストール

まずは必要なライブラリをインストールしていきます。

私は今回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をブラウザで見てみましょう!

スクリーンショット 2025-12-11 18.34.21.png

こんな感じのグラフが表示できたら完成です!

マウスのドラッグで動かしてみることもできます!

おわりに

いかがでしたでしょうか?

今回は音の可視化に挑戦してみました!

音を「見る」ことで、音楽の構造や楽器の配置が視覚的にわかって面白いですね。

ぜひいろいろな音源を使って音の可視化をしてみてください!

14
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?