#Pythonでギターのフレットから音階を求める
##はじめに
前回の「Pythonでシンセサイザーを作って演奏する。」の記事にて音の生成については解説をしていますので、ぜひご覧ください。
##ソースコード
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の動く環境でコピペして使ってみてください。