In version 2.19.x, how can I make LilyPond decide whether – and by how much – to transpose up or down, depending on a target octave/range for one of the transposed notes (I'll call that note the "reference note")?
All the other notes are to be transposed in the same direction and by the same amount as the reference note, so a single LilyPond
\transpose command will handle all of the transposed music.
Use case: I want to make a set of chord voicings, each in multiple transpositions, with the lowest note of each transposed voicing always within a specified octave, say between
b (the octave below middle C in LilyPond notation). This would require some sort of conditional (in concept, something like: "try transposing the chord down; if the lowest note of the downward transposition is too low, transpose up").
Added to clarify (?) the goal: Typically chord voicings are fairly tight, with separations between the notes of no more than a 6th and usually less, but the solution shouldn't be based on the distance (or any other relationship) between the notes being transposed. I just want to pick a note in the chord/music as the reference note, choose a transposition key/note name, and define a range into which the transposed note must fall after transposition. LilyPond/Scheme would take over to figure out the details of the
\transpose command, up or down by how many octaves, and would apply that command to the entirety of the original subject 'chunk' of music. The result would be that the entire chunk – including the reference note and all the other notes therein – would be transposed by the same amount and in the same direction. The reference note is the only one that must fall in the specified range. In the typical case, you want a chord voicing that is not too low to be muddy, but as low as you can get it so it stays more or less out of the way of the melody. There. Please feel free to improve on/simplify this description of what I'm looking for.
I can't find any relevant snippets in the LilyPond snippet library. There is one discussion of conditional transposing I found via a Google search but the Scheme code is opaque to me--with the sparse comments I can't even understand what the original poster was trying to accomplish, much less the proposed solution. And it gave me an error when I tried to run it using the sample LilyPond music passage ("input") (see below). To be clear, since I can't follow the Scheme in that link, I'm not sure how – or if – the code is relevant to my problem, other than that both involve some sort of conditional transposition.
Parsing...C:...tmpdocument.ly:7:3: In procedure ly:music-set-property! in expression ((setter ly:music-property) (quote from-to) music ...):
C:...tmpdocument.ly:7:3: Wrong type argument in position 1 (expecting Prob): from-to
I can imagine a fairly general approach that takes any specified note in a series as the reference point for the up/down decision, but for this purpose the reference note will always be the first one in the chord, for example the
c in the C major
< c e g > triad.
Edit/addition: Since I first posted, I've figured out working logic for transposing to a range. A condition is involved, but not the one I originally imagined. Here's Python code implementing that logic, based on numeric values for pitches:
# find same note at a different octave, ie in specified range
starting_pitch = 67 # these values are just examples
bottom_of_range = 48 # 'c' in Lilypond, C below middle C
top_of_range = 59 # # Lilypond 'b'
octave_delta_from_bottom = -((starting_pitch - bottom_of_range) // 12)
octave_delta_from_top = (-(starting_pitch - top_of_range)) // 12
#round up by negating the numerator
if octave_delta_from_bottom == octave_delta_from_top:
transposed_note = starting_pitch + (octave_delta_from_bottom *12)
print ("target note not in specified range.")