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