Open davidrizo opened 4 years ago
Given the examples in the documentation, when two splines must be merged into one, the *v operator must be used at the end of both spines. Then, the expected encoding should be:
Yes, that is close. But the problem with this line:
*v *v *v *v
*
is that it means to merge all spines into a single one. When you do this:
....
D2 AA2 dd2 f#2
* *v *v *v
= =
*- *-
the right three are merged into the second spine below. The problem is that the original spines were not restored (2:2 goes to 1:3). Technically this allowed in Humdrum, although I avoid this since it is difficult to distinguish from a bug in the data.
The current solution to this is to do each merge on a separate line:
**kern **kern
*staff2 *staff1
*clefF4 *clefG2
*k[f#c#] *k[f#c#]
*D: *D:
*M2/4 *M2/4
*^ *^
G2 BB2 g8L d4
. . a8J .
. . b8L e4
. . cc#8J .
= = = =
D2 AA2 dd2 f#2
* * *v *v
*v *v *
= =
*- *-
Either merge can happen before the other, although collapsing the right-most subspine group first make the visual display of the data a little more complex:
*v *v * *
* *v *v
* *
I do not like this, and I would like to implement a new spine manipulator *V
that would allow merging adjacent spines groups on a single line, where the capitalization indicate a new merge group is starting:
*v *v *V *v
* *
But I have not yet implemented this system (and it would not be backward compatible with the original Humdrum Toolkit). This would improve readability and data processing in certain cases, but would also cause complications when adding/removing spines from a score (where the v/V states may need to change).
In my parser, I could also disallow merging across original spines, then the original case would be as you expected:
*v *v *v *v
* *
Coming from above in the data, I keep track of which primary spine a token belongs two. If I see such a merger where two adjacent tokens are from a different primary spine (which I call a track to avoid confusion between spine/subspine terms), then I could implicitly segment the merges into two separate groups. However, this would make the data incompatible with the original Humdrum Toolkit tools, so I have avoided doing that.
I changed the documentation example to include more complex spining:
**kern **kern
*M4/4 *M4/4
=1 =1
* *^
1E 1cc 4a
. . 4g
* * *^
. . 4f/ 2c\
. . 4e/ .
* *v *v *v
=2 =2
*^ *^
* * * *^
1E 4r 4r 2gg 4d/
. 2EE 2.ccc . 4g
. . . 2ryy 4f
. 8FFL . . 4e
. 8GGJ . . .
* * *v *v *v
*v *v *
=2 =2
1AA; 1f;
== ==
*- *-
And added a paragraph describing the complications:
Note that when the subspines for adjacent staves merge at the same time (at the end of measure 2), then the merges must be staggered for grouping clarity. Also when a spine needs to expand from one to three voices, there must be two
*^
expansions (the first to go from one to two subspines, and the second to go from two to three spines). Also note the use of2ryy
, which is used to delay merging of the spines until the end of the measure (otherwise the two right subspines could merge together before merging with the first subspine for the staff at the end of the measure). Also note that subspines should not be ended before the full duration of the last note in the subspine (so the first two subspines in the top staff in measure 2 can not merge half-way through the measure since the note in the first subspine has not yet finished sounding).
You are writing the duration after pitch in **kern
tokens, such as D2
for a half note on the D below middle C. This is allowed in **kern
data, so there is not real problem, but it makes the data a little more difficult to read, because scientific pitch will use a number after the pitch to indicate the octave. For example C4
in scientific pitch notation means middle C. If you put the rhythm first, such as 2D
, then there is less confusion when viewing the notes out of context. Also, this would allow rhythm and scientific pitch to be mixed easily, such as 2C4
which might mean a half note middle C.
So you can keep putting the rhythm after the pitch without any problems, but there is a "canonical ordering" for **kern
data in the documentation somewhere that says that rhythm-pitch
is preferred over pitch-rhythm
.
Hi, the following case is just a lab experiment, but can be a good example to check the correct collapsing of spines.
In this case there are two main spines that are splitted. VHV just works when all the spines join into one spine.. Shouldn't be at least the three main spines maintained?
**kern **kern **kern
* *^ *
1r 1A 1AA 1a
* * *^ *
2r 2A 2AA 2AA# 2a
*^ *^ *^ *^ *^
4r 4r 4A 4A 4AA 4AA 4AA# 4AA# 4a 4a
*v *v *v *v *v *v *v *v *v *v
8r
*-
I was expecting the last row to have three spines instead the 8r
alone.
Thanks!!
In the original Humdrum Toolkit, all adjacent *v
merge into a single spine. The proper way is to place merges on separate lines when adjacent *v
merge into separate spines:
**kern **kern **kern
* *^ *
1r 1A 1AA 1a
* * *^ *
2r 2A 2AA 2AA# 2a
*^ *^ *^ *^ *^
4r 4r 4A 4A 4AA 4AA 4AA# 4AA# 4a 4a
* * * * * * * * *v *v
* * *v *v *v *v *v *v *
*v *v * *
8r 8r 8r
*- *- *-
And the following is probably legal with the original Humdrum Toolkit tools since the *v
of spines 1 and 3 are not adjacent:
**kern **kern **kern
* *^ *
1r 1A 1AA 1a
* * *^ *
2r 2A 2AA 2AA# 2a
*^ *^ *^ *^ *^
4r 4r 4A 4A 4AA 4AA 4AA# 4AA# 4a 4a
* * *v *v *v *v *v *v * *
*v *v * *v *v
8r 8r 8r
*- *- *-
This requirement is probably due to the original Humdrum Toolkit tools not having a centralized parser and thus a low complexity method of requiring separate merge lines. In Humdrum Extras and humlib, there is a single parser thanks to object oriented programming. 😉
I don't particularly like this and agree with your expectation. I have been thinking of implementing in humlib (which are used to create filters in VHV) what you expect: prevent subspines from merging with other subspines unless they have the same originating spine:
**kern **kern **kern
* *^ *
1r 1A 1AA 1a
* * *^ *
2r 2A 2AA 2AA# 2a
*^ *^ *^ *^ *^
4r 4r 4A 4A 4AA 4AA 4AA# 4AA# 4a 4a
*v *v *v *v *v *v *v *v *v *v
8r 8r 8r
*- *- *-
An alternate idea would be to create *V
for separating subspines from separate origins:
**kern **kern **kern
* *^ *
1r 1A 1AA 1a
* * *^ *
2r 2A 2AA 2AA# 2a
*^ *^ *^ *^ *^
4r 4r 4A 4A 4AA 4AA 4AA# 4AA# 4a 4a
*v *v *V *v *v *v *v *v *V *v
8r 8r 8r
*- *- *-
where *V
prevents merging with any *v
to its left.
Both would be incompatible with the original Humdrum Tools, so I have not done it yet. But there could be a converter between the two (or three) systems (the first method is probably better than the *V
method).
I have a tool in Humdrum Extras to examine the spine pathes, called spinetrace
:
spinetrace file.krn
Results with your example:
**kern **kern **kern
* *^ *
1 (2)a (2)b 3
* * *^ *
1 (2)a ((2)b)a ((2)b)b 3
*^ *^ *^ *^ *^
(1)a (1)b ((2)a)a ((2)a)b (((2)b)a)a (((2)b)a)b (((2)b)b)a (((2)b)b)b (3)a (3)b
*v *v *v *v *v *v *v *v *v *v
3
*-
(The Humdrum Extras parser gets confused with the mass merge and assigns the last token to originate from spine 3 (rather than 1 and 2 and 3).
In humlib
, there is a tool called spinetrace2
which behaves slightly different (it uses a different Humdrum parser), but it also loses spine information if the primary spines are merged, with the last token assigned to primary spine 1.
**spine **spine **spine
* *^ *
1 (2)a (2)b 3
* * *^ *
1 (2)a ((2)b)a ((2)b)b 3
*^ *^ *^ *^ *^
(1)a (1)b ((2)a)a ((2)a)b (((2)b)a)a (((2)b)a)b (((2)b)b)a (((2)b)b)b (3)a (3)b
*v *v *v *v *v *v *v *v *v *v
1
*-
Also in humlib, the last token would ideally have a spinetrace of 1 2 3
rather than 1
, although I avoid merging subspines from different originating spines, so I have not bothered to refine the spine tracing analysis so far. (I use spinetrace
to track down spine split/merge problems.)
Notice that I keep track of the originating spine, so parsing as
*v *v *v *v *v *v *v *v *v *v
1 2 3
would be fairly easy to implement.
In Partial voices/layers, when two spines are to be merged into one spine the
*v
operator is used on both spines:In Multiple staves, the top staff spines are merged into just one using the same method, while the bottom staff is maintained without being split or merged. This is perfect.
However, for getting the example below the encoding is a bit different.
Given the examples in the documentation, when two splines must be merged into one, the
*v
operator must be used at the end of both spines. Then, the expected encoding should be:However, VHV complains because the number of tokens in the last bar line record do not match. To make it work, I've had to remove the left spine merge operator :