leonawicz / tabr

R package: tabr. Notation-based and tidy music data analysis and transcription.
https://leonawicz.github.io/tabr/
Other
126 stars 10 forks source link

Repeated sections in sheet music do not repeat in the midi file #2

Closed areeves87 closed 6 years ago

areeves87 commented 6 years ago

Can tabr call lilypond to create a midi file of the tab yet?

If no, any interest in building out that feature? I am willing to help.

I understand if you feel it is outside the scope of the project but it may be useful for verifying you have the correct notation.

leonawicz commented 6 years ago

Yes, in fact it does so by default. That's easy because all that legwork is part of LilyPond. To actually turn it off in tabr, simply set midi = FALSE in tab or lilypond, depending on which wrapper you are using.

I'm going to leave this issue open, however, because the midi files are not always correct. Specifically, if your sheet music uses repeat notation (volta or percent repeats, via volta or pct), the repeated sections do not seem to be repeated in the midi file. I don't know exactly where this lack of specificity is occurring. If something is missing from the volta output for example, I don't know what it is. It does provide the number of repeats.

Any help is appreciated! I love the midi option (though I may back off of having the default set to TRUE. Starting to think that is overkill). But yeah, I'm so focused on the transcribing that midi is off my radar.

It's not outside the scope. I also plan to add a mapping function to take midi input straight to tabr syntax to be rendered to sheet music. I'll make a separate issue for that.

Matt

areeves87 commented 6 years ago

I see now that the simple example you've included in the readme produces a pdf and a midi. Very nice!

I am willing to look into the repeat notation issue. Could you help me get started by providing a minimally reproducible example of the issue?

leonawicz commented 6 years ago

Here are two examples based on the tiny opening package example that is one measure long.

p1 <- p("r a2 c f d a f", "4 8*6", "x 5 5 4 4 3 4")
volta(p1) %>% track %>% score %>% tab("phrase-repeated1.pdf")
pct(p1) %>% track %>% score %>% tab("phrase-repeated2.pdf")

If you look at the print result of volta and pct, I'm pretty sure I am specifying it fully based on LilyPond docs examples. If this is where the issue lies (I think it probably is), I'm not sure what is wrong.

By default these do one repeat/two plays. You can increase n repeats above the default for either function and the result is the same: the midi files always plays the measure a single time. Same behavior with repeats in the middle of larger pieces of music.

The text annotation that appears on the staff for > 1 repeat with volta is my own addition. It bugged me that I even had to do this (otherwise it remained a basic volta section with no indication in the output that it was to be repeated more than just the one time). That tipped me off that something must be wrong, because even with n applied correctly, it made zero difference in the sheet music.

Interestingly, pct does work properly, in that it clearly generates the explicit repeated percent notation in the output. Nevertheless, this too is not repeated in the midi file, so there may be more than one thing going on here.

areeves87 commented 6 years ago

http://lilypond.org/doc/v2.18/Documentation/notation/repeats-in-midi

You might need to include an "unfold" option in the volta and pct function parameters.

From the lilypond docs (see link) when an unfold command is included, lilypond will explicitly repeat the notes. This is required for making the midi play the repeats. To make it so that the score uses repeat notation whereas the midi unfolds, see the bottom of the page where they hint that you'll need two score blocks: one for the score and one for the midi.

I started taking a stab at the changes but I will be slower than you probably. I'm still wrapping my head around the code!

leonawicz commented 6 years ago

Nice! So the good news is now we know the issue and exactly how to tell LilyPond how to handle the document and the midi file. Hopefully it will be as simple as dropping a \unfoldRepeats in front of the entire midi tag score block contents they are calling ...music... like they show in the docs.

The only trouble with adding an unfold argument to volta and pct is I don't think it will be used. I could still add it for an edge case where the user only wishes to write midi, but even there I think it will be taken care of automatically: When a user makes use of these functions when constructing a phrase, I don't want them to have to think about constructing the same phrases twice (and then having to do something with two versions of that phrase...). So I'll plan to make it so that unfolding is inferred later (during the lilypond call) based on whether its dealing with the main score section of the LilyPond file or the copy being written inside its midi tag. Different unexported helper functions construct different parts of the .ly file in the lilypond call. I'll try to generalize the one that inserts the midi tag portion of the file.

It'll either be easy or difficult, but I'll do it this way so the user never has to think about it (and so I don't have to refactor the approach to everything else)

areeves87 commented 6 years ago

Ah yeah like I said I still haven't wrapped my head around the code yet. Inferring the unfolding later on makes a lot of sense. I also hope its an easy solution. Good luck!

leonawicz commented 6 years ago

Repeat sections are now unfolded by the lilypond function in tabr that writes the .ly file. This is applied to each unique voice and track so that all are respected in the MIDI output. The LilyPond file generated is now one where the layout tag for the sheet music and the midi tag for the optionally accompanying MIDI file are in separate score tags. It also works if you go straight from the tab function directly to sheet music/MIDI.

I tested on several toy examples unfolding percent and volta repeats, as well as on much larger scores that have many of each repeat tag throughout the scores requiring unfolding. All worked properly and led to MIDI files playing the proper number of all measures, matching the sheet music. So it looks all good now! :)