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