]> git.donarmstrong.com Git - lilypond.git/blob - lily/beaming-pattern.cc
Merge branch 'lilypond/translation' of ssh://git.sv.gnu.org/srv/git/lilypond into...
[lilypond.git] / lily / beaming-pattern.cc
1 /*
2   beaming-pattern.cc -- implement Beam_rhythmic_element, Beaming_pattern
3
4   A Beaming_pattern object takes a set of stems at given moments and calculates
5   the pattern of their beam. That is, it works out, for each stem, how many
6   beams should be connected to the right and left sides of that stem. In
7   calculating this, Beaming_pattern takes into account
8    - the rhythmic position of the stems
9    - the options that are defined in Beaming_options
10
11   source file of the GNU LilyPond music typesetter
12
13   (c) 1999--2009 Han-Wen Nienhuys <hanwen@xs4all.nl>
14 */
15
16 #include "context.hh"
17 #include "beam-settings.hh"
18 #include "beaming-pattern.hh"
19
20 /*
21   Represents a stem belonging to a beam. Sometimes (for example, if the stem
22   belongs to a rest and stemlets aren't used) the stem will be invisible.
23
24   The rhythmic_importance_ of an element tells us the significance of the
25   moment at which this element occurs. For example, an element that occurs at
26   a beat is more significant than one that doesn't. Smaller number are
27   more important. The rhythmic_importance_ is decided and filled in by
28   Beaming_pattern. A rhythmic_importance_ smaller than zero has extra
29   significance: it represents the start of a beat and therefore beams may
30   need to be subdivided.
31 */
32 Beam_rhythmic_element::Beam_rhythmic_element ()
33 {
34   start_moment_ = 0;
35   rhythmic_importance_ = 0;
36   beam_count_drul_[LEFT] = 0;
37   beam_count_drul_[RIGHT] = 0;
38   invisible_ = false;
39
40 }
41
42 Beam_rhythmic_element::Beam_rhythmic_element (Moment m, int i, bool inv)
43 {
44   start_moment_ = m;
45   rhythmic_importance_ = 0;
46   beam_count_drul_[LEFT] = i;
47   beam_count_drul_[RIGHT] = i;
48   invisible_ = inv;
49 }
50
51 void
52 Beam_rhythmic_element::de_grace ()
53 {
54   if (start_moment_.grace_part_)
55     {
56       start_moment_.main_part_ = start_moment_.grace_part_;
57       start_moment_.grace_part_ = 0;
58     }
59 }
60
61 int
62 Beam_rhythmic_element::count (Direction d) const
63 {
64   return beam_count_drul_[d];
65 }
66
67 /*
68   Finds the appropriate direction for the flags at the given index that
69   hang below the neighbouring flags. If
70   the stem has no more flags than either of its neighbours, this returns
71   CENTER.
72 */
73 Direction
74 Beaming_pattern::flag_direction (Beaming_options const &options, vsize i) const
75 {
76   // The extremal stems shouldn't be messed with, so it's appropriate to
77   // return CENTER here also.
78   if (i == 0 || i == infos_.size () - 1)
79     return CENTER;
80
81   int count = infos_[i].count (LEFT); // Both directions should still be the same
82   int left_count = infos_[i-1].count (RIGHT);
83   int right_count = infos_[i+1].count (LEFT);
84
85   // If we are told to subdivide beams and we are next to a beat, point the
86   // beamlet away from the beat.
87   if (options.subdivide_beams_)
88     {
89       if (infos_[i].rhythmic_importance_ < 0)
90         return RIGHT;
91       else if (infos_[i+1].rhythmic_importance_ < 0)
92         return LEFT;
93     }
94
95   if (count <= left_count && count <= right_count)
96     return CENTER;
97
98   // Try to avoid sticking-out flags as much as possible by pointing my flags
99   // at the neighbour with the most flags.
100   else if (right_count > left_count)
101     return RIGHT;
102   else if (left_count > right_count)
103     return LEFT;
104
105   // If all else fails, point the beamlet away from the important moment.
106   return (infos_[i].rhythmic_importance_ <= infos_[i+1].rhythmic_importance_) ? RIGHT : LEFT;
107 }
108
109 void
110 Beaming_pattern::de_grace ()
111 {
112   for (vsize i = 0; i < infos_.size (); i ++)
113     {
114       infos_[i].de_grace ();
115     }
116 }
117
118 void
119 Beaming_pattern::beamify (Beaming_options const &options)
120 {
121   unbeam_invisible_stems ();
122
123   if (infos_.size () <= 1)
124     return;
125
126   if (infos_[0].start_moment_.grace_part_)
127     de_grace ();
128
129   if (infos_[0].start_moment_ < Moment (0))
130     for (vsize i = 0; i < infos_.size (); i++)
131       infos_[i].start_moment_ += options.measure_length_;
132
133   find_rhythmic_importance (options);
134
135   for (vsize i = 1; i < infos_.size () - 1; i++)
136     {
137       Direction non_flag_dir = other_dir (flag_direction (options, i));
138       if (non_flag_dir)
139         {
140           int importance = (non_flag_dir == LEFT)
141             ? infos_[i].rhythmic_importance_ : infos_[i+1].rhythmic_importance_;
142           int count = (importance < 0 && options.subdivide_beams_)
143             ? 1 : min (infos_[i].count (non_flag_dir),
144                        infos_[i+non_flag_dir].count (-non_flag_dir));
145
146           infos_[i].beam_count_drul_[non_flag_dir] = count;
147         }
148     }
149 }
150
151 void
152 Beaming_pattern::find_rhythmic_importance (Beaming_options const &options)
153 {
154   Moment measure_pos (0);
155   SCM grouping = options.grouping_;
156   vsize i = 0;
157
158   // Mark the importance of stems that start at a beat or a beat group.
159   while (i < infos_.size ())
160     {
161       // If a beat grouping is not specified, default to 2 beats per group.
162       int count = 2;
163       if (scm_is_pair (grouping))
164         {
165           count = scm_to_int (scm_car (grouping));
166           grouping = scm_cdr (grouping);
167         }
168
169       // Mark the start of this beat group
170       if (infos_[i].start_moment_ == measure_pos)
171         infos_[i].rhythmic_importance_ = -2;
172
173       // Mark the start of each beat up to the end of this beat group.
174       for (int beat = 1; beat <= count; beat++)
175         {
176           Moment next_measure_pos = measure_pos + options.beat_length_;
177
178           while (i < infos_.size () && infos_[i].start_moment_ < next_measure_pos)
179             {
180               Moment dt = infos_[i].start_moment_ - measure_pos;
181
182               // The rhythmic importance of a stem between beats depends on its fraction
183               // of a beat: those stems with a lower denominator are deemed more
184               // important.
185               // FIXME: This is not the right way to do things for tuplets. For example,
186               // in an 8th-note triplet with a quarter-note beat, 1/3 of a beat should be
187               // more important than 1/2.
188               if (infos_[i].rhythmic_importance_ >= 0)
189                 infos_[i].rhythmic_importance_ = (dt / options.beat_length_).den ();
190
191               i++;
192             }
193
194           measure_pos = next_measure_pos;
195           if (i < infos_.size () && infos_[i].start_moment_ == measure_pos)
196             infos_[i].rhythmic_importance_ = -1;
197         }
198     }
199 }
200
201
202 /*
203   Invisible stems should be treated as though they have the same number of
204   beams as their least-beamed neighbour. Here we go through the stems and
205   modify the invisible stems to satisfy this requirement.
206 */
207 void
208 Beaming_pattern::unbeam_invisible_stems ()
209 {
210   for (vsize i = 1; i < infos_.size (); i++)
211     if (infos_[i].invisible_)
212       {
213         int b = min (infos_[i].count (LEFT), infos_[i-1].count (LEFT));
214         infos_[i].beam_count_drul_[LEFT] = b;
215         infos_[i].beam_count_drul_[RIGHT] = b;
216       }
217
218   for (vsize i = infos_.size (); i--;)
219     if (infos_[i].invisible_)
220       {
221         int b = min (infos_[i].count (LEFT), infos_[i+1].count (LEFT));
222         infos_[i].beam_count_drul_[LEFT] = b;
223         infos_[i].beam_count_drul_[RIGHT] = b;
224       }
225 }
226
227
228 void
229 Beaming_pattern::add_stem (Moment m, int b, bool invisible)
230 {
231   infos_.push_back (Beam_rhythmic_element (m, b, invisible));
232 }
233
234 Beaming_pattern::Beaming_pattern ()
235 {
236 }
237
238 int
239 Beaming_pattern::beamlet_count (int i, Direction d) const
240 {
241   return infos_.at (i).beam_count_drul_[d];
242 }
243
244 void
245 Beaming_options::from_context (Context *context)
246 {
247   grouping_ = ly_beat_grouping (context->self_scm ());
248   subdivide_beams_ = to_boolean (context->get_property ("subdivideBeams"));
249   beat_length_ = robust_scm2moment (context->get_property ("beatLength"), Moment (1, 4));
250   measure_length_ = robust_scm2moment (context->get_property ("measureLength"), Moment (4, 4));
251 }
252
253 Beaming_options::Beaming_options ()
254 {
255   grouping_ = SCM_EOL;
256   subdivide_beams_ = false;
257 }