-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGF.py
194 lines (174 loc) · 8.17 KB
/
GF.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
"""
'GF' refers to Guitar Fingering, it works in module GCPG.
This module defines all the available fingerings in guitar playing, which is used by GCPG.
"""
import itertools
import chorder
"""
This function defines a dictionary of barre chord's finger types and its range.
该函数定义全封闭和弦指法组,返回所有可能的和弦
Attention:
the subset of finger type set, which can be regarded as half barre chord, is not included in the set.
注意:
可以看作半封闭和弦的指法组子集(即有从6弦开始,有连续的,没演奏的弦),是不被包含在这个和弦指法组内的。
"""
def barre_chord(tuning_type, capo_character=0, span_tolerance=7):
"""
:param tuning_type: Tuning type, which could be predefined in GCPG.
:param capo_character: Capo character, which could be predefined in GCPG.
:param span_tolerance: The tolerance of span in circle of fifth, the smaller it is, the more harmonic chords are.
:return: Available barre chords' list.
"""
# 初始化和弦指法组和数组
finger_type_set = []
# 先定义没有演奏的弦
unplayed_string = None
# 通过排列组合生成所有的和弦指法组
for e in itertools.product([2, 1, 0, unplayed_string], repeat=6):
# 初始化计数器(递归计算没有手指摁弦的弦数,计算空弦数)
cal_no_finger = 0
cal_empty_string = 0
for n in e:
if n == 0 or n == unplayed_string:
cal_no_finger += 1
if n == unplayed_string:
cal_empty_string += 1
# 加入到指法组的条件:用到三个以下的手指;和弦音符数量 >= 4;6弦有音符
if cal_no_finger > 2 \
and cal_empty_string < 3 \
and e[0] != unplayed_string:
finger_type_set.append(e)
# 将指法组改为和弦组
available_cg_6 = []
for ft in finger_type_set:
# 初始化要导出的和弦
chord = []
# 从指法组向和弦内添加音符
for i in range(len(ft)):
if ft[i] is not None:
chord.append(tuning_type[i] + ft[i])
# 创建chorder中的Chord实例
chord1 = chorder.Chord(chord)
# 用chorder中的方法判断音集是否有两个以上的小二度,用c_span方法判断其和谐程度:
if chord1.semitone_num < 2 \
and chord1.span <= span_tolerance\
and chord[1] - chord[0] > 2 \
and chord[2] - chord[1] > 2:
# 依次升高12品,将得到的和弦加入和弦组
for ii in range(capo_character, 12):
available_cg_6.append(list(note + ii for note in chord))
return available_cg_6
# TODO: span_tolerance的截取方法有待优化,详情见 chorder 文件的 class Chord。
def five_barre_chord_fts(tuning_type, capo_character=0, span_tolerance=7):
"""
:param tuning_type: Tuning type, which could be predefined in GCPG.
:param capo_character: Capo character, which could be predefined in GCPG.
:param span_tolerance: The tolerance of span in circle of fifth, the smaller it is, the more harmonic chords are.
:return: Available five-strings' half barre chords' list.
"""
# 初始化和弦指法组和数组
finger_type_set = []
# 先定义没有演奏的弦
unplayed_string = None
# 通过排列组合生成所有的和弦指法组
for e in itertools.product([2, 1, 0, unplayed_string], repeat=5):
# 初始化计数器(递归计算没有手指摁弦的弦数,计算空弦数)
cal_no_finger = 0
cal_empty_string = 0
for n in e:
if n == 0 or n == unplayed_string:
cal_no_finger += 1
if n == unplayed_string:
cal_empty_string += 1
# 加入到指法组的条件:用到三个以下的手指;和弦音符数量 >= 4;5弦有音符
if cal_no_finger > 2 \
and cal_empty_string < 3 \
and e[0] != unplayed_string:
finger_type_set.append(e)
# 将指法组改为和弦组
available_gc = []
for ft in finger_type_set:
# 初始化要导出的和弦
chord = []
# 从指法组向和弦内添加音符
for i in range(len(ft)):
if ft[i] is not None:
chord.append(tuning_type[i + 1] + ft[i])
for ii in range(capo_character, 12):
chord0 = (list(note + ii for note in chord))
chord0.append(tuning_type[0] + capo_character)
chord0 = sorted(chord0)
# 创建chorder中的Chord实例
chord1 = chorder.Chord(chord0)
# 用chorder中的方法判断音集是否有两个以上的小二度,用c_span方法判断其和谐程度:
if chord1.semitone_num < 2 \
and chord1.span <= span_tolerance \
and chord0[1] - chord0[0] > 2 \
and chord0[2] - chord0[1] > 2:
available_gc.append(chord0)
return available_gc
def four_barre_chord_fts(tuning_type, capo_character=0, span_tolerance=7):
"""
:param tuning_type: Tuning type, which could be predefined in GCPG.
:param capo_character: Capo character, which could be predefined in GCPG.
:param span_tolerance: The tolerance of span in circle of fifth, the smaller it is, the more harmonic chords are.
:return: Available four-strings' half barre chords' list.
"""
# 初始化和弦指法组和数组
finger_type_set = []
# 先定义没有演奏的弦
unplayed_string = None
# 通过排列组合生成所有的和弦指法组
for e in itertools.product([2, 1, 0, unplayed_string], repeat=4):
# 初始化计数器(递归计算没有手指摁弦的弦数,计算空弦数)
cal_no_finger = 0
cal_empty_string = 0
for n in e:
if n == 0 or n == unplayed_string:
cal_no_finger += 1
if n == unplayed_string:
cal_empty_string += 1
# 加入到指法组的条件:用到三个以下的手指;和弦音符数量 >= 4;5弦有音符
if cal_no_finger > 2 \
and cal_empty_string < 3 \
and e[0] != unplayed_string:
finger_type_set.append(e)
# 将指法组改为和弦组
available_gc = []
for ft in finger_type_set:
# 初始化要导出的和弦
chord = []
# 从指法组向和弦内添加音符
for i in range(len(ft)):
if ft[i] is not None:
chord.append(tuning_type[i + 2] + ft[i])
for ii in range(capo_character, 12):
chord0 = (list(note + ii for note in chord))
chord0.append(tuning_type[0] + capo_character)
chord0.append(tuning_type[1] + capo_character)
chord0 = sorted(chord0)
# 创建chorder中的Chord实例
chord1 = chorder.Chord(chord0)
# 用chorder中的方法判断音集是否有两个以上的小二度,用c_span方法判断其和谐程度:
if chord1.semitone_num < 2 \
and chord1.span <= span_tolerance \
and chord0[1] - chord0[0] > 2 \
and chord0[2] - chord0[1] > 2:
available_gc.append(chord0)
return available_gc
def other_finger_types(tuning_type, capo_character, span_tolerance=7):
"""
:param tuning_type: Tuning type, which could be predefined in GCPG.
:param capo_character: Capo character, which could be predefined in GCPG.
:param span_tolerance: The tolerance of span in circle of fifth, the smaller it is, the more harmonic chords are.
:return: Available none-barred chords' list.
"""
return
if __name__ == "__main__":
g6 = barre_chord([40, 45, 50, 55, 59, 64], 5)
g5 = five_barre_chord_fts([40, 45, 50, 55, 59, 64], 5)
g4 = four_barre_chord_fts([40, 45, 50, 55, 59, 64], 5)
print(g4)
print(len(g6))
print(len(g5))
print(len(g4))