bool
Part_combine_music_iterator::ok () const
{
- //hmm
return first_iter_p_->ok () || second_iter_p_->ok ();
}
error (_f ("none of these in my family: `%s'", to_id.ch_C ()));
}
-void
-Part_combine_music_iterator::process (Moment m)
-{
- /*
- TODO:
- - Use three named contexts (be it Thread or Voice): one, two, solo.
- Let user pre-set (pushproperty) stem direction, remove
- dynamic-engraver, and such.
- - staff-combiner must switch only on per-measure basis (maybe even on
- per-line-basis, but that's not feasible). Maybe set minimum lengths
- of matching rhythm for combine/split?
- */
-
- Part_combine_music const * p = dynamic_cast<Part_combine_music const* > (music_l_);
-
- Moment now = pending_moment ();
-
- Array<Musical_pitch> first_pitches;
- Array<Duration> first_durations;
- if (first_iter_p_->ok ())
+static void
+get_music_info (Moment m, Music_iterator* iter, Array<Musical_pitch> *pitches, Array<Duration> *durations)
+{
+ if (iter->ok ())
{
- /* get_music () also performs next, modifying iterator */
- Music_iterator *mi = first_iter_p_->clone ();
- for (SCM i = mi->get_music (now); gh_pair_p (i); i = gh_cdr (i))
+ for (SCM i = iter->get_music (m); gh_pair_p (i); i = gh_cdr (i))
{
Music *m = unsmob_music (gh_car (i));
if (Melodic_req *r = dynamic_cast<Melodic_req *> (m))
- first_pitches.push (r->pitch_);
+ pitches->push (r->pitch_);
if (Rhythmic_req *r = dynamic_cast<Rhythmic_req *> (m))
- first_durations.push (r->duration_);
+ durations->push (r->duration_);
}
- delete mi;
}
+}
- Array<Musical_pitch> second_pitches;
- Array<Duration> second_durations;
- if (second_iter_p_->ok ())
- {
- Music_iterator *mi = second_iter_p_->clone ();
- for (SCM i = mi->get_music (now); gh_pair_p (i); i = gh_cdr (i))
- {
- Music *m = unsmob_music (gh_car (i));
- if (Melodic_req *r = dynamic_cast<Melodic_req *> (m))
- second_pitches.push (r->pitch_);
- if (Rhythmic_req *r = dynamic_cast<Rhythmic_req *> (m))
- second_durations.push (r->duration_);
- }
- delete mi;
- }
+int
+Part_combine_music_iterator::get_state (Moment)
+{
+ int state = UNKNOWN;
+ Part_combine_music const *p = dynamic_cast<Part_combine_music const* > (music_l_);
+ Translator_group *first_translator = first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "one");
+
+ SCM s = first_translator->get_property (ly_symbol2scm ("changeMoment"));
+ Moment change_mom = *unsmob_moment (gh_car (s));
+ Moment diff_mom = *unsmob_moment (gh_cdr (s));
- SCM interval = SCM_BOOL_F;
- if (first_pitches.size () && second_pitches.size ())
- {
- first_pitches.sort (Musical_pitch::compare);
- second_pitches.sort (Musical_pitch::compare);
- interval = gh_int2scm (first_pitches.top ().steps ()
- - second_pitches[0].steps ());
- }
- if (first_durations.size ())
- {
- first_durations.sort (Duration::compare);
- Moment new_until = now + first_durations.top ().length_mom ();
- if (new_until > first_until_)
- first_until_ = new_until;
- }
+ Moment now = pending_moment ();
- if (second_durations.size ())
+ if (!now.mod_rat (change_mom))
{
- second_durations.sort (Duration::compare);
- Moment new_until = now + second_durations.top ().length_mom ();
- if (new_until > second_until_)
- second_until_ = new_until;
- }
+ SCM interval = SCM_BOOL_F;
+ Moment first_mom = first_until_ - now;
+ Moment second_mom = second_until_ - now;
+
+ bool first = true;
+ Music_iterator *first_iter = first_iter_p_->clone ();
+ Music_iterator *second_iter = second_iter_p_->clone ();
+ while ((first_mom <? second_mom) < diff_mom
+ && (first_iter->ok () || second_iter->ok ()))
+ {
+ Moment m;
+ if (!second_iter->ok ())
+ m = first_iter->pending_moment ();
+ else if (!first_iter->ok ())
+ m = second_iter->pending_moment ();
+ else
+ m = first_iter->pending_moment () <? second_iter->pending_moment ();
+
+ Array<Musical_pitch> first_pitches;
+ Array<Duration> first_durations;
+ get_music_info (m, first_iter, &first_pitches, &first_durations);
+
+ Array<Musical_pitch> second_pitches;
+ Array<Duration> second_durations;
+ get_music_info (m, second_iter, &second_pitches, &second_durations);
+
+ if (first_pitches.size () && second_pitches.size ())
+ {
+ first_pitches.sort (Musical_pitch::compare);
+ second_pitches.sort (Musical_pitch::compare);
+ interval = gh_int2scm (first_pitches.top ().steps ()
+ - second_pitches[0].steps ());
+ }
+ if (first_durations.size ())
+ {
+ first_durations.sort (Duration::compare);
+ first_mom += first_durations.top ().length_mom ();
+ if (first)
+ first_until_ = first_mom + now;
+ }
+
+ if (second_durations.size ())
+ {
+ second_durations.sort (Duration::compare);
+ second_mom += second_durations.top ().length_mom ();
+ if (first)
+ second_until_ = second_mom + now;
+ }
+ first = false;
#if 0 /* DEBUG */
- printf ("now: %s\n", now.str ().ch_C ());
- printf ("first: ");
- for (int i = 0; i < first_pitches.size (); i++)
- {
- printf ("%s, ", first_pitches[i].str ().ch_C ());
- }
- printf ("\nsecond: ");
- for (int i = 0; i < second_pitches.size (); i++)
- {
- printf ("%s, ", second_pitches[i].str ().ch_C ());
- }
- printf ("\n");
+ printf ("now: %s\n", now.str ().ch_C ());
+ printf ("first: ");
+ for (int i = 0; i < first_pitches.size (); i++)
+ {
+ printf ("%s, ", first_pitches[i].str ().ch_C ());
+ }
+ printf ("\nsecond: ");
+ for (int i = 0; i < second_pitches.size (); i++)
+ {
+ printf ("%s, ", second_pitches[i].str ().ch_C ());
+ }
+ printf ("\n");
#endif
- Translator_group * fir = first_iter_p_->report_to_l ();
- Translator_group * sir = second_iter_p_->report_to_l ();
-
- bool solo_b = (first_pitches.empty () != second_pitches.empty ())
- && !(first_until_ > now && second_until_ > now);
-
- bool unirhythm_b = !solo_b && !compare (&first_durations, &second_durations);
- bool unison_b = unirhythm_b && !first_pitches.empty ()
- &&!compare (&first_pitches, &second_pitches);
- bool unisilence_b = unirhythm_b && first_pitches.empty ();
+ if (!first_pitches.empty () && second_pitches.empty ()
+ && !(second_until_ > now))
+ {
+ state |= UNRELATED;
+ state &= ~UNISILENCE;
+ if (!(state & ~(UNRELATED | SOLO1 | UNISILENCE)))
+ state |= SOLO1;
+ }
+ else
+ state &= ~SOLO1;
+
+ if (first_pitches.empty () && !second_pitches.empty ()
+ && !(first_until_ > now))
+ {
+ state |= UNRELATED;
+ state &= ~UNISILENCE;
+ if (!(state & ~(UNRELATED | SOLO2 | UNISILENCE)))
+ state |= SOLO2;
+ }
+ else
+ state &= ~SOLO2;
+
+ if (!compare (&first_durations, &second_durations))
+ {
+ state &= ~UNISILENCE;
+ if (!(state & ~(UNIRHYTHM | UNISON)))
+ state |= UNIRHYTHM;
+ }
+ else
+ state &= ~(UNIRHYTHM | UNISILENCE);
+
+ if (!first_pitches.empty ()
+ &&!compare (&first_pitches, &second_pitches))
+ {
+ state &= ~UNISILENCE;
+ if (!(state & ~(UNIRHYTHM | UNISON)))
+ state |= UNISON;
+ }
+ else
+ state &= ~(UNISON);
+
+ if (first_pitches.empty () && second_pitches.empty ())
+ {
+ if (!(state & ~(UNIRHYTHM | UNISILENCE)))
+ state |= UNISILENCE;
+ }
+ else
+ state &= ~(UNISILENCE);
+
+ if (gh_number_p (interval))
+ {
+ SCM s = first_translator->get_property (ly_symbol2scm ("splitInterval"));
+ int i = gh_scm2int (interval);
+ if (gh_pair_p (s)
+ && gh_number_p (gh_car (s))
+ && gh_number_p (gh_cdr (s))
+ && i >= gh_scm2int (gh_car (s))
+ && i <= gh_scm2int (gh_cdr (s)))
+ {
+ if (!(state & ~(SPLIT_INTERVAL | UNIRHYTHM | UNISON)))
+ state |= SPLIT_INTERVAL;
+ }
+ else
+ state &= ~(SPLIT_INTERVAL);
+ }
+
+#if 0
+ Moment next = (first_mom <? second_mom) + now;
+ if (first_iter->ok ())
+ first_iter->skip (next);
+ if (second_iter->ok ())
+ second_iter->skip (next);
+#else
+ if (first_iter->ok ())
+ first_iter->skip (first_mom + now);
+ if (second_iter->ok ())
+ second_iter->skip (second_mom + now);
+#endif
+ }
+ delete first_iter;
+ delete second_iter;
+ }
+ return state;
+}
- Translator_group * fd = fir->find_create_translator_l (p->what_str_, "one");
- Translator_group * sd = sir->find_create_translator_l (p->what_str_, "two");
+void
+Part_combine_music_iterator::process (Moment m)
+{
- bool split_interval_b = false;
- if (gh_number_p (interval))
- {
- SCM s = fd->get_property (ly_symbol2scm ("splitInterval"));
- int i = gh_scm2int (interval);
- if (gh_pair_p (s)
- && gh_number_p (gh_car (s))
- && gh_number_p (gh_cdr (s))
- && i >= gh_scm2int (gh_car (s))
- && i <= gh_scm2int (gh_cdr (s)))
- split_interval_b = true;
- }
+ /*
+ TODO:
+ - Use three named contexts (be it Thread or Voice): one, two, solo.
+ Let user pre-set (pushproperty) stem direction, remove
+ dynamic-engraver, and such.
+ */
+
+ int state = get_state (m);
+ if (state)
+ state_ = state;
+ else
+ state = state_;
+
+ Part_combine_music const *p = dynamic_cast<Part_combine_music const* > (music_l_);
bool combined_b = first_iter_p_->report_to_l ()->daddy_trans_l_
== second_iter_p_->report_to_l ()->daddy_trans_l_;
String to_id = combined_b ? "one" : "two";
- if ((!unirhythm_b && combined_b)
- || (split_interval_b && combined_b)
- || (solo_b && combined_b)
- /*|| (unisilence_b && combined_b) */
- || ((unirhythm_b || unison_b || unisilence_b)
- && !combined_b && !split_interval_b && !solo_b))
+ if ((!(state & UNIRHYTHM) && combined_b)
+ || ((state & SPLIT_INTERVAL) && combined_b)
+ || ((state & (SOLO1 | SOLO2)) && combined_b)
+ || (((state & (UNIRHYTHM | UNISILENCE))
+ && !combined_b && !(state & SPLIT_INTERVAL)
+ && !(state & (SOLO1 | SOLO2)))))
{
combined_b = !combined_b;
to_id = combined_b ? "one" : "two";
change_to (second_iter_p_, p->what_str_, to_id);
}
- if (!combined_b)
- sir = second_iter_p_->report_to_l ();
-
- SCM b = unirhythm_b ? SCM_BOOL_T : SCM_BOOL_F;
- fd->set_property ("unirhythm", b);
- sd->set_property ("unirhythm", b);
-
- b = split_interval_b ? SCM_BOOL_T : SCM_BOOL_F;
- fd->set_property ("split-interval", b);
- sd->set_property ("split-interval", b);
- b = unisilence_b ? SCM_BOOL_T : SCM_BOOL_F;
- fd->set_property ("unisilence", b);
- sd->set_property ("unisilence", b);
+ Translator_group *first_translator = first_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "one");
+ Translator_group *second_translator = second_iter_p_->report_to_l ()->find_create_translator_l (p->what_str_, "two");
- b = unison_b ? SCM_BOOL_T : SCM_BOOL_F;
- fd->set_property ("unison", b);
- sd->set_property ("unison", b);
-
- b = solo_b ? SCM_BOOL_T : SCM_BOOL_F;
- if (first_pitches.size ())
- {
- fd->set_property ("solo", b);
- sd->set_property ("solo", SCM_BOOL_F);
- }
-
- if (second_pitches.size ())
- {
- fd->set_property ("solo", SCM_BOOL_F);
- sd->set_property ("solo", b);
- }
+ /*
+ hmm
+ */
+ SCM b = (state & UNIRHYTHM) ? SCM_BOOL_T : SCM_BOOL_F;
+ first_translator->set_property ("unirhythm", b);
+ second_translator->set_property ("unirhythm", b);
+
+ b = (state & SPLIT_INTERVAL) ? SCM_BOOL_T : SCM_BOOL_F;
+ first_translator->set_property ("split-interval", b);
+ second_translator->set_property ("split-interval", b);
+
+ b = (state & UNISILENCE) ? SCM_BOOL_T : SCM_BOOL_F;
+ first_translator->set_property ("unisilence", b);
+ second_translator->set_property ("unisilence", b);
+
+ // difference in definition...
+ //b = ((state & UNISON) ? SCM_BOOL_T : SCM_BOOL_F;
+ b = ((state & UNISON) && (state & UNIRHYTHM)) ? SCM_BOOL_T : SCM_BOOL_F;
+ first_translator->set_property ("unison", b);
+ second_translator->set_property ("unison", b);
+
+ SCM b1 = (state & SOLO1) ? SCM_BOOL_T : SCM_BOOL_F;
+ SCM b2 = (state & SOLO1) ? SCM_BOOL_T : SCM_BOOL_F;
+ first_translator->set_property ("solo", b1);
+ second_translator->set_property ("solo", b2);
if (first_iter_p_->ok ())
first_iter_p_->process (m);