2 // mudela-staff.cc -- implement Mudela_staff
4 // copyright 1997 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "duration-convert.hh"
10 #include "string-convert.hh"
11 #include "midi2ly-proto.hh"
12 #include "midi2ly-global.hh"
13 #include "mudela-column.hh"
14 #include "mudela-item.hh"
15 #include "mudela-staff.hh"
16 #include "mudela-stream.hh"
17 #include "mudela-voice.hh"
18 #include "mudela-score.hh"
20 #include "killing-cons.tcc"
22 extern Mudela_score* mudela_score_l_g;
24 Mudela_staff::Mudela_staff (int number_i, String copyright_str, String track_name_str, String instrument_str)
27 copyright_str_ = copyright_str;
28 instrument_str_ = instrument_str;
29 name_str_ = track_name_str;
31 mudela_time_signature_l_ = 0;
36 Mudela_staff::add_item (Mudela_item* mudela_item_p)
38 mudela_item_p_list_.append (new Killing_cons <Mudela_item> (mudela_item_p, 0));
39 if (mudela_item_p->mudela_column_l_)
40 mudela_item_p->mudela_column_l_->add_item (mudela_item_p);
43 Walk ITEMS and find voices. Remove categorised items.
45 TODO: collect all channels into separate voices. Use chords for sim
46 notes on same channel.
50 Mudela_staff::eat_voice (Cons_list<Mudela_item>& items)
52 Mudela_voice* voice_p = new Mudela_voice (this);
53 mudela_voice_p_list_.append (new Killing_cons<Mudela_voice> (voice_p, 0));
55 // Moment mom = items.top ()->at_mom ();
58 for (Cons<Mudela_item>** pp = &items.head_; *pp;)
60 Cons<Mudela_item>* i = *pp;
61 if (i->car_->at_mom () > mom)
63 Moment dur = i->car_->at_mom () - mom;
65 Mudela_column* start = mudela_score_l_g->find_column_l (mom);
66 voice_p->add_item (new Mudela_skip (start, dur));
67 mom = i->car_->at_mom ();
68 continue; // unnecessary
71 Link_array<Mudela_item> now_items;
72 for (Cons<Mudela_item> *cp = i; cp && cp->car_->at_mom () == mom; cp = cp->next_)
73 now_items.push (i->car_);
75 Mudela_note * last_note = dynamic_cast<Mudela_note*> (voice_p->last_item_l_);
76 Link_array<Mudela_item> candidates;
78 for (int i=0; last_note && i < now_items.size (); i++)
80 Mudela_note * now_note = dynamic_cast<Mudela_note*> (now_items[i]);
81 if (now_note && last_note->channel_i_ != now_note->channel_i_)
82 candidates.push (now_note);
85 if (candidates.size())
87 now_items = candidates;
90 Mudela_item * which = 0;
91 if (now_items.size () > 1)
93 int mindiff = 100000; // ugh
94 for (int i=0; last_note && i < now_items.size (); i++)
96 Mudela_note *nt = dynamic_cast<Mudela_note*> (now_items[i]);
99 int diff = abs (last_note->pitch_i_ - nt->pitch_i_ );
103 which = now_items [i];
107 if (which && mindiff > 18) // more than 1.5 octaves apart. Don't put in same voice.
112 else if (now_items.size () == 1)
113 which = now_items[0];
117 while ((*pp)->car_ != which)
120 mom += (*pp)->car_->duration_mom ();
121 Cons<Mudela_item>* c = items.remove_cons (pp);
122 voice_p->add_item (c->car_);
134 Mudela_staff::id_str ()
136 String id (name_str ());
137 char *cp = id.ch_l ();
138 char *end = cp + id.length_i ();
139 for (;cp < end; cp++)
150 Mudela_staff::name_str ()
152 if (name_str_.length_i ())
154 return String ("track") + to_str (char ('A' - 1 + number_i_));
160 Mudela_staff::output (Mudela_stream& mudela_stream_r)
164 String trackbody = "";
165 for (Cons<Mudela_voice>* i = mudela_voice_p_list_.head_; i; i = i->next_)
167 String voicename = id_str () + "voice" + to_str (char (c + 'A'));
169 mudela_stream_r << voicename << " = \\notes ";
171 trackbody += "\\" + voicename + "\n";
173 mudela_stream_r << "\n";
174 i->car_->output (mudela_stream_r);
178 mudela_stream_r << _ ("% MIDI copyright:") << copyright_str_ << '\n';
179 mudela_stream_r << _ ("% MIDI instrument:") << instrument_str_ << '\n';
180 mudela_stream_r << id_str () << " = ";
181 mudela_stream_r << "<\n " << trackbody << " >\n";
183 mudela_stream_r << " % " << name_str () << '\n';
187 Mudela_staff::output_mudela_begin_bar (Mudela_stream& mudela_stream_r, Moment now_mom, int bar_i)
189 Moment bar_mom = mudela_time_signature_l_->bar_mom ();
190 Moment into_bar_mom = now_mom - Moment (bar_i - 1) * bar_mom;
194 mudela_stream_r << "|\n";
196 mudela_stream_r << "% " << String_convert::i2dec_str (bar_i, 0, ' ');
198 mudela_stream_r << ":" << Duration_convert::dur2_str (Duration_convert::mom2_dur (into_bar_mom));
199 mudela_stream_r << '\n';
203 #if 0 // not used for now
205 Mudela_staff::output_mudela_rest (Mudela_stream& mudela_stream_r, Moment begin_mom, Moment end_mom)
207 Moment bar_mom = mudela_time_signature_l_->bar_mom ();
208 Moment now_mom = begin_mom;
210 int begin_bar_i = (int) (now_mom / bar_mom) + 1;
211 int end_bar_i = (int) (end_mom / bar_mom) + 1;
213 if (end_bar_i == begin_bar_i)
215 output_mudela_rest_remain (mudela_stream_r, end_mom - begin_mom);
219 // multiple bars involved
220 int bar_i = (int) (now_mom / bar_mom) + 1;
223 Moment begin_bar_mom = Moment (begin_bar_i - 1) * bar_mom;
224 if (now_mom > begin_bar_mom)
226 int next_bar_i = (int) (now_mom / bar_mom) + 2;
227 Moment next_bar_mom = Moment (next_bar_i - 1) * bar_mom;
228 assert (next_bar_mom <= end_mom);
230 Moment remain_mom = next_bar_mom - now_mom;
231 if (remain_mom > Moment (0))
233 output_mudela_rest_remain (mudela_stream_r, remain_mom);
234 now_mom += remain_mom;
237 bar_i = check_end_bar_i (now_mom, bar_i);
241 int count_i = end_bar_i - bar_i;
242 for (int i = 0; i < count_i; i++)
244 int begin_bar_i = check_begin_bar_i (now_mom, bar_i);
246 output_mudela_begin_bar (mudela_stream_r, now_mom, begin_bar_i);
247 mudela_stream_r << "r1 ";
248 // *mudela_stream_r.os_p_ << flush;
250 LOGOUT (NORMAL_ver) << begin_bar_i << flush;
251 bar_i = check_end_bar_i (now_mom, bar_i);
255 // use "int i" here, and gcc 2.7.2 hits internal compiler error
256 int ii = check_begin_bar_i (now_mom, bar_i);
258 output_mudela_begin_bar (mudela_stream_r, now_mom, ii);
260 // bar_i = check_end_bar_i (now_mom, bar_i);
262 Moment remain_mom = end_mom - Moment (end_bar_i - 1) * bar_mom;
263 if (remain_mom > Moment (0))
265 output_mudela_rest_remain (mudela_stream_r, remain_mom);
266 now_mom += remain_mom;
268 assert (now_mom == end_mom);
272 Mudela_staff::output_mudela_rest_remain (Mudela_stream& mudela_stream_r, Moment mom)
274 if (Duration_convert::no_quantify_b_s)
276 Duration dur = Duration_convert::mom2_dur (mom);
277 mudela_stream_r << "r" << dur.str () << " ";
278 // assert (mom == dur.mom ());
279 assert (mom == dur.length ());
283 Duration dur = Duration_convert::mom2standardised_dur (mom);
285 mudela_stream_r << "r" << dur.str () << " ";
291 Mudela_staff::process ()
294 group items into voices
297 assert (mudela_score_l_g);
298 mudela_key_l_ = mudela_score_l_g->mudela_key_l_;
299 mudela_time_signature_l_ = mudela_score_l_g->mudela_time_signature_l_;
300 mudela_tempo_l_ = mudela_score_l_g->mudela_tempo_l_;
302 Cons_list<Mudela_item> items;
303 for (Cons<Mudela_item>* i = mudela_item_p_list_.head_; i; i = i->next_)
304 items.append (new Cons<Mudela_item> (i->car_, 0));
306 while (items.size_i ())