先に。一つ前、最初の投稿で間違っちゃったので、追記見てないなら見といて。
今回も、ひとさまに何かを伝える気は毛頭ない、ぶっきらぼうですまん、な記事。
であ:
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')}]
前回の「わかったつもりになったこと」の単なる発展形。周波数ドメインに分解すればスケールに戻せるでしょう、と。それだけのこと。