31
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PythonのWaveモジュールを使ってwavファイルを編集する

Last updated at Posted at 2017-06-06

こんにちはみなさん

Pythonにはwaveモジュールっていうのが標準でついているようで、こいつを使うことでwavファイルを読み込んだり書き込んだりできるようです。
今回は、そいつを使って長いwavファイルに対して後半を切り取った短めのwavファイルを作るようなプログラムを組んで遊んでみましょう。

環境準備

私はPHPerなので、python環境の用意の仕方なんてようわからんのですが、よく使っているkeras入りのdockerイメージがあったので、こいつを使っちゃいます。(かなり重いけど)
https://hub.docker.com/r/gw000/keras-full/

また、当然ファイルを作ってコンソールで繰り返し動かすような根性を持っているわけではないので、jupyterをササッと起動させてブラウザ経由で動かすします。

$ docker run --rm -v `pwd`/src:/srv -v `pwd`/data:/data -p 8888:8888 -p 6006:6006 -m 2g gw000/keras-full

メモリが心配だったので、念のため2GB確保しています。
あとは、
http://127.0.0.1:8888
にブラウザでアクセスすれば、jupyterが動いているので、パスワード[ keras ]を入れて、はじめちゃいます。

wavの読み込み

準備が完了したので、早速waveファイルを読み込んで、その情報を取得してみましょう。
jupyter上で以下のように入力します。

import wave
import struct
from scipy import fromstring, int16

# ファイルを読み出し
wavf = '/data/input/test.wav'
wr = wave.open(wavf, 'r')

# waveファイルが持つ性質を取得
ch = wr.getnchannels()
width = wr.getsampwidth()
fr = wr.getframerate()
fn = wr.getnframes()

print("Channel: ", ch)
print("Sample width: ", width)
print("Frame Rate: ", fr)
print("Frame num: ", fn)
print("Params: ", wr.getparams())
print("Total time: ", 1.0 * fn / fr)

# waveの実データを取得し、数値化
data = wr.readframes(wr.getnframes())
wr.close()
X = fromstring(data, dtype=int16)

一旦ここまでで実行してみます。

Channel:  2
Sample width:  2
Frame Rate:  44100
Frame num:  15884224
Params:  _wave_params(nchannels=2, sampwidth=2, framerate=44100, nframes=15884224, comptype='NONE', compname='not compressed')
Total time:  360.18648526077095

こんな結果が出力されます。
Channelが2になっているので、このファイルがステレオになっていることがわかります。
また、Total timeが360秒 = 6分と、わりと長めのファイルになっていることがわかります。

waveへの書き出し

次に読み出した内容を頭から90秒だけ取り出したものを別のファイルとして書き出してみましょう。

# 90秒分に相当するフレーム数を算出
time = 90
frames = int(ch * fr * time)

# 出力データを生成
outf = '/data/output/test.wav'
Y = X[:frames]
outd = struct.pack("h" * len(Y), *Y)

# 書き出し
ww = wave.open(outf, 'w')
ww.setnchannels(ch)
ww.setsampwidth(width)
ww.setframerate(fr)
ww.writeframes(outd)
ww.close()

こんな感じです。
チャンネルが複数あると、その分必要なフレーム数が増えるので、それを考慮してあります。
で、出力データを再度文字列の形式に直してから、読み出し時と同じパラメータを指定して書き出しているっていう感じですね。
で、実際にファイルができたかを見ると、

スクリーンショット 2017-06-06 13.53.56.png

できてるみたいです。

まとめ

今回はPythonの標準モジュールであるwaveを使ってwavファイルを直接編集するやり方を調べてみました。
だからなんだって話ですが。。。

今回はこんなところです。

参考

http://yukara-13.hatenablog.com/entry/2013/11/09/103848
http://denshi.blog.jp/signal_processing/python/save_sine_wave

31
25
3

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
31
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?