-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[myank] Add -l
flag to select line range and improve cutting null tokens
#55
Conversation
I think it is not necessary to have a separate tool/filter called |
What is the best way to modify a token? I am trying something like below but it has no effect. if (startLineHandled == false) {
HLp line = infile.getLine(i);
if(line->isData()) {
vector<HTp> tokens;
line->getTokens(tokens);
for (HTp token : tokens) {
if (token->isDataType("**kern") && token->isNull()) {
string recip = Convert::durationToRecip(token->getDurationToNoteEnd());
string pitch = Convert::base40ToKern(token->resolveNull()->getBase40Pitch());
string tokenText = recip + pitch + "]";
token->setText(tokenText);
}
}
startLineHandled = true;
}
}
m_humdrum_text << infile[i] << "\n"; |
The problem is that when a token's content is changed with The easiest thing to do is to is call Ideally I should add a more automated way of doing this: when HumdrumToken::setText is called, this would inform the HumdrumLine that it will need to regenerate its text when printing, and when printing a Humdrum file, the HumdrumLines would regenerate if there are any changes to tokens that have been reported. Or I should get rid of the complicated system of how this is done 😉 |
And don't forget to put spaces after |
Note that |
For the line in the sample code: string pitch = Convert::base40ToKern(token->resolveNull()->getBase40Pitch()); For the output of I don't know what Also related: if the resolved null token is a rest, I would not continue on to I double checked and Here is more robust code to replace the above line: HTp resolution = token->resolveNull();
if (resolution->isNull()) {
continue;
}
string pitch;
if (resolution->isRest()) {
pitch = "r";
} else {
pitch = resolution->getBase40Pitch();
} Or with the triple operator that you like to use: HTp resolution = token->resolveNull();
if (resolution->isNull()) {
continue;
}
string pitch = resolution->isRest() ? "r" : resolution->getBase40Pitch(); |
There was also the Here is some adjustments to the sample that also includes a flag to keep track of if HumLine needs to be updated: if (startLineHandled == false) {
HLp line = infile.getLine(i);
bool lineChange = false;
if (line->isData()) {
vector<HTp> tokens;
line->getTokens(tokens);
for (HTp token : tokens) {
if (token->isDataType("**kern") && token->isNull()) {
HTp resolve = token->resolveNull();
if (resolve->isNull()) {
continue;
}
string recip = Convert::durationToRecip(token->getDurationToNoteEnd());
string pitch;
if (resolve->isRest()) {
pitch = "r";
} else {
pitch = Convert::base40ToKern(resolve->getBase40Pitch());
}
string tokenText = recip + pitch + "]";
token->setText(tokenText);
}
}
startLineHandled = true;
}
if (lineChange) {
line->createLineFromToken();
}
}
m_humdrum_text << infile[i] << "\n"; |
Here is an improvement for the extraction of a pitch string (avoid going through a numeric conversion): string pitch;
if (hre.search(resolve, "([rRA-Ga-gxyXYn#-]+)") {
pitch = hre.getMatch(1);
} There is also a problem because chords are not yet handled... This will also handle semi-pitched notes which contain an |
-l
flag to myank to enable selecting a line range-l
flag to select line range and improve cutting sustained notes
… to end Add `HumdrumToken::getDurationFromNoteStart` and `HumdrumToken::getDurationToNoteEnd`
I have improved this now and it works okay so far:
One thing I would improve is the handling of the bar lines. I think if the section does not end at the end of a bar then the bar line should not be displayed. Maybe bar numbers should be displayed when using Additionally I could add an option to hide the notes that are cut and now need a tie. Although I'm not sure if this is useful since then there will be missing notes in the harmony (e.g. for And what you describe in humdrum-tools/verovio-humdrum-viewer#780 (comment) could still be implemented: when notes are longer than the section or when the null resolved notes start before the section they could be displayed with Anything I did not consider yet? You mentioned chords and maybe I should have a look at spine splits. Ideally we should refactor this so the |
We need a linter 😇️. Clang is not configurable the way you want it? |
Note that for some examples it will output !!!COM: Lassus, Orlandus
!!!CDT: 1532-1594/06/14
!!!OPR: Geistliche Psalmen mit dreyen Stimmen
!!!ONM: 5
!!!OTL@@LA: Verba mea auribus
!!!OTL-incipit@@DE: Vernimb Herr meine Wort
**kern **text **kern **text **kern **text
*Ivox * *Ivox * *Ivox *
*I"Bassus * *I"Tenor * *I"Cantus *
*I'B * *I'T * *I'C *
!!!COM: Lassus, Orlandus
!!!COM: Lassus, Orlandus
!!!COM: Lassus, Orlandus
!!!COM: Lassus, Orlandus
!!!COM: Lassus, Orlandus
!!!COM: Lassus, Orlandus
2d re- 2f# re- 4a -dach-
. . . . 4dd -te
2e-X -den 2.g -den 8cc re-
. . . . 8b- .
. . . . 8b- .
. . . . 16a .
. . . . 16g .
=10 =10 =10 =10 =10 =10
1d mein/ . . 2a .
. . 8f#i . . .
. . 8e . . .
. . 2f#i . 2a -den
2r . [2g mein/ 2g mein/
= = = = = =
*- *- *- *- *- *-
!!!RDF**kern: l = terminal long
!!!RDF**kern: i = editorial accidental
!!!AGN: Psalm; Tricinium
!!!LIB: Ulenberg, Caspar
!!!LIB-CDT: 1548/12/24-1617/02/16
!!!YOR: https://mdz-nbn-resolving.de/details:bsb00075346
!!!YOR-alternative: https://mdz-nbn-resolving.de/details:bsb00072990
!!!YOO: München, Bayerische Staatsbibliothek
!!!URL-scan: https://www.digitale-sammlungen.de/de/view/bsb00075346?page=15 Cantus
!!!URL-scan: https://www.digitale-sammlungen.de/de/view/bsb00075346?page=75 Tenor
!!!URL-scan: https://www.digitale-sammlungen.de/de/view/bsb00075346?page=131 Bassus
!!!IIIF: https://api.digitale-sammlungen.de/iiif/presentation/v2/bsb00075346/manifest
!!!EED: Wolfgang Drescher
!!!END: 2022/12/22
!!!ENC: Wolfgang Drescher
!!!EEV: 2022/12/22
!!!title: @{ONM}. @{OTL} / <i>@{OTL-incipit@@DE}</i> |
In theory this would be nice, but I like to vertically align code in cases such as when there is a lot of repetition, and in the *.h files I like to line up the member function names vertical to make it faster to browse through the list of functions. So a linting option for In verovio there is a style file for clang-format: And before I submit updates to code in the verovio repository (excluding humlib which is an external library to verovio), I run |
For cases such as this one:
There should not be a barline added at the end of the yanked line (there is a 16th duration more before the barline) Current output: myank -l 41-45 /tmp/z.krn | rid -G **kern **text **kern **text **kern **text
*clefC3 * *clefC1 * *clefG2 *
*k[b-] * *k[b-] * *k[b-] *
*g:dor * *g:dor * *g:dor *
*M2/1 * *M2/1 * *M2/1 *
*met(C|) * *met(C|) * *met(C|) *
*MM180 * *MM180 * *MM180 *
4f] . 4a] . 4.cc dir
[4..e- kom- [4..g dir . .
. . . . 8b- .
. . . . 8b- .
. . . . 16a .
= = = = = =
*- *- *- *- *- *- Desired output: **kern **text **kern **text **kern **text
*clefC3 * *clefC1 * *clefG2 *
*k[b-] * *k[b-] * *k[b-] *
*g:dor * *g:dor * *g:dor *
*M2/1 * *M2/1 * *M2/1 *
*met(C|) * *met(C|) * *met(C|) *
*MM180 * *MM180 * *MM180 *
4f] . 4a] . 4.cc dir
[4..e- kom- [4..g dir . .
. . . . 8b- .
. . . . 8b- .
. . . . 16a .
*- *- *- *- *- *- This will prevent displaying a barline where there should not be one: |
This is fixed now. Additionally bar numbers are now displayed when the yanked section (with
What do you mean with «adding any lines before the lines to be extracted will mess up»?
I would simply convert those measures into a line range. How about
This sound interesting for my analysis ideas of Bach chorales as I want to interate over each n quater notes segments. But how should we handle when there is no slice existing in the score for a selected beat (e.g. rhythm goes in whole notes but you select quater note 2-3). Either simply display the whole note which is not ideal, or we need a complicated manipulation of this slice.
Maybe |
Actually the problem is not in combination with This seems to be related to if (clefQ) {
for (i=0; i<infile[ii].getFieldCount(); i++) {
ptrack = infile.token(ii, i)->getTrack();
x = outmeasures[index].sclef[ptrack].x;
y = outmeasures[index].sclef[ptrack].y;
if ((x>=0)&&(y>=0)) {
m_humdrum_text << infile.token(x, y);
} else {
m_humdrum_text << "*";
}
if (i < infile[ii].getFieldCount()-1) {
m_humdrum_text << "\t";
}
}
m_humdrum_text << "\n";
}
|
I found a solution for this in 3fc4f16. But I think it's better if you review this as I don't know well the logic of |
-l
flag to select line range and improve cutting sustained notes-l
flag to select line range and improve cutting null tokens
I added options to hide everything before the yanked data starts ( |
Is there anything you want me to add or test for this PR? Your suggestions from humdrum-tools/verovio-humdrum-viewer#780 (comment) are not implemented yet where notes that exceed the the myank (beginning or end) are displayed with their full duration. But currently I don't think this is needed for a initial version of this feature. I can come back to this when someone needs it. So I think this PR should be ready to merge, or at least ready for review. |
The PR code looks great. There were just a few very minor things I just commented on. You can tell me when you push changes for those, and then I will integrate the PR and compile it for VHV use. Another small thing is that sometimes the lines are a bit long. I used to limit to 80 characters on a line, but no longer bother with that. But it would be good to strive to avoid long lines in any case. Sometimes I break long lines onto two lines in this way: after a line break inside of a condition, such as |
Also you should document new options on https://doc.verovio.humdrum.org/filter/myank for tools as they are added. But I just looked and see there is no documentation for myank on that website, so you are off the hook for that (at the moment :-) As a coincidence, I showed someone today how measures can be selected from a full score with The myank tool was ported from the Humdrum Extras code base, and there is documentation: New options cannot be added to that page, since the old version will not have the new options. At some point I will transfer over the documentation for the humlib version of |
Okay, I will have a look again, must have missed some.
You can assign me an issue then. One thing I noticed: Alternatively, this could probably be achieved with |
Yes, I think that reference records should always be preserved. There can be a fine distinction: Any reference records before the first exclusive interpretation and last data termination line Reference records are "timeless" so they should be unaffected by the time region selected by |
You did not miss them: I just newly added them (I can point them out if you did not get email messages about them from Github). |
# Conflicts: # include/humlib.h # src/humlib.cpp
JS linters (even php-cs-fixer) will format this completely different. I'm used to something like this: if (
getBoolean("lines") &&
lastDataLine >= 0 &&
infile.getLine(lastDataLine)->getDurationToBarline() > infile.getLine(lastDataLine)->getDuration()
) { I run But personally I prefer having long lines, even though I tend to use verbose variable names (and the editor can still wrap lines if you want it).
Do you mean this comment: #55 (comment)? If not I did not get a notification from GitHub for other review comments, so I'd be glad If you point them out again. |
Another thing I noticed is that |
Yes, it would be best to remove it. Was it there before you added code? There is also a problem in the text editor on VHV, where the editor loves to add an extra line at the bottom of the text, which is hard to get rid of.
Long lines are not a problem, so don't worry about it too much. (but also don't be excessive with them :-) if (
getBoolean("lines") &&
lastDataLine >= 0 &&
infile.getLine(lastDataLine)->getDurationToBarline() > infile.getLine(lastDataLine)->getDuration()
) { I would do this: if (getBoolean("lines") & lastDataLine >= 0 &&
infile.getLine(lastDataLine)->getDurationToBarline() > infile.getLine(lastDataLine)->getDuration()) {
i = i + 2;
} There is a double indent of the continuation of the condition, and the main body of the block has a normal single indentation. Just having if HLp line = &infile.getLine(lastDataLine);
if (getBoolean("lines") && (lastDataLine >= 0) && (line->getDurationToBarline() > line->getDuration())) {
i = i + 2;
} Note the extra I will merge this PR now and adjust a few things in style I was mentioning. The main thing is that |
Another style thing is for the triple operator: int w = x ? y : z; There should be a space between the |
Why do you use the variable name for (int d = i; d <= endLineNumber - 1; d++) {
if (!infile.getLine(d)->isCommentGlobal()) {
nextLineIndexWithSpines = d;
break;
}
} No problem with that. I customarily use |
Regarding long variable names: Having a variable name that is describes what it is being used for is good. I tend to prefer to have a comment describing what the variable does along with a shorter name, unless it is important to keep track of the meaning of the variable. There is also another way of having both by making an alias reference variable: int someLongNameDescribingWhatTheVariableDoes = 42;
int& myvar = someLongNameDescribingWhatTheVariableDoes; Now you can use In iohumdrum.cpp I use this often, such as: void HumdrumInput::processHangingTieStarts()
{
std::vector<humaux::StaffStateVariables> &ss = m_staffstates;
for (int i = 0; i < (int)ss.size(); ++i) {
for (auto &it : ss[i].tiestarts) {
processHangingTieStart(it);
}
}
} This also reminds me what the type of void HumdrumInput::processHangingTieStarts()
{
std::vector<humaux::StaffStateVariables> &ss = m_staffstates;
for (int i = 0; i < (int)m_staffstates.size(); ++i) {
for (auto &it : m_staffstates[i].tiestarts) {
processHangingTieStart(it);
}
}
} In the previous code snippet, I see the flow of the logical structure clearer and the names of the variables do not get in the way (particularly if they are repeating). |
Regarding |
Must have been a typo. Usually I do this.
There was a bug with nested loop where I used two times
I personally find it more readable when long variable names are declared. But I can follow your suggestions for future PRs in humlib. |
This PR enables to pass a line range to
myank
to filter a specific segment of the score and adds improved support for sustained notes that are not tied. See this exmaple:VHV
Probably this is not the best approach because in combination with
myank
this feature needs bar numbers to be present in the source kern file, but filtering by a line range should not depend on bar numbers.Maybe it's better to add a new
lyank
method to themyank
tool? Or would it be better to create a separate command for this? Sincemyank
andlyank
need similar features, like the one described in humdrum-tools/verovio-humdrum-viewer#780 and humdrum-tools/verovio-humdrum-viewer#781, I suggest to keep it withinmyank
.