それほど続きというわけでもなく。
1 import os
2 import struct
3 import itertools
4 import wave
5 import numpy as np
6
7 if __name__ == '__main__':
8 import argparse
9 parser = argparse.ArgumentParser()
10 parser.add_argument(
11 "mode", choices=[
12 "copy", "reverse", "swaplr", "rdelay",
13 "left2mono", "right2mono",
14 ])
15 parser.add_argument("target")
16 args = parser.parse_args()
17
18 with wave.open(args.target, 'r') as fi:
19 nchannels, width, rate, nframes, _, _ = fi.getparams()
20 onchannels = nchannels
21 raw = np.fromstring(fi.readframes(nframes), dtype=np.int16)
22 if args.mode == "reverse":
23 channels = reversed(raw[::2]), reversed(raw[1::2])
24 elif args.mode == "swaplr":
25 # if nchannels is 1, actualy this swap odd and even.
26 channels = raw[1::2], raw[::2]
27 elif args.mode == "rdelay":
28 delay = rate // 50
29 channels = [
30 np.hstack((raw[::2], np.zeros(delay, dtype=np.int16))),
31 np.hstack((np.zeros(delay, dtype=np.int16), raw[1::2]))]
32 elif nchannels == 1 and args.mode in ("left2mono", "right2mono"):
33 channels = (raw,)
34 elif args.mode == "left2mono":
35 channels = (raw[::2],)
36 onchannels = 1
37 elif args.mode == "right2mono":
38 channels = (raw[1::2], )
39 onchannels = 1
40 else:
41 channels = raw[::2], raw[1::2]
42
43 with wave.open(os.path.splitext(args.target)[0] + "_" + args.mode + '.wav', 'w') as fo:
44 fo.setparams((onchannels, width, rate, 0, 'NONE', 'not compressed'))
45 pcm = list(itertools.chain.from_iterable(zip(*channels)))
46 packed = struct.pack('h' * len(pcm), *pcm)
47 fo.writeframes(packed)
入力 wav を逆再生 wav にしたりとか…「色々出来るぜ、格調高いぜ」と思った人はご愁傷様。よーく読むとわかるんだけれど、元データの「加工」やフィルタの類を一切トライしてない。ゆえにこれを発展させようと思うもんなら、知識がない人は即座に挫折する。
なんでこんなことになってるかといえば、「元データの「加工」やフィルタの類」の高等なことでごにょごにょやってたらわけわかんなくなってきたので、先に「基本垂れ流し(左から右へ受け流す、てやつ)」の基礎だけそれなりに綺麗な例が「ワタシが」欲しかっただけ。のでこのスクリプトの「機能」は実は単に「ステレオチャンネルの扱いに必要な基本的な操作だけは多少のバリエーションを踏まえる」てだけで派生したもの。
ところで wav ファイルのサンプルデータそのものが、直接は手に入りにくい時代だけれど、mp3 やら mp4 なら手に入るでしょ、なので ffmpeg とかで wav に出来る:
1 me@host: ~$ ffmpeg -i downloaded.mp4 -acodec pcm_u8 -ar 44100 out.wav
みたいに。