-1.3.76
+--- ../lilypond-1.3.76/CHANGES Fri Aug 4 02:29:02 2000
+++ b/CHANGES Mon Aug 7 00:19:35 2000
+@@ -1,3 +1,12 @@
+1.3.76.gp1
+==========
+* Lyric_phrasing_engraver now catches lyric extenders and correctly
+ terminates them under the last note of a melisma.
+
+* Lyric word spacing code changed to fix hyphen alignment.
+
+* Other minor tidying up of Lyric_phrasing_engraver and related code.
+
+ 1.3.76
+ ======
+ 1.3.76
======
* Lyric_phrasing_engraver now adjusts for melisma. (Glenn Prideaux).
MAJOR_VERSION=1
MINOR_VERSION=3
PATCH_LEVEL=76
-MY_PATCH_LEVEL=
+MY_PATCH_LEVEL=gp1
# use the above to send patches: MY_PATCH_LEVEL is always empty for a
# released version.
Oh __ \repeat "fold" 2 { }
\alternative {
{
- say, can you | see, by the dawn's ear- ly light
- What so proud- ly we hailed,
- At the twi- light's last gleam- ing.
+ say, can you | see, by the dawn's ear -- ly light
+ What so proud -- ly we hailed,
+ At the twi -- light's last gleam -- ing.
% Ah, it seems that this context stops to exist just before
% the :| barline is set, and doesn't see its width?
% Ugly fix:
Whose broad \bar "|.";
}
+ \context LyricVoice = "one-2"
{
- stripes and bright stars, through the per- il- ous fight,
- O'er the ram- parts we watched, were so gal- lant- ly
+ stripes and bright stars, through the per -- il -- ous fight,
+ O'er the ram -- parts we watched, were so gal -- lant -- ly
" " " " " " " "% UGH UGH UGH
- stream- ing
+ stream -- ing
- And the rock- ets' red glare, the bombs burst- ing in air,
+ And the rock -- ets' red glare, the bombs burst -- ing in air,
gave proof through the night that our flag was still there,
- Oh say, does that star- span- gled ban- ner yet wave, __
+ Oh say, does that star -- span -- gled ban -- ner yet wave, __
O'er the land __ of the free and the home of the brave.
}
}
\$staff1_voice_2
}
>
- \context LyricVoice \text
+ \context LyricVoice = "one-1" \text
\context Staff=lower <
\global
\clef bass;
\GrandStaffContext
\accepts "Lyrics";
}
- \translator {
- \LyricsContext
- \consists "Span_bar_engraver";
- }
+% We have a Span_bar_engraver in GrandStaff; we only get grief if we add it here too.
+% \translator {
+% \LyricsContext
+% \consists "Span_bar_engraver";
+% }
\translator {
\LyricsVoiceContext
\consists "Bar_engraver";
>
\paper {
- \translator {
- \ScoreContext
- \consists "Lyric_phrasing_engraver";
- automaticPhrasing = ##t;
- }
}
}
\ No newline at end of file
--- /dev/null
+\header{
+filename = "twinkle-pop.ly";
+%title = "Ah, vous dirais-je, maman ";
+description = "twinkle twinkle in pop-song-settings";
+composer = "traditional";
+enteredby = "HWN, chords by Johan Vromans";
+copyright = "public domain";
+}
+
+\version "1.3.59";
+
+m =\notes \relative c'' {
+ \property Staff.automaticMelismata = ##t
+ \autoBeamOff
+ g4 r8 \times 2/3 { g'8( f )e } r8 \grace { [d16 c b] } e4
+ \emptyText
+ d8.^"melisma" \melisma c16
+ \melismaEnd
+ b c d e }
+
+textI = \lyrics { la4 __ la -- la I, la dargh la dargh. }
+textII = \lyrics { dar -- dargh __ dargh dargh; dargh la dargh loo. }
+textIII = \lyrics { la -- da __ doo dah; dargh la dargh loo. }
+
+\score {
+
+ \notes < \context Staff = SA \context Voice = VA { s1 }
+ \context LyricVoice = "VA-1" { s1 }
+ \context LyricVoice = "VA-2" { s1 }
+
+ \addlyrics
+ \context Staff = SA \m
+ < \context LyricVoice = "VA-1" \textI
+ \context LyricVoice = "VA-2" \textII
+ \context LyricVoice = "VA-3" \textIII
+ >
+
+ >
+
+ \paper {
+ \translator {
+ \ScoreContext
+ \consists "Lyric_phrasing_engraver";
+ automaticPhrasing = ##t;
+ }
+ }
+
+}
\ No newline at end of file
Real th = gh_scm2double (sp->get_elt_property ("thickness")) * lt ;
Real h = gh_scm2double (sp->get_elt_property ("height")) * ss;
Real l = gh_scm2double (sp->get_elt_property ("minimum-length")) * ss;
+ // The hyphen can exist in the word space of the left lyric ...
+ SCM space = sp->get_bound (LEFT)->get_elt_property ("word-space");
+ if (gh_number_p (space))
+ {
+ bounds[LEFT] -= gh_scm2double (space)*ss;
+ }
Real w = bounds.length ();
- /* First try: just make the hyphen take 1/3 of the available space
- for length, use a geometric mean of the available space and some minimum
+ /* for length, use a geometric mean of the available space and some minimum
*/
if(l < w)
l = sqrt(l*w);
void record_notehead(const String &context_id, Score_element * notehead);
void record_lyric(const String &context_id, Score_element * lyric);
void record_melisma(const String &context_id);
+ void record_extender(const String &context_id, Score_element * extender);
Voice_alist_entry * lookup_context_id(const String &context_id);
public:
bool first_in_phrase_b_;
Score_element * notehead_l_;
Link_array<Score_element> lyric_list_;
+// Link_array<Score_element> extender_list_;
Score_element * longest_lyric_l_;
Score_element * shortest_lyric_l_;
int alignment_i_;
void set_first_in_phrase(bool f);
void set_notehead(Score_element * notehead);
void add_lyric(Score_element * lyric);
+ void add_extender(Score_element * extender);
+// void terminate_extenders();
+// void clear_extenders();
void set_melisma();
bool get_melisma() { return melisma_b_; }
int lyric_count() { return lyric_list_.size(); }
text_p_= new Item (get_property ("basicLyricTextProperties"));
text_p_->set_elt_property ("text",
- ly_str02scm ((req_l_->text_str_ + " ").ch_C ()));
+// ly_str02scm ((req_l_->text_str_ + " ").ch_C ()));
+ ly_str02scm ((req_l_->text_str_).ch_C ()));
text_p_->add_offset_callback (&Side_position::aligned_on_self,X_AXIS);
/*
Real leftext = sp->get_bound (LEFT)->extent (X_AXIS).length ();
Real ss = sp->paper_l ()->get_var ("staffspace");
- Real w = sp->spanner_length () - leftext - ss/2;
+ Real righttrim = 0.5; // default to half a staffspace gap on the right
+ SCM righttrim_scm = sp->get_elt_property("right-trim-amount");
+ if (gh_number_p (righttrim_scm)) {
+ righttrim = gh_scm2double (righttrim_scm);
+ }
+ // The extender can exist in the word space of the left lyric ...
+ SCM space = sp->get_bound (LEFT)->get_elt_property ("word-space");
+ if (gh_number_p (space))
+ {
+ leftext -= gh_scm2double (space)*ss;
+ }
+ Real w = sp->spanner_length () - leftext - righttrim*ss;
Real h = sp->paper_l ()->get_var ("extender_height");
Molecule mol (sp->lookup_l ()->filledbox ( Box (Interval (0,w), Interval (0,h))));
#include "note-head.hh"
#include "translator-group.hh"
#include "side-position-interface.hh"
+#include "spanner.hh"
+#include "paper-def.hh"
String get_context_id(Translator_group * ancestor, const char * type);
String trim_suffix(String &id);
v->add_lyric(lyric);
}
+void
+Lyric_phrasing_engraver::record_extender(const String &context_id, Score_element * extender)
+{
+ SCM key = ly_str02scm(context_id.ch_C());
+ if( ! gh_null_p(voice_alist_) ) {
+ SCM s = scm_assoc(key, voice_alist_);
+ if(! (gh_boolean_p(s) && !to_boolean(s))) {
+ /* match found */
+ // ( key . ( (alist_entry . old_entry) . previous_entry) )
+ SCM previous_scm = gh_cddr(s);
+ if(previous_scm != SCM_EOL) {
+ Voice_alist_entry * v = unsmob_voice_entry(previous_scm);
+ v->add_extender(extender);
+ }
+ }
+ }
+}
+
void
Lyric_phrasing_engraver::record_melisma(const String &context_id)
{
record_melisma(voice_context_id);
return;
}
+ /* How about catching any extender items and then if we have a melisma,
+ set the RIGHT item of the extender spanner to the melismatic note in
+ the corresponding context (if any).
+ This has the effect of finishing the extender under the last note
+ of the melisma, instead of extending it to the next lyric.
+
+ Problem: the extender request is thrown at the same moment as the next lyric,
+ by which time we have already passed the last note of the melisma.
+ However, the Lyric_phrasing_engraver remembers the last note, so just
+ attach it to that, provided it was melismatic. If it was not melismatic,
+ then ignore it and let the Extender_engraver take care of it (i.e. finish at next
+ lyric).
+ */
+ if(h->has_interface (ly_symbol2scm ("lyric-extender-interface"))) {
+ String voice_context_id = get_context_id(i.origin_trans_l_->daddy_trans_l_, "LyricVoice");
+ record_extender(trim_suffix(voice_context_id), h);
+ return;
+ }
}
String
for(SCM v=voice_alist_; gh_pair_p(v); v = gh_cdr(v)) {
SCM v_entry = gh_cdar(v);
// ((current . oldflag) . previous)
- Voice_alist_entry *entry = unsmob_voice_entry(gh_caar(v_entry));
- if(! entry->set_lyric_align(punc.ch_C(), any_notehead_l_))
- warning (_ ("lyrics found without any matching notehead"));
-
- // is this note melismatic? If so adjust alignment of previous one.
- if(entry->get_melisma()) {
- if(entry->lyric_count())
- warning (_ ("Huh? Melismatic note found to have associated lyrics."));
- SCM previous_scm = gh_cdr(v_entry);
- if(previous_scm != SCM_EOL) {
- Voice_alist_entry *previous = unsmob_voice_entry(previous_scm);
- if (previous->lyric_count())
- previous->adjust_melisma_align();
+ if(!to_boolean(gh_cdar(v_entry))) { // not an old entry left over from a prior note ...
+ Voice_alist_entry *entry = unsmob_voice_entry(gh_caar(v_entry));
+ if(! entry->set_lyric_align(punc.ch_C(), any_notehead_l_))
+ warning (_ ("lyrics found without any matching notehead"));
+
+ // is this note melismatic? If so adjust alignment of previous one.
+ if(entry->get_melisma()) {
+ if(entry->lyric_count())
+ warning (_ ("Huh? Melismatic note found to have associated lyrics."));
+ SCM previous_scm = gh_cdr(v_entry);
+ if(previous_scm != SCM_EOL) {
+ Voice_alist_entry *previous = unsmob_voice_entry(previous_scm);
+ if (previous->lyric_count())
+ previous->adjust_melisma_align();
+ }
}
}
}
longest_lyric_l_ = shortest_lyric_l_ = lyric;
}
- void
+void
+Voice_alist_entry::add_extender(Score_element * extender)
+{
+ if(notehead_l_ && melisma_b_) {
+ dynamic_cast<Spanner*>(extender)->set_bound (RIGHT, notehead_l_);
+ // should the extender finish at the right of the last note of the melisma, or the left?
+ // Comments in lyric-extender.hh say left, but right looks better to me. GP.
+
+ // Left:
+// extender->set_elt_property("right-trim-amount", gh_double2scm(0.0));
+
+ // Right:
+ Real ss = extender->paper_l ()->get_var ("staffspace");
+ extender->set_elt_property("right-trim-amount",
+ gh_double2scm(-notehead_l_->extent(X_AXIS).length()/ss));
+ }
+}
+
+void
Voice_alist_entry::set_melisma()
{
melisma_b_ = true;
SCM lyric_scm = lyric->get_elt_property("text");
String lyric_str = gh_string_p(lyric_scm)?ly_scm2string(lyric_scm):"";
char lastchar;
- if(lyric_str.length_i()>1) {
- lastchar = lyric_str[lyric_str.length_i()-2];
- /* We look at the second last character, because lily always appends a space. */
+ if(lyric_str.length_i()>0) {
+ lastchar = lyric_str[lyric_str.length_i()-1];
/* If it doesn't end in punctuation then it ain't an end of phrase */
if(! strchr(punc, lastchar)) {
/* Special case: trailing space. Here examine the previous character and reverse the
FIXME: The extra space throws alignment out a bit.
*/
if(lastchar == ' ') {
- if(lyric_str.length_i()>2) {
- lastchar = lyric_str[lyric_str.length_i()-3];
+ if(lyric_str.length_i()>1) {
+ lastchar = lyric_str[lyric_str.length_i()-2];
if(strchr(punc, lastchar))
end_phrase=false;
}
)
basicLyricExtenderProperties = #`(
(molecule-callback . ,Lyric_extender::brew_molecule)
+ (right-trim-amount . 0.5)
+ (interfaces . (lyric-extender-interface))
)
basicLyricTextProperties = #`(
(molecule-callback . ,Text_item::brew_molecule)
(self-alignment-X . 0)
(non-rhythmic . #t)
+ (word-space . 0.6)
(interfaces . (lyric-syllable-interface text-item-interface))
)
basicMarkProperties = #`(
(interfaces . (mark-interface))
(visibility-lambda . ,end-of-line-invisible)
)
+ basicMelismaProperties = #`(
+ (interfaces . (melisma-interface))
+ )
basicMultiMeasureRestProperties = #`(
(spacing-procedure . ,Multi_measure_rest::set_spacing_rods)
(molecule-callback . ,Multi_measure_rest::brew_molecule)
(thick-thickness . 6.0)
(interfaces . (bar-interface span-bar-interface))
)
+ basicStanzaNumberProperties = #`(
+ (breakable . #t)
+ (molecule-callback . ,Text_item::brew_molecule)
+ (break-align-symbol . Clef_item)
+ (visibility-lambda . ,begin-of-line-visible)
+ )
+ basicStemProperties = #`(
+ (before-line-breaking-callback . ,Stem::before_line_breaking)
+ (molecule-callback . ,Stem::brew_molecule)
+
+ ; if stem is on middle line, choose this direction.
+ (default-neutral-direction . 1)
+ (interfaces . (stem-interface))
+ )
basicSustainPedalProperties = #`(
(no-spacing-rods . #t)
(molecule-callback . ,Sustain_pedal::brew_molecule)
(self-alignment-X . 0)
(interface . (sustain-pedal-interface))
)
+ staffSymbolBasicProperties = #`(
+ (molecule-callback . ,Staff_symbol::brew_molecule)
+ (staff-space . 1.0)
+ (line-count . 5 )
+ (interfaces . (staff-symbol-interface ))
+ )
basicSystemStartDelimiterProperties = #`(
(molecule-callback . ,System_start_delimiter::brew_molecule)
(after-line-breaking-callback . ,System_start_delimiter::after_line_breaking)
(bracket-thick . 0.25)
(bracket-width . 2.0)
)
- basicStemProperties = #`(
- (before-line-breaking-callback . ,Stem::before_line_breaking)
- (molecule-callback . ,Stem::brew_molecule)
-
- ; if stem is on middle line, choose this direction.
- (default-neutral-direction . 1)
- (interfaces . (stem-interface))
- )
- staffSymbolBasicProperties = #`(
- (molecule-callback . ,Staff_symbol::brew_molecule)
- (staff-space . 1.0)
- (line-count . 5 )
- (interfaces . (staff-symbol-interface ))
- )
basicTextScriptProperties = #`(
(molecule-callback . ,Text_item::brew_molecule)
(no-spacing-rods . #t)
(molecule-callback . ,Volta_spanner::brew_molecule)
(interfaces . (volta-spanner-interface))
)
- basicStanzaNumberProperties = #`(
- (breakable . #t)
- (molecule-callback . ,Text_item::brew_molecule)
- (break-align-symbol . Clef_item)
- (visibility-lambda . ,begin-of-line-visible)
- )
- basicMelismaProperties = #`(
- (interfaces . (melisma-interface))
- )
\accepts "Staff";
\accepts "StaffGroup";