Comment #6 on issue 687 by adam.spiers: Enhancement: inequal MIDI
quantization of equal durations (swing, rubato)
http://code.google.com/p/lilypond/issues/detail?id=687
Regarding the previous comment 5 - I agree with both your observations
(although I think that the spec in comment 4 already contained your first
point implicitly). To put it another way:
- It would *not* be sufficient to only displace Note-On MIDI events, nor
even Note-On *and* Note-Off MIDI events.
- It would *not* be sufficient to only displace Note-On/Note-Off MIDI
events corresponding to 8th notes (or 16th notes if we were in an
imaginary "16th note swing mode"), since you could have 8th notes (or 16th
notes) tied to longer notes, or quarter notes or longer starting on the
second 8th note (or 16th note) of the measure. For example, if attempting
to generate 8th note swing,
| r8 a4 b c d8~ | d4. f8~ f2 |
would require displacement of the following events:
- Note-On and Note-Off for 'a4'
- Note-On and Note-Off for 'b4'
- Note-On and Note-Off for 'c4'
- Note-On for 'd8'
- Note-Off for 'd4.'
- Note-On for 'f8'
Therefore one might be tempted to think that for conventional jazz swing at
least, it would be enough to displace any Note-On and Note-Off MIDI events
falling on 8th note boundaries which do not coincide with quarter note
boundaries. However, this is still not sufficient!
Firstly, as correctly observed in the previous comment 5, with 8th note
swing,
| a8 a a a b16 b b b a8 a |
may or may not require the Note-Off/Note-On boundary in between the second
and third 'b' to be displaced. If they are to be displaced, what happens
to the boundaries between the first and second 'b', and between the third
and fourth 'b' ?
Secondly, we still have to deal with other types of MIDI events, such as
Control/Program Change, which are associated with a particular MIDI
channel. Most likely their displacement (if any) would be calculated by
the same treatment that Note-Off and Note-On events receive. (SysEx
messages are another can of worms which hopefully we would not have to
worry about in this context.)
Thirdly, there are other more complex types of swing which would need to be
catered for. For example, the Viennese waltz requires the 2nd beat of a
3/4 measure to be played slightly early, and in every four 16th notes of
samba swing, the second 16th note must be slightly late and the fourth 16th
note must be slightly early. Additionally, one might want every single 8th
note of the solo instrument slightly delayed and every single 8th note of
the bass instrument slightly anticipated, to give a more authentic jazz
ensemble feel.
Fourthly, swing is a function of tempo - it can become more or less
pronounced as the tempo increases.
So to solve this in a manner which is flexible enough to accommodate any
style of swing, we are facing a non-trivial mathematical challenge. Here
is a suggested solution:
A swing style is defined as a list of swing displacements. Each swing
displacement specifies the criteria for which MIDI events it should apply
to, and proportionally by how much time forwards or backwards the
displacement should be made. The criteria for displacement should include
the following:
- The "denominator" note duration, e.g. for 8th note swing, where
displacements only occur on certain 8th note boundaries, this would be 8,
and for 16th note swing it would be 16.
- The repeat count, i.e. after how many of the above note durations does
the swing pattern finish and start repeating itself. For jazz swing it
would be 2, since swing repeats every two 8th (or 16th) notes.
- The "numerator" swing note selector, starting counting from 1, and not
exceeding the repeat count above. For jazz swing it would be 2, since
every second 8th (or 16th) note is displaced.
This could be expressed in Scheme in the following manner:
% Displace every second 8th note to be 20% later
jazzswing8 = #`((8 2 2 20))
% Make the second quarter note in every measure 30% earlier
vienneselilt = #`((4 3 2 -30))
% Make the second 16th note of every four 25% later,
% and the fourth 16th note of every four 25% earlier
sambaswing16 = #`(
(16 4 2 25)
(16 4 4 -25)
)
% Ensemble "feel" examples
jazzswing_lazysax = #`(
(8 2 1 2)
(8 2 2 22)
)
jazzswing_pushingbass = #`(
(8 2 1 -2)
(8 2 2 18)
)
Using simple arithmetic in Scheme, the percentage values could easily be
calculated dynamically as a function of tempo, which solves that problem.
Let us now re-examine this case given above:
| a8 a a a b16 b b b a8 a |
and see how the above jazzswing8 definition would apply to it. Since the
denominator is 8, the Note-Off/Note-On boundary in between the second and
third 'b' would indeed be displaced 20% later. It seems to me that this
should not happen by default, because of the implications on the other 16th
notes. A solution to this would be to make our implementation of
Swing_Performer only displace notes whose start and end *both* fall on
a "swing boundary" as determined by the denominator value. In this
example, the Note-Off for the second 'b' coincides with an 8th note
boundary, but the Note-On does not. Conversely, the Note-On for the
third 'b' does, but the Note-Off does not. Therefore neither note would
incur any displacement, and in fact, none of the four 16th notes in this
example would.
If this displacement *was* required, then it would have to be specified
manually at 16th note granularity, eliminating any doubt regarding how the
swing should be distributed, e.g.
% Displace every second 8th note to be 20% later, and also
% slightly swing 16th notes
jazzswing8 = #`(
( 8 2 2 20)
% This might sound weird!
(16 4 2 10)
(16 4 3 20)
(16 4 4 5)
)
_______________________________________________
bug-lilypond mailing list
bug-lilypond@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-lilypond