Pythonでギターのフレットから音階を求める

#Pythonでギターのフレットから音階を求める
##はじめに
　前回の「[Pythonでシンセサイザーを作って演奏する。](https://qiita.com/menow2525/items/7f743a68792c05189d78)」の記事にて音の生成については解説をしていますので、ぜひご覧ください。

##ソースコード

```python:checkChord.py
amp = 0.5   #音量
A = 440.0    #A=440Hz
rate = 44100    #サンプリングレート
bpm = 120   #BPM
scoreWave = None
fileName = ""
kArray = ["C", "Cs", "D", "Ds", "E", "F", "Fs", "G", "Gs", "A", "As", "B"]

#音の周波数を計算してsin波を生成する関数
def sinWave_from_key(k, o, v, s, m):
    """
    parameters
    ----------
    k : string
        key in scale
    o : int
        octave
    v : float
        volume
    s : int
        seconds
    t : string
        type
        
    Returns
    ----------
    wave : ndarray
    """
    t = np.arange(0, s, 1 / rate) #時間パラメータ
    wave = 0 * t
    if k in kArray:
        kNum = kArray.index(k)
        kFreq = A * (2 ** ((kNum - kArray.index("A")) / 12)) * (2 ** (o - 3))
        loudness = (amp * v)
        param = 2 * np.pi * kFreq * t
        wave = loudness * np.sin(param)
    return wave

#wav保存
def saveWav():
    name = ""
    for s in fileName:
        if s is ".":
            break
        name += s
    if not fileName is "":
        wavfile.write(name + ".wav", rate, scoreWave)
    else:
        wavfile.write("untitled.wav", rate, scoreWave)

#コードチェック
def checkChord():
    frets = []
    keys = []
    octave = []
    for i in range(6, 0, -1):
        s = ""
        if i is 1:
            s = "1st"
        elif i is 2:
            s = "2nd"
        elif i is 3:
            s = "3rd"
        else:
            s = str(i) + "th"
        print("Please enter the number of the fret on the", s, "string.")
        frets.append(input())
    for i, s in enumerate(frets):
        if s.isdecimal():
            if i is 0:
                keys.append(kArray[(int(s) + 4) % 12])
                octave.append(1 + int((int(s) + 4) / 12))
            elif i is 1:
                keys.append(kArray[(int(s) + 9) % 12])
                octave.append(1 + int((int(s) + 9) / 12))
            elif i is 2:
                keys.append(kArray[(int(s) + 2) % 12])
                octave.append(2 + int((int(s) + 2) / 12))
            elif i is 3:
                keys.append(kArray[(int(s) + 7) % 12])
                octave.append(2 + int((int(s) + 7) / 12))
            elif i is 4:
                keys.append(kArray[(int(s) + 11) % 12])
                octave.append(2 + int((int(s) + 11) / 12))
            elif i is 5:
                keys.append(kArray[(int(s) + 4) % 12])
                octave.append(3 + int((int(s) + 4) / 12))
    wave = None 
    for i in range(len(keys)):
        print(keys[i] + str(octave[i]))
        if wave is None:
            wave = sinWave_from_key(keys[i], octave[i], 100, 1, "default")
        else:
            wave += sinWave_from_key(keys[i], octave[i], 100, 1, "default")
    global scoreWave
    scoreWave = wave
    saveName = ""
    for i in range(len(keys)):
        saveName += keys[i] + str(octave[i])
    global fileName
    fileName = saveName + "."
    saveWav()

#main関数
def main():
    checkChord()

if __name__ is "__main__":
    main()
```

##使い方
```
Please enter the number of the fret on the 6th string.
-
Please enter the number of the fret on the 5th string.
0
Please enter the number of the fret on the 4th string.
2
Please enter the number of the fret on the 3rd string.
2
Please enter the number of the fret on the 2nd string.
1
Please enter the number of the fret on the 1st string.
0
A1
E2
A2
C3
E3
Done! A1E2A2C3E3.wav
Press any key to continue . . .
```
　実行するとコンソールが立ち上がるので、テキストに沿って入力を進めていくだけです。自分もふと忘れるときがあるのですが、ギターの弦は太い方から順に6弦、5弦、4弦...となっているようです。つまり入力は、「TAB譜で下から順に」入力することです。
　
　1弦まで入力が終わったら、コードの成分を表示し、sin波を合成して生成されたコードのwav音源が作成されます。ただしギターの和音のように綺麗な響きではありません。なんとなく音を把握する程度に使ってください。

##解説
　発想はシンプルで、弦を開放で鳴らした音にフレットの数を加算しているだけです。ここでのギターは6弦、ノーマルチューニング(EADGBE)を仮定しています。また、フレットには上限を設けていないため「ネックが無限に長い」ギターになっています。

　弦ごとのキーは単に割り算と剰余で求めることができます。
　あとは前回触れたsin波から音を生成するプログラムを使って音源として保存しています。

##あとがき
　私自身作曲をしたりカバー曲を作ったりしている過程でギターのTAB譜からピアノロールに打ち込む作業があったりして、ギターの経験が長いわけでもないので、その度に1音1音確認しながら作業していたのですが、あまりにも面倒だったため作ることにしました。
　私のような人は少数だと思いますが、ギターの運指と音楽理論を同時に学習したい人や、何気なく弾いたコードがいい感じだったけどどんなコードなのかわからないって人に使ってもらえたらな～とか思ってます。
　Pythonの動く環境でコピペして使ってみてください。