信号処理は計測データに対して行うことがよくあります。オーディオファイルであるwavファイルは計測データを格納するのに非常に適した形式であるため、本記事ではwavファイルの波形を表示することで、Pythonでデータを処理可能にする方法までを説明します。
こんにちは。wat(@watlablog)です。
いよいよ信号処理のための第一歩!
wav波形の取り込み方法を習得します!
wavファイルを波形表示する
wavファイルとは?
wavファイルとは一言で言えば音声ファイルです。音楽や会議の音声録音時に頻繁に使われるファイル形式ですが、実は計測の現場でも重宝されています。
かく言う僕も仕事で実験を行うのですが、計測した何かしらのデータを色々なソフトに読み込ませる時に、このwavファイルを使うことがあります。
wavファイルは歴史が古いファイル形式なので、様々なソフトに対応しています。各専門のソフト形式の方が計測データの保存に優れている部分が多くありますが、ソフト間の橋渡し、互換性という意味ではwavファイルが最強なのではないでしょうか?
Pythonでwavファイルを扱ってみよう!
使うパッケージ
今回調べた中では、以下のライブラリパッケージを使う方法が最も簡単でした。カッコ内はpipを使ったインストールコマンドです。
pipについての詳しい説明は「Pythonのパッケージ管理ツール pipの使い方とコマンド集」をご覧下さい。
- NumPy (python -m pip install numpy)
- matplotlib (python -m pip install matplotlib)
- PySoundFile (python -m pip install pysoundfile)
特に、PySoundFileは音声ファイルを扱うためのライブラリなので、wavファイルの扱いに関して強い味方になってくれます。
NumPyはwavファイルのデータをPythonで扱える行列形式に変換し、matplotlibはグラフを描画するために使います。
波形表示までのコード
プログラミングしたソースコードを紹介します。今回も基本はdef文を使った関数形式でメインであるwav読み込みの部分を記述しました。
関数の基本的な使い方は「Pythonの関数 def文の使い方!引数や別ファイル式も解説」をご覧下さい。
関数で表現したwavファイル読み込み部分は以下のwav.pyファイルです。
このプログラムではdataとsamplerateという二つの戻り値を返しています。
dataはnumpyの配列形式(ndarray型)で用意された、波形そのもののデータです。
samplerateはサンプリングレートと呼び、データを収集した時のサンプリング周波数を意味しています。ちなみにサンプリング周波数の逆数が時間刻み値になります。
1 2 3 4 5 |
import soundfile as sf def wavload(path): data, samplerate = sf.read(path) return data, samplerate |
実行するファイルはこちらのmain_wavplot.pyです。
wav.pyをimportして参照しています。numpyはグラフ表示時の横軸の作成に使っています。len文で波形の長さ(データ数)を取得し、サンプリングレートで割る(つまり時間刻み値をかける)ことで時間の最大値を算出しています。
あとはmatplotlibの関数を使ってグラフ表示をするという手順です。
1 2 3 4 5 6 7 8 9 10 11 12 |
import wav import numpy as np from matplotlib import pyplot as plt path = 'ff_A.wav' data, samplerate = wav.wavload(path) t = np.arange(0, len(data))/samplerate plt.plot(t, data) plt.show() plt.close() |
以下が実行結果です。無事に波形表示ができました!
追記:関数ファイルを使わないで一度に書く
先ほどまでのコードは今後のことも考え関数ファイル(wav.py)を作成し、メインの実行ファイル(main.py)でwav.pyをインポートしていましたが、この程度の文量であれば1つのファイルに全て記入した方が良いかも知れません。
以下に純粋に1つの.pyファイルだけを使ってwav波形を表示させるコードを紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import soundfile as sf # wavファイルの取り扱いに使用 import numpy as np # 配列処理に使用 from matplotlib import pyplot as plt # グラフ表示に使用 path = 'ff_A.wav' # wavファイルまでのパスを指定(名前はお手持ちのファイル名に変更して下さい) data, samplerate = sf.read(path) # wavファイルを読み込む t = np.arange(0, len(data)) / samplerate # グラフ表示のための横軸を設定 # グラフ表示 plt.plot(t, data) plt.show() plt.close() |
この方がシンプルでした!
まとめ
Pythonで簡単にwav波形の中身を表示するためには、PySoundFileというパッケージが便利でした。
まずは波形を表示、次に本題の信号処理、という流れになります。
また、今はグラフの書式は適当ですが、軸のラベル等書式は別記事でまとめたいと思います。
意外と簡単にwav波形のグラフ表示ができたぞ!もしかしてPythonって思ったより初心者にやさしい?
さぁ!これから信号処理だ!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!
コメント失礼します。このサイトのコードを使ってモーターの振動解析をしようと試みました。
import wav と入力すると、name ‘wav’ is not definedと出たので、
import wave 入力して行い、次に data, samplerate = wave.waveload(path)と入力すると、AttributeError: module ‘wave’ has no attribute ‘waveload’とエラーが出ました。どうすれば解決するでしょうか。
ご訪問ありがとうございます!
記事がわかりにくくて申し訳ございません。
この記事では、「wav.py」というファイルにdef文を記入し、同フォルダに作るメイン実行ファイルでwav.pyをインポートする仕様でした。
wav.pyはご用意されていますでしょうか?waveというのはPythonのその他ライブラリ名なので「そんな属性はありません」と出たと考えられます。
とはいえ、本記事はわかりにくかったので、「追記:関数ファイルを使わないで一度に書く」にたった一つだけのPythonファイルで実行できるようなコードを追記しました。
まずはこちらの内容で再度ご確認いただけませんでしょうか?
よろしくお願い致します!
data, samplerate = sf.read(path) この部分でpathの部分は’test.mp3’なのですがRuntimeError: Error opening ‘test.mp3’: File contains data in an unknown format.というようなエラーが出てしまいました。どうすればよいでしょうか?
ご訪問ありがとうございます!
mp3というフォーマットを用意されているので、本ページで紹介しているPySoundFileのコードで扱えなくエラーとなっているみたいです(フォーマットエラー)。
PySoundFileの公式ページを見てみてもmp3は扱えないようです。ただmp3をそのまま処理するのはかなり難易度が高いみたいです。そんな時はお手持ちのmp3をwavファイルに変換するという選択肢もあります。
お役に立てるかわかりませんが、「Python/pydubでmp3をwavファイルに変換する方法」にmp3をwavに変換する方法を書きましたので、是非ご確認下さい。
mp3をそのまま扱いたいということであればすみません。
以上、また何かございましたら気軽にコメント下さい!
wavに変更したのですが、RuntimeError: Error opening ‘test.wav’: File contains data in an unknown format.と同じようなエラーが出てしまいました。
おかしいですね…。名前を変更しただけではなく、先ほど紹介しましたページのコードでwavに変換しましたでしょうか?
僕の方もmp3ファイルを用意してみましたが、同じエラーを確認した後、以下の手順で解決することができました。
1.mp3ファイルをpydubとffmpegを使ってwavファイルに変換する。
→こちらの方法「https://watlab-blog.com/2020/05/03/pydub-mp3-wav/」
2.変換されたwavファイルを本ページのコードで波形表示する。
もうすこし手順を教えて頂けると適切な回答ができるかも知れません。
ご確認頂ければ幸いです。よろしくお願いします。
何度もすみません。
pydubとffmpegを使ってwavファイルに変換する方法ではなく、ボイスメモアプリから作成した新規録音.m4aを名前を変更でtest.wavに変更してwavファイルにしました。ファイルの情報を見ると種類:WAVEオーディオとなっており、wavファイルになっていると思われます。
ご回答ありがとうございます。
Windowsのプロパティは拡張子だけでファイルの種類を判断しているため、名前の変更だけでもWAVEオーディオと表示されてしまいます(適当なテキストファイル.txtを.jpgにすると画像と判断されてしまうが明らかに画像では無いという事と同じ)。
しかしファイルの構造(データの並び、文字の種類、ヘッダ、書式)までは拡張子変更だけでwavのフォーマットには変わりません。
そのため、本当のwavファイルにするためには先に紹介した方法やフリーソフトでmp3をwavに「変換」するか、元々wavで録音するかといった方法をとるしかないと思われます。
(僕の方もiPhoneのボイスメモで作成したmp3で検証してみたので、多分同じ方法でいけると思います)
おそらくmp3をPythonでそのまま扱うよりはwavに変換する方法が楽だと思いますので、上記ご検討頂けますでしょうか。よろしくお願いします。
こんにちは。
調べても分からないので、質問させてください。
main.pyを実行すると以下のようなエラーが出ます。
Traceback (most recent call last):
File “main.py”, line 1, in
import soundfile as sf
File “C:\Users\admin\AppData\Local\Programs\Python\Python38\lib\site-packages\soundfile.py”, line 15, in
from cffi import FFI as _FFI
ValueError: source code string cannot contain null bytes
pysoundfileのsoundfile.pyのソースに不備があるのでしょうか?
ご回答いただけたら幸いです。
ご訪問ありがとうございます。
こちらも初めて見るエラーです。
stackoverflow「https://stackoverflow.com/questions/12988619/python-cturtle-module-not-loading」によると、
エラー源のファイルにNullが入っていることが原因で発生するとのことです。
ただ、普通にPySoundfileをインストールできていれば問題ないと思いますが…。
このような場合はPySoundfileを一度アンインストールし、再度pipインストールし直すと解決することが多いのですが、どうでしょうか。
ちなみに、私の環境はWindowsでもMacでもPython3.7, PySoundfile0.9.0、Anaconda使用せず…という環境で、PySoundfileはpipでインストールしています。
ご検討下さい。
ご回答ありがとうございます。
アンインストールしても解決しなかったのですが、watさんのバージョン情報で閃き、PySoundFile公式HPを参考にしました。
試しに、
pip install soundfile
としたところ解決しました。
原因はよくわかりませんが、助かりました。
迅速なご回答ありがとうございましたm(_ _)m
こちらこそご返信ありがとうございます。
解決したようで安心しました。
また何かございましたらお気軽にコメント下さい。よろしくお願いします。