Add abcrange.py to return the range of a tune, and use it in instrument transposition.
This lets us transpose on boundaries that aren't octave boundaries.
This commit is contained in:
parent
0bea7c9b59
commit
e26974292c
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# 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 about ('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():
|
||||
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)
|
16
makeCello.sh
16
makeCello.sh
|
@ -1,6 +1,7 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copy a booke to cello-friendly form. Bass clef, transposed down 2 octaves.
|
||||
# Copy a booke to cello-friendly form. Bass clef, transposed down
|
||||
# 1 or 2 octaves.
|
||||
#
|
||||
# It would be easier to do with transpose in dottes.fmt, but I can't get
|
||||
# that to work properly for a 2 octave downward transpose.
|
||||
|
@ -12,6 +13,12 @@ if [ $# != 1 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Transpose down (return 0) if bottom note was < C.
|
||||
transposedowntwo()
|
||||
{
|
||||
return $(($3 >= 100))
|
||||
}
|
||||
|
||||
dir=`pwd`
|
||||
|
||||
booke=$dir/$1
|
||||
|
@ -27,13 +34,16 @@ echo "Cello" > $outdir/instrument.txt
|
|||
find $booke -name "*.abc" | sort |
|
||||
while read filename
|
||||
do
|
||||
name=`basename $filename .abc`
|
||||
range=`./abcrange.py $filename`
|
||||
|
||||
# Move down either one octave or two, depending on the range
|
||||
# of the tune. If there are any notes below middle C, transpose
|
||||
# down one octave. The default is to transpose down two octaves.
|
||||
middle="d"
|
||||
if grep -v "^[A-Z]:" $filename | sed -e 's/"[^"]*"//g' | grep -q "[A-Z],"; then
|
||||
if transposedowntwo $range; then
|
||||
middle="D"
|
||||
fi
|
||||
name=`basename $filename .abc`
|
||||
|
||||
sed -e "/^ *K:/s/$/ clef=bass middle=$middle/" $filename > $outdir/$name.abc
|
||||
done
|
||||
|
|
|
@ -7,6 +7,12 @@ if [ $# != 1 ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Transpose down (return 0) if top note was > e (> a for horn).
|
||||
transposedown()
|
||||
{
|
||||
return $(($2 <= 109))
|
||||
}
|
||||
|
||||
dir=`pwd`
|
||||
|
||||
booke=$dir/$1
|
||||
|
@ -23,17 +29,13 @@ find $booke -name "*.abc" | sort |
|
|||
while read filename
|
||||
do
|
||||
name=`basename $filename .abc`
|
||||
tmpfile=$outdir/$name.abc.tmp
|
||||
|
||||
# Strip out guitar chords first. This has the advantage of removing
|
||||
# text with arbitary lower case characters too.
|
||||
sed -e "s/\"[^\"]*\"//g" $filename > $tmpfile
|
||||
range=`./abcrange.py $filename`
|
||||
|
||||
# Transpose concert pitch up a fifth.
|
||||
# If there are any notes at or above C above middle C, transpose
|
||||
# If there are any notes above 'd' (Horn 'g'), transpose
|
||||
# down a seventh instead.
|
||||
transpose=5
|
||||
if grep -v "^[A-Z]:" $tmpfile | sed -e 's/"[^"]*"//g' | grep -q "[a-g]"; then
|
||||
if transposedown $range; then
|
||||
transpose=-7
|
||||
fi
|
||||
|
||||
|
@ -42,7 +44,6 @@ find $booke -name "*.abc" | sort |
|
|||
# output to be in treble clef; some lower tunes with the odd high
|
||||
# note will otherwise appear in bass clef, which is not what this
|
||||
# crap horn player wants.
|
||||
abc2abc $tmpfile -e -t $transpose | \
|
||||
abc2abc $filename -e -t $transpose | \
|
||||
sed -e "/^ *K:/s/$/ clef=treble/" > $outdir/$name.abc
|
||||
rm $tmpfile
|
||||
done
|
||||
|
|
Loading…
Reference in New Issue