python_wave
Python Wave
音声デバイスの操作
波形ファイルの操作
wave ファイルを読み込んで、別のファイルに書き込む。
numpy / scipy を使わなくてよい方法を知りたいので、試行錯誤する。
とりあえず wave を使ってみる。16bit mono 48KHz sampling を対象としている。
C:\>python
Python 2.6 (r26:66721, Oct 2 2008, 11:35:03) [MSC v.1500 32 bit (Intel)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import wave
>>> a = wave.open("c:/data/A01.wav")
>>> a
<wave.Wave_read instance at 0x00A108C8>
>>> a.getnchannels()
1
>>> a.getsampwidth()
2
>>> a.getframerate()
48000
>>> a.getnframes()
136634
>>> d = a.readframes(a.getnframes())
>>> p = a.getparams()
>>> p
(1, 2, 48000, 136634, 'NONE', 'not compressed')
>>> w = wave.Wave_write()
Exception AttributeError: "Wave_write instance has no attribute '_file'"
...
>>> w = wave.Wave_write("_test.wav")
>>> w.setparams(p)
>>> w.writeframes(d)
>>> w.close()
wave ファイルを作るところだけまとめ直す(2010-09-28追加):
# buf に string として 16KHz サンプリングのバイナリが入っているとする import wave w = wave.Wave_write("_test.wav") p = (1, 2, 16000, len(buf)/2, 'NONE', 'not compressed') w.setparams(p) w.writeframes(buf) w.close()
d は String なので、音声を加工するためには:
>>> data = struct.unpack('%dh' % a.getnframes(), d)
>>> len(data)
136634
>>> data[0:10]
(0, 0, 7, 6, 4, 5, 4, 3, 2, 2)
>>> data[-10:]
(-1, -7, -6, -3, -3, -1, -4, -3, 0, -2)
音声ファイルの振幅を 1/10 にする
#!/usr/bin/python # Takuya Nishimoto import wave import struct import array src_file = "C:/data/A01.wav" a = wave.open(src_file) d = a.readframes(a.getnframes()) p = a.getparams() data = struct.unpack('%dh' % a.getnframes(), d) data2 = [x / 10 for x in data] d2 = array.array('h', data2).tostring() w = wave.Wave_write("_test.wav") w.setparams(p) w.writeframes(d2) w.close()
audioop.mul を使っても同じことができる。 以下、引数で入出力ファイルを指定する。
#!/usr/bin/python # Takuya Nishimoto # usage: # make_wav.py dest.wav src.wav import wave import sys import audioop argvs = sys.argv dest_file = argvs[1] src_file = argvs[2] a = wave.open(src_file) d = a.readframes(a.getnframes()) p = a.getparams() d2 = audioop.mul(d, 2, 0.1) w = wave.Wave_write(dest_file) w.setparams(p) w.writeframes(d2) w.close()
sox でやるような nohead ファイル(拡張子 .sw)との相互変換。
#!/usr/bin/python # Takuya Nishimoto # usage: wav2sw.py src.wav dest.sw # equiv: sox src.wav dest.sw import wave import sys argvs = sys.argv src_file = argvs[1] dest_file = argvs[2] a = wave.open(src_file) d = a.readframes(a.getnframes()) p = a.getparams() w = open(dest_file, 'wb') w.write(d) w.close()
#!/usr/bin/python # Takuya Nishimoto # usage: sw2wav.py 48000 src.sw dest.wav # equiv: sox -r 48000 src.sw dest.wav import wave import sys argvs = sys.argv rate = int(argvs[1]) src_file = argvs[2] dest_file = argvs[3] w = open(src_file, 'rb') d = w.read() w.close() size = len(d) / 2 a = wave.open(dest_file, 'w') p = a.setparams( (1, 2, rate, size, 'NONE', '') ) d = a.writeframes(d)
バイトオーダーを指定してタプルに変換する(<はリトルエンディアン、>はビッグエンディアン)
>>> import wave
>>> a = wave.open('FAK_3Z82A.wav','r')
>>> s = a.readframes(10)
>>> import struct
>>> t = struct.unpack('<10h', s)
>>> t
(-5, -6, -8, -7, -4, -5, -3, -1, -6, -4)
>>> t = struct.unpack('>10h', s)
>>> t
(-1025, -1281, -1793, -1537, -769, -1025, -513, -1, -1281, -769)
>>>
タプルのかわりに array を使う
>>> import array
>>> ar = array.array('h')
>>> ar.fromstring(s)
>>> ar
array('h', [-5, -6, -8, -7, -4, -5, -3, -1, -6, -4])
numpy.array を使う:
>>> import wave
>>> import numpy as np
>>> a = wave.open("hoge.wav")
>>> d = a.readframes(a.getnframes())
>>> x = np.frombuffer(d, dtype="int16")
>>> print(x)
[-2563 -2624 -2608 ..., 144 244 -187]
>>> np.amax(x)
16401
>>> np.amin(x)
-16452
python_wave.txt · 最終更新: 2015/09/18 20:37 by Takuya Nishimoto
