ssb22 / jianpu-ly

Jianpu in Lilypond
http://ssb22.user.srcf.net/mwrhome/jianpu-ly.html
Apache License 2.0
70 stars 18 forks source link

Supporting Grace #5

Closed jasongaoks closed 4 years ago

jasongaoks commented 4 years ago

Hi Silas, Is it possable to support \grace in jianpu-ly? image

Thanks

ssb22 commented 4 years ago

I'd really like to do this, but it's really difficult!

For our jianpu staff, we use Lilypond's RhythmicStaff to make sure all the notes are at the same vertical position. (If we didn't use a RhythmicStaff, then high notes will be higher and low notes will be lower, because Lilypond really wants to write 五线谱 even if you tell it to hide the 5 lines.) Then we tell Lilypond to change the "note heads" to look like numbers, make the stems zero height and make the beams thin (plus some other overrides to make it look better).

But Lilypond's RhythmicStaff (at least in the versions of Lilypond I tried) cannot change the vertical position of any of its notes. That means we cannot do chords and we cannot do grace-notes, because all notes must lie flat on one line ☹

I did try using a normal staff instead of a RhythmicStaff, and writing the music all on one note (because the version for MIDI-playing can be different), changing which number is used to print that one note. That, in theory, would let us have chords and grace-notes by changing Lilypond's idea of the pitch. But when I tried this, I couldn't get all the appearance overrides to work properly: it just made a mess, and I threw away my attempt and kept only the RhythmicStaff version.

To be honest, what I really wanted to happen is for the Lilypond development team to see my project and say "hey, jianpu is a good idea, maybe we can do that in the core Lilypond code so you won't need your project anymore". If they can do it in the main Lilypond code, they won't have to work around the limitations of RhythmicStaff—they could create a new staff type just for jianpu, and have it support chords and everything.

Unfortunately, not enough people expressed interest for the core Lilypond team to try it (and nobody set a bounty on it for them), so all we have is my ‘hack’. And unfortunately, although the Lilypond source code is free and open so I can go in there and edit it myself, it's rather big and complicated and I don't understand it as well as the core developers do. I can make small tweaks, but I cannot program a new staff type all by myself.

I originally wrote jianpu-ly because I was helping to print a songbook in jianpu. The voice parts had no chords and no grace-notes, just a simple tune and words. It was good enough for that. Of course I also wanted to add chords and grace-notes (and \afterGrace), as I thought maybe CUCOS CID could use it, so I did try. But it turns out CID prefer to write their music by hand anyway (even when it doesn't have chords or grace-notes), as very few of them run command-line programs. So when I couldn't get chords or grace-notes to work in jianpu-ly, I didn't worry about it too much, and just hoped my incomplete effort might prompt the real Lilypond development team to do it properly later.

It might be worth trying again for grace-notes, using the overrides available on Lilypond 2.19. jianpu-ly is currently supposed to support Lilypond 2.15, 2.16, 2.18 etc, in case you're on an old computer that cannot run the latest Lilypond, but one option might be to throw away that compatibility and say "thou shalt use 2.19", and see if the overrides can be kludged any differently. Only problem with 2.19 is, it is an unstable development branch (the next stable release will be 2.20; even numbers are stable, odd numbers are unstable, and eventually unstable 2.19 will become stable 2.20). We've been waiting for 2.20 to be released for a long time; I don't know when it will be. But the list of new features they've added so far doesn't seem to have anything that will help us, so if there is something then it's hidden ☹

If anybody manages to edit the generated Lilypond code to produce the desired result by doing something to override the vertical positions of notes etc, then it should be easy to port that edit back into the script—the problem here is to figure out what Lilypond code needs to be output.

jasongaoks commented 4 years ago

Thank you for your detailed answer. Only a few songs have chords and grace-notes. So Jianpu-ly already can meet most of my needs. It really helps. I will try the override on Lilypond 2.19 when I'm free. But before that, I have to read tons of documents to know the basic knowledge of Lilypond. :)

lianghongzhuo commented 4 years ago

@ssb22 Thank you for your effort in writing this code and sharing it with us. I also tried to write grace on it. After running jianpu-ly, I write a script to add markup notes on the positions that I want to make notes (In the ss file I write some placeholder to mark where I want to add markup notes). For grace, if I treat them as a markup it's easy to write numbers, but the grace symbol is hard to draw. For the symbol, I borrowed a font for erhu and draw it. The result is shown in the picture below. The drawback is, in this way, the midi will ignore the grace. And it limited to work on only one number as the position and offset and font size are all hardcoded.

note

ssb22 commented 4 years ago

Thanks Hongzhuo. What is the name of the erhu font you used? Does it have a free license? (I checked the font that Hiroshi Tachibana submitted with his erhu MuseScore plugin, but it doesn't have any grace-note symbols.)

Did you use Lilypond markup commands to print both the numbers and the symbol, stacked on top of each other? Can you give us an example of your Lilypond code? It might be possible to make jianpu-ly output the code by itself (so you don't need a separate script), if the user has the correct font installed. If we do that, we can also fix the MIDI problem at the same time, since jianpu-ly already creates a separate (invisible) staff for MIDI, so all we have to do is use Lilypond's normal grace notes in the MIDI staff while using markup in the jianpu staff.

多谢!

lianghongzhuo commented 4 years ago

The erhu font is a part of a free plug-in that use ms-word to write notes and the link is https://simperhu.weebly.com/ As far as I know, it's a free license. But I think the font style in it does not match what lilypond output. So I only use the grave symbol in that font. You can see the example in this zip file. Unzip this file and cd into jianpu folder and run ./compile_jianpu tianyuanchunse/tianyuanchunse.ss to see an example. I used erhu font and a Chinese font in it. You can change to another font if you don't have FZ Hei-B01 Regular. For example the Adobe fonts. jianpu.zip

ssb22 commented 4 years ago

Thanks. Unfortunately the current SimpErhu license is not free as in 自由软件, it is not compatible with the GNU GPL (通用公共授权) which is used by GNU Lilypond (and by jianpu-ly, because it makes sense for jianpu-ly to use the same license as Lilypond). SimpErhu_license_agreement.txt in simperhuengv48.zip says "User may distribute this free font and all the accompanying software and documentations to third parties freely, but only in the package's entirety" and "User may not sell, rent, lease, or otherwise charge for the distribution". It also says modifying it is not allowed. The GPL, on the other hand, says people must be allowed to charge (as long as the person who gets it can then give it away), and people must be allowed to modify. Therefore, that font cannot be included in a GPL project, because the two licenses don't agree with each other. In fact, including that font in another project at all might count as "modifying" it, so its license is unclear about whether you're allowed to include it in another project or not. Perhaps we should contact the author and ask for the license to be changed? but they might have had reasons for setting the license to what it is now, so perhaps that's not possible.

We might still be able to include Lilypond code that uses the font, but the user would have to install the font separately by themselves (and we'd better make sure that use of this font is optional i.e. you can still use jianpu-ly without it if you don't need those symbols). Your erhu_markup looks like something that can be integrated into jianpu-ly (although erhu_yiying might need changing to support more than one number).

ssb22 commented 4 years ago

by the way, for "yiying" did you mean 倚音 yǐyīn ? or something else? (just wondering if the g changes the meaning)

lianghongzhuo commented 4 years ago

Yes, I agree to integrate my code into jianpu-ly. But the grace staff is still not solved. Even if we got permission to use simple_erhu font, the erhu_yiying still needs to change.

lianghongzhuo commented 4 years ago

And you are right about the spelling. yiying was a typo. Maybe change to erhu_grace for better understanding.

ssb22 commented 4 years ago

Hi, how about something like this instead:

\once \textLengthOn  % (lets the markup take space in the stave)
\applyOutput #'Voice #note-five g'4   % (the line generated by jianpu-ly)

-\tweak font-size #-4 \trill   % that's a small trill

% Remove this line if you want the grace higher:
^\tweak outside-staff-priority ##f

^\markup {  % Draw the grace:
 \right-align
 \override #'(baseline-skip . 0.1) \column {
 \line { \fontsize #-4 "#4" }  % the note to put in the grace
 \line { \path #0.1 #'(
   (moveto 0 0) (lineto 1.5 0)   % first underline
   (moveto 0 -0.3) (lineto 1.5 -0.3)   % second underline
   (moveto 0.75 -0.3)   % and the slur:
   (curveto 0.75 -1 0.75 -1 1.5 -1)) }
} }

test

Maybe there could be more padding before the grace, and maybe the curve needs adjusting, but... something like that?

The main problem here is the 1.5 comes from the width of the string "#4", and the curveto parameters are derived from that—our script would have to figure out the width of each grace (which depends how many notes are in it), unless we can somehow get Lilypond's Scheme interpreter to calculate the text dimensions for us and multiply the coordinates accordingly.

ssb22 commented 4 years ago

This version adds a little more space around the grace-note, and makes it a bit higher although not as high as if outside-staff-priority is not set. But the trill becomes higher too.

\once \textLengthOn
\applyOutput #'Voice #note-five g'4

-\tweak font-size #-4 \trill

^\tweak outside-staff-priority ##f
^\markup {
 \right-align
 \override #'(baseline-skip . 0.2) \column {
 \line { \fontsize #-4 "#4" }
 \line { \pad-to-box #'(-0.1 . 0) #'(-1.6 . 0)
   \path #0.1 #'(
   (moveto 0 0) (lineto 1.5 0)
   (moveto 0 -0.3) (lineto 1.5 -0.3)
   (moveto 0.75 -0.3)
   (curveto 0.75 -1 0.75 -1 1.5 -1)) }
} }
ssb22 commented 4 years ago

Here's a version that makes Lilypond compute the width automatically. It works in Lilypond 2.18.2 and 2.20.0, but does not work in old Lilypond 2.16.2.

#(define-markup-command (erhu-grace layout props text)
(markup?) "Draw erhu grace under text."
(let ((textWidth (cdr (ly:stencil-extent (interpret-markup layout props (markup (#:fontsize -4 text))) 0))))
(interpret-markup layout props
(markup
  #:line
  (#:right-align
   (#:override
    (cons (quote baseline-skip) 0.2)
    (#:column
     (#:line
      (#:fontsize -4 text)
      #:line
      (#:pad-to-box
       (cons -0.1 0)  ; X padding before grace
       (cons -1.6 0)  ; affects height of grace
       (#:path
        0.1
        (list (list (quote moveto) 0 0)
              (list (quote lineto) textWidth 0)
              (list (quote moveto) 0 -0.3)
              (list (quote lineto) textWidth -0.3)
              (list (quote moveto) (* textWidth 0.5) -0.3)
              (list (quote curveto) (* textWidth 0.5) -1 (* textWidth 0.5) -1 textWidth -1))))))))))))

\once \textLengthOn
\applyOutput #'Voice #note-five g'4

-\tweak font-size #-4 \trill

^\tweak outside-staff-priority ##f
^\markup \erhu-grace "#4"

test(1)

lianghongzhuo commented 4 years ago

This output looks good to me! Thanks for your work on it. Maybe integrate this into jianpu-ly.py?

ssb22 commented 4 years ago

嗯好的... I just need to figure out how to make it work with octave dots as well, because this will be different from octave dots on the main music line, and I guess grace notes sometimes have octave dots inside them....