Python の wave モジュール例の殴り書き(2)

先に。一つ前、最初の投稿で間違っちゃったので、追記見てないなら見といて。

今回も、ひとさまに何かを伝える気は毛頭ない、ぶっきらぼうですまん、な記事。

であ:

hoge.py
 1 import math
 2 import wave
 3 import numpy as np
 4 
 5 _SCALES_L = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
 6 
 7 def _nn2scale(d):
 8     sc = int(d) % 12
 9     oc = int(d / 12) - 2
10     return oc, _SCALES_L[sc]
11 
12 def _freq2nn(f):
13     """
14     frequency to note number.
15 
16     Converting from frequency (f) midi note number (d) is given by the following formula:
17 
18     .. math::
19 
20         d = 69 + 12 \log_2 \left( \frac{f}{440 [Hz]} \right)
21 
22     See `MIDI tuning standard <https://en.wikipedia.org/wiki/MIDI_tuning_standard>`_.
23     """
24     return round(69 + 12 * math.log2(f / 440.))
25 
26 def _freqdomain(sig, rate):
27     fft = np.abs(np.fft.fft(sig))
28     freq = np.fft.fftfreq(len(fft), 1.0 / rate)
29     return freq[:len(freq) // 2], fft[:len(fft) // 2]
30 
31 with wave.open('test_CEG.wav', 'r') as fi:
32     rate = fi.getframerate()
33     _ = np.fromstring(fi.readframes(fi.getnframes()), dtype=np.int16)
34     stereo = _[::2], _[1::2]
35 
36 for i in range(0, len(stereo[0]), rate):
37     x = [stereo[0][i:i + rate], stereo[1][i:i + rate]]
38     f, y = [[], []], [[], []]
39     (f[0], y[0]), (f[1], y[1]) = _freqdomain(x[0], rate), _freqdomain(x[1], rate)
40     chord = [set(), set()]
41     for j in range(len(f)):
42         w = np.where(np.divide(y[j], y[j].max() / 100) > 60)
43         f[j], y[j] = f[j][w], y[j][w]
44         for i in range(len(y[j])):
45             chord[j].add(_nn2scale(_freq2nn(f[j][i])))
46     print(chord)

test_CEG.wav は 一つ前 ので作ったヤツ。

 1 me@host: ~$ /c/Python35/python hoge.py
 2 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'C')}]
 3 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'E')}]
 4 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'G')}]
 5 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'E')}]
 6 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'C')}]
 7 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'C')}]
 8 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'C')}]
 9 [{(5, 'C'), (5, 'E'), (5, 'G')}, {(6, 'C')}]
10 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'D')}]
11 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'F')}]
12 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'A')}]
13 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'F')}]
14 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'D')}]
15 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'D')}]
16 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'D')}]
17 [{(5, 'D'), (5, 'F'), (5, 'A')}, {(6, 'D')}]

前回の「わかったつもりになったこと」の単なる発展形。周波数ドメインに分解すればスケールに戻せるでしょう、と。それだけのこと。