This should produce the bookes and website, but the website is not linked into the main page yet.
96 lines
2.4 KiB
Python
Executable File
96 lines
2.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Find the range of a tune. Do minimal parsing of an ABC input file
|
|
# and print the lowest and highest notes therein. Accidentals are
|
|
# ignored.
|
|
#
|
|
# The output is given in purely numeric form, to avoid needing to
|
|
# re-parse it in an external script. A single line is printed with
|
|
# the highest note followed by a space and the lowest note. Middle C ('C') is
|
|
# 100. D an octave above ('d') is 108. D an octave above that ('d'') is
|
|
# 205. D below middle C ('d,') is 94. And so on.
|
|
#
|
|
# For example:
|
|
# $./abcrange.py choon.abc
|
|
# choon.abc: 112 97
|
|
#
|
|
|
|
import sys
|
|
|
|
def process(filename, inf):
|
|
highest = 0
|
|
lowest = 1000
|
|
for line in inf:
|
|
line = line.strip()
|
|
# If it is empty or starts "%", ignore it.
|
|
if len(line) == 0 or line[0] == "%":
|
|
continue
|
|
|
|
# Is it a header line? I.e. does it start LETTER COLON?
|
|
# If so, ignore.
|
|
start = line[:2]
|
|
if len(start) > 1 and start[1] == ":" and (start[0].isalpha() or start[0] == '+'):
|
|
continue
|
|
|
|
# Tune line.
|
|
inchord = False
|
|
note = 0
|
|
notevals = {
|
|
"C": 100,
|
|
"D": 101,
|
|
"E": 102,
|
|
"F": 103,
|
|
"G": 104,
|
|
"A": 105,
|
|
"B": 106,
|
|
"c": 107,
|
|
"d": 108,
|
|
"e": 109,
|
|
"f": 110,
|
|
"g": 111,
|
|
"a": 112,
|
|
"b": 113,
|
|
}
|
|
for c in line:
|
|
if c == "," and note > 0:
|
|
note = note - 7
|
|
continue
|
|
elif c == "'" and note > 0:
|
|
note = note + 7
|
|
continue
|
|
|
|
if note > 0:
|
|
if note > highest:
|
|
highest = note
|
|
if note < lowest:
|
|
lowest = note
|
|
note = 0
|
|
|
|
if c == '"':
|
|
inchord = not inchord
|
|
continue
|
|
if inchord:
|
|
continue
|
|
|
|
if c in notevals:
|
|
note = notevals[c]
|
|
|
|
if note > 0:
|
|
if note > highest:
|
|
highest = note
|
|
if note < lowest:
|
|
lowest = note
|
|
note = 0
|
|
|
|
print("{0}: {1} {2}".format(filename, highest, lowest))
|
|
|
|
if len(sys.argv) > 1:
|
|
for arg in sys.argv[1:]:
|
|
try:
|
|
inf = open(arg, "r")
|
|
process(arg, inf)
|
|
finally:
|
|
inf.close()
|
|
else:
|
|
process("stdin", sys.stdin)
|