Pythonで信号処理をした後に、音楽としてwavファイル形式で保存したい時があります。ここでは、PythonのPySoundFileを使ってモノラルとステレオの両方のwavを作成する方法を紹介します。
こんにちは。wat(@watlablog)です。
wavファイルは大変便利ですが、データタイプにはモノラルやステレオといった形式があります!ここでは、Pythonでモノラルとステレオの両方のwavファイルを保存する方法を紹介します!
wavファイルのモノラルとステレオ概要とPySoundFileについて
wavファイルのおさらい
当WATLABブログでは過去にwavファイルを読み込み波形表示をする所までのコードを「PythonのPySoundFileでwavファイル波形表示」という記事で紹介しました。
wavファイルとは、音声を録音したファイルとして既に世間で有名なファイル形式ですが、計測の現場でも互換性・ソフト間データの橋渡しの観点からかなり重宝されているファイルということは上記記事で説明した通りです。
たいていの商用計測ソフト(FFTアナライザやデータロガー)はwavに変換する機能を持つのではないでしょうか?
上記記事ではモノラルのwavファイルしか扱っていないのですが、実はwavファイルにはモノラルとステレオといった形式が存在します。
実際にPythonコードを紹介する前に、軽く両者の違いについて触れてみます。
モノラルとステレオのwavファイルの中身を見てみる
百聞は一見にしかず、ということで、モノラルとステレオのwavファイルとはどういうものかをグラフを用いて説明します。
まずはモノラルのwav波形を下図に示します。モノラルはmono(1つの)という意味通り波形が1つだけ入っています。
続いてステレオのwav波形を下図に示します。ステレオの場合は2つの波形があることが特徴です。
グラフに書いてある「L」と「R」はそれぞれ左と右を意味しています。LとRを別々に再生する機器や、両方を均等に再生する機器等色々ありますね。
wavファイルを使った信号処理には、モノラルかステレオかという形式の違いはプログラミングそのものに影響する要素なので、よく把握しておこう!
wavファイルの取り扱いはPySoundFileが楽
wavファイルの概要や形式を理解したので、早速プログラミングコードの紹介をしたいと思います。
今回、wavファイルの取り扱いはPySoundFileというライブラリパッケージを使います。
PySoundFileを使う理由は「初心者にやさしく使いやすい」からです。
例えば、Pythonにはwaveというライブラリもwavファイルの取り扱いができますが、僕が使っている範囲内ではPySoundFileの方がコードが少なくなる特徴があります。
もちろん特殊なケースではwaveに軍配があがる場合もあると思いますが、今回はPySoundFileでサクっとプログラミングをしていきたいと思います。
Pythonでモノラルのwavファイルを保存するコード
まず始めにモノラルのwavファイルを保存するコードを紹介します。モノラルの場合はとても簡単で、以下のコードはチャープ信号をPython上で生成して、その信号をwavファイルに保存しているものです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import soundfile as sf from scipy.signal import chirp import numpy as np import matplotlib.pyplot as plt # サンプル波形を生成(チャープ信号) samplerate = 44100 # サンプリングレート ts = 0 # 信号の開始時間 tf = 4 # 信号の終了時間 t = np.linspace(ts, tf, tf * samplerate) # 時間軸を作成 L = chirp(t, f0=10, f1=5000, t1=10, method='linear') # 縦軸を作成 # モノラルのwavファイルを保存 sf.write('mono.wav', L, samplerate) # ここからグラフ描画 # フォントの種類とサイズを設定する。 plt.rcParams['font.size'] = 14 plt.rcParams['font.family'] = 'Times New Roman' # 目盛を内側にする。 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' # グラフの上下左右に目盛線を付ける。 fig = plt.figure() ax1 = fig.add_subplot(111) ax1.yaxis.set_ticks_position('both') ax1.xaxis.set_ticks_position('both') # 軸のラベルを設定する。 ax1.set_xlabel('Time [s]') ax1.set_ylabel('L') # データプロット。 ax1.plot(t, L) # レイアウト設定 fig.tight_layout() # グラフを表示する。 plt.show() plt.close() |
信号さえ出来てしまえばたった1行でモノラルのwavファイルが保存できてしまいました。
参考までに、保存されたwavファイルの音声を以下に載せました。
※注意:再生ボタンをクリックすると音が出ます。
Pythonでステレオのwavファイルを保存するコード
次にステレオのwavファイルを以下に示します。
信号生成部分で2つの波形LとRを作っています。このLとRは左と右を意味しています。Lは時間と共に信号の周波数が増加しますが、RはLの信号を反転させたものなので、時間と共に周波数が減少する波形です(音が干渉して変にならないように音量を半分にしています)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
import soundfile as sf from scipy.signal import chirp import numpy as np import matplotlib.pyplot as plt # サンプル波形を生成(チャープ信号) samplerate = 44100 # サンプリングレート ts = 0 # 信号の開始時間 tf = 4 # 信号の終了時間 t = np.linspace(ts, tf, tf * samplerate) # 時間軸を作成 L = chirp(t, f0=10, f1=5000, t1=10, method='linear') # 1チャンネル目の縦軸を作成 R = np.flip(L) / 2 # 2チャンネル目の縦軸を作成 wave = np.array([L, R]) # チャンネル1と2を結合 wave = wave.T # 多チャンネルwav形式に変換(転置) # ステレオのwavファイルを保存 sf.write('stereo.wav', wave, samplerate) # ここからグラフ描画 # フォントの種類とサイズを設定する。 plt.rcParams['font.size'] = 14 plt.rcParams['font.family'] = 'Times New Roman' # 目盛を内側にする。 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' # グラフの上下左右に目盛線を付ける。 fig = plt.figure() ax1 = fig.add_subplot(211) ax1.yaxis.set_ticks_position('both') ax1.xaxis.set_ticks_position('both') ax2 = fig.add_subplot(212) ax2.yaxis.set_ticks_position('both') ax2.xaxis.set_ticks_position('both') # 軸のラベルを設定する。 ax1.set_xlabel('Time [s]') ax1.set_ylabel('L') ax2.set_xlabel('Time [s]') ax2.set_ylabel('R') # データプロット。 ax1.plot(t, L) ax2.plot(t, R) # レイアウト設定 fig.tight_layout() # グラフを表示する。 plt.show() plt.close() |
ステレオでもwavファイルを保存するコードはモノラルと同様にたった1行ですが、データの形を整えるため前処理をしています。
モノラルの場合は生成した波形をそのまま保存すればよかったのですが、ステレオデータの場合はデータをリストでまとめた後に以下の図のように転置する必要があります。
ちなみに、このフォーマットのことはPySoundFileの公式ドキュメントに書いてありました。
Examples
>>> from soundfile import SoundFile>>> myfile = SoundFile('stereo_file.wav')
>>> myfile.read(3)array([[ 0.71329652, 0.06294799], [-0.26450912, -0.38874483],
[ 0.67398441, -0.11516333]])
PySoundFile:https://pysoundfile.readthedocs.io/en/0.9.0/
参考までに、保存されたwavファイルの音声を以下に載せました。2つの信号が同時再生されていることがわかります。
※注意:再生ボタンをクリックすると音が出ます。
この方法を覚えれば、実験データを多チャンネルのwavファイルに変換することもできそうですね。
まとめ
本記事ではモノラルとステレオのwavファイルの概要を説明し、PythonのPySoundFileを使ってそれぞれの形式のwavファイルを保存する方法を紹介しました。
wavファイルの保存方法や多チャンネルwavの作成方法がわかりました!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!
コメント