-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathabctoguitar.py
executable file
·187 lines (160 loc) · 4.89 KB
/
abctoguitar.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
#!/usr/bin/env python3
# Convert simple ABC files into guitar notation.
import pyabc
import argparse
def get_args():
# Get Import args
parser = argparse.ArgumentParser(
description="Take and ABC file and render possible guitar tabs")
parser.add_argument("input", type=str,
help="An ABC file to feed to this script.")
parser.add_argument(
"--output", "-o",
type=str,
default=None,
help=(
"Name for output file. If unset will replace *.abc"
" with *.tab"
)
)
parser.add_argument(
"--maxfret", "-x",
type=int,
default=5,
help="The highest fret to allow use of. Default is 5th."
)
parser.add_argument(
"--minfret", "-m",
type=int,
default=0,
help="the lowest fret you wish to use. Default is 0."
)
parser.add_argument(
"--testmode",
action="store_true",
help="turns on verbose printing out output"
)
parser.add_argument(
"--transpose", '-t',
type=int,
default=0,
help=('Number of octaves to transpose')
)
parser.add_argument(
"--tuning",
type=str,
choices=["EADGBE", "DADGBE"],
default='DADGBE',
help="Guitar tunings."
)
args = parser.parse_args()
return args
def output_filename(input_filename, output_filename=None):
# Creates a sensible filename for programme output
# @TODO refactor to not need all args.
if output_filename:
return output_filename
else:
if input_filename[-4:].lower() == ".abc":
return input_filename[:-4] + ".tab"
else:
return input_filename + ".tab"
# Setup the Tuning
DADGAD = [pyabc.Pitch('D', -1),
pyabc.Pitch('A', -1),
pyabc.Pitch('D', 0),
pyabc.Pitch('G', 0),
pyabc.Pitch('A', 0),
pyabc.Pitch('D', 1)]
DADGAD.reverse()
EADGBE = [pyabc.Pitch('E', -1),
pyabc.Pitch('A', -1),
pyabc.Pitch('D', 0),
pyabc.Pitch('G', 0),
pyabc.Pitch('B', 0),
pyabc.Pitch('E', 1)]
EADGBE.reverse()
TUNINGS = [EADGBE, DADGAD]
def setup_strings(tuning, maxfret=5, minfret=0):
"""
Create a data structure representing all the playable notes
Args:
tuning (list of pyabc.Pitch):
representing all the strings 0th fret note
maxfret (int):
the highest fret the guitarist is willing to use
minfret (int):
the lowest fret the guitarist is willing to use.
@TODO -not yet implemented
Returns:
strings (dict):
Nested dictionaries wit the form:
{string: {fret: note_int}}
"""
strings = {}
for i, string in enumerate(tuning):
frets = {}
for fret in range(minfret, maxfret):
frets[fret + string.abs_value] = fret
strings[i + 1] = frets
return strings
def main():
args = get_args()
# Open input file
with open(args.input, 'r') as fhandle:
RAW_TUNE = fhandle.read()
# Parse the tune using pyabc
try:
tune = pyabc.Tune(RAW_TUNE)
except KeyError:
tune = pyabc.Tune("X:0\n" + RAW_TUNE)
if args.tuning == 'EADGBE':
tuning = EADGBE
else:
tuning = DADGAD
strings = setup_strings(tuning, args.maxfret, args.minfret)
# Memoize this?
possible_tabs = []
for note in tune.tokens:
if type(note) == pyabc.Beam:
x = [note._text for i in range(6)]
possible_tabs.append(x)
elif type(note) != pyabc.Note:
pass
else:
note.octave += args.transpose
options = []
for gstring in strings.values():
if note.pitch.abs_value in gstring.keys():
options.append("{}".format(gstring[note.pitch.abs_value]))
else:
options.append("")
possible_tabs.append(options)
import numpy as np
notation = np.array(possible_tabs).T
# print(notation)
str_outs = []
for line in notation:
str_out = ''
for i in line:
if len(i) == 0:
str_out += ("----")
else:
str_out += f"-{i:2s}-"
bars = [bar for bar in str_out.split('|')]
bargroups = []
for i in range(0, len(bars), 4):
bargroups.append('|' + '|'.join(bars[i: i+4]) + '|')
str_outs.append(bargroups)
# Finsh off and write a file, if that's what's been asked for.
final_out = str(np.array(str_outs).T)
if args.output:
with open(args.output, 'w') as fhandle:
fhandle.write(final_out)
else:
with open(output_filename(args.input, args.output), 'w') as fhandle:
fhandle.write(final_out)
if args.testmode:
print(final_out)
if __name__ == '__main__':
main()