--- /dev/null
+
+%{
+
+ Example template for a SATB vocal score.
+
+%}
+
+sopMusic = \notes \relative c'' { c4 c [c8( )b] c4 }
+sopWords = \lyrics { hi4 hi hi hi }
+
+altoMusic = \notes \relative c' { e4 f d e }
+altoWords =\lyrics { ha4 ha ha ha }
+
+tenorMusic = \notes \relative c' { g4 a f g }
+tenorWords = \lyrics { hu4 hu hu hu }
+
+bassMusic = \notes \relative c { c4 c g c }
+bassWords = \lyrics { ho4 ho ho ho }
+
+\score { \notes
+ \context StaffGroup <
+ \property Score.automaticMelismata = ##t
+ \context Lyrics = sopLyrs { s1 }
+ \context Staff = women { s1 }
+ \context Lyrics = altoLyrs { s1 }
+ \context Lyrics = tenorLyrs { s1 }
+ \context Staff = men {\clef bass s1 }
+ \context Lyrics = bassLyrs { s1 }
+ \addlyrics
+ \context Staff = women \context Voice = VA { \voiceOne \sopMusic }
+ \context Lyrics = sopLyrs { \sopWords}
+ \addlyrics
+ \context Staff = women \context Voice = VB { \voiceTwo \altoMusic }
+ \context Lyrics = altoLyrs { \altoWords}
+ \addlyrics
+ \context Staff = men \context Voice = VA { \voiceOne \tenorMusic }
+ \context Lyrics = tenorLyrs { \tenorWords}
+ \addlyrics
+ \context Staff = men \context Voice = VB { \voiceTwo \bassMusic }
+ \context Lyrics = bassLyrs { \bassWords}
+
+ >
+ \paper {
+ \translator {
+
+ % a little smaller so lyrics can be closer to the staff.
+ \StaffContext
+ minimumVerticalExtent = #'(-3 . 3)
+ }
+ }
+}
{
public:
TRANSLATOR_DECLARATIONS(Ambitus_engraver);
- virtual void start_translation_timestep ();
virtual void acknowledge_grob (Grob_info);
- virtual void create_grobs ();
virtual void stop_translation_timestep ();
+ virtual void finalize ();
private:
void create_ambitus ();
Ambitus_engraver::stop_translation_timestep ()
{
if (!ambitus_p_) {
+ // Create ambitus not before stopping timestep. centralCPosition
+ // will then be the same as that for the first timestep.
+ //
+ // TODO: is this really a good idea? At least, creating the
+ // ambitus in start_translation_timestep is a *bad* idea, since we
+ // may then oversee a clef that is defined in a staff context if
+ // we are in a voice context; centralCPosition would then be
+ // assumed to be 0.
create_ambitus ();
}
if (ambitus_p_ && isActive)
SCM key_signature = get_property ("keySignature");
ambitus_p_->set_grob_property ("keySignature", key_signature);
typeset_grob (ambitus_p_);
- //ambitus_p_ = 0;
isActive = 0;
}
}
-void
-Ambitus_engraver::start_translation_timestep ()
-{
- if (!ambitus_p_) {
- create_ambitus ();
- }
-}
-
-void
-Ambitus_engraver::create_grobs ()
-{
- if (!ambitus_p_) {
- create_ambitus ();
- }
-}
-
void
Ambitus_engraver::acknowledge_grob (Grob_info info)
{
// not yet init'd; use current pitch to init min/max
pitch_min = pitch;
pitch_max = pitch;
- ambitus_p_->set_grob_property ("pitch-min",
- pitch_min.smobbed_copy ());
- ambitus_p_->set_grob_property ("pitch-max",
- pitch_max.smobbed_copy ());
}
else if (Pitch::compare (pitch, pitch_max) > 0) // new max?
{
pitch_max = pitch;
- ambitus_p_->set_grob_property ("pitch-max",
- pitch_max.smobbed_copy ());
}
else if (Pitch::compare (pitch, pitch_min) < 0) // new min?
{
pitch_min = pitch;
- ambitus_p_->set_grob_property ("pitch-min",
- pitch_min.smobbed_copy ());
}
}
}
announce_grob (ambitus_p_, SCM_EOL);
}
+void
+Ambitus_engraver::finalize ()
+{
+ if (ambitus_p_)
+ {
+ if (Pitch::compare (pitch_min, pitch_max) <= 0)
+ {
+ ambitus_p_->set_grob_property ("pitch-min",
+ pitch_min.smobbed_copy ());
+ ambitus_p_->set_grob_property ("pitch-max",
+ pitch_max.smobbed_copy ());
+ }
+ else // have not seen any pitch, so forget about the ambitus
+ {
+ // Do not print a warning on empty ambitus range, since this
+ // most probably arises from an empty voice, such as shared
+ // global timesig/clef definitions.
+#if 0
+ ambitus_p_->warning("empty ambitus range [ignored]");
+#endif
+ ambitus_p_->suicide();
+ }
+ }
+}
+
ENTER_DESCRIPTION(Ambitus_engraver,
/* descr */ "",
/* creats*/ "Ambitus",
return SCM_EOL;
}
+ int p_min, p_max;
Pitch *pitch_min = unsmob_pitch (me->get_grob_property ("pitch-min"));
- int p_min = pitch_min->steps ();
+ if (!pitch_min)
+ {
+ me->programming_error("Ambitus: pitch_min undefined; assuming 0");
+ p_min = 0;
+ }
+ else
+ {
+ p_min = pitch_min->steps ();
+ }
Pitch *pitch_max = unsmob_pitch (me->get_grob_property ("pitch-max"));
- int p_max = pitch_max->steps ();
+ if (!pitch_max)
+ {
+ me->programming_error("Ambitus: pitch_max undefined; assuming 0");
+ p_max = 0;
+ }
+ else
+ {
+ p_max = pitch_max->steps ();
+ }
if (p_min > p_max)
{
- String message = "Ambitus: no range to output";
- me->warning (_ (message.ch_C ()));
- return SCM_EOL;
+ me->programming_error ("Ambitus: reverse range");
}
SCM c0 = me->get_grob_property ("centralCPosition");