Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
24
Help us understand the problem. What is going on with this article?
@niisan-tokyo

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

More than 3 years have passed since last update.

こんにちはみなさん

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

24
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
niisan-tokyo
流行りに微妙に遅れてついていく、エンジニア9年生です。
roxx
人材紹介業むけプラットフォーム「agent bank」、リファレンスチェックサービス「back check」を運営。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
24
Help us understand the problem. What is going on with this article?