lilypond-1.5.37
[lilypond.git] / midi2ly / lilypond-staff.cc
blob481bc38417ad01214d452a7aa8083fd78c9c9c42
1 //
2 // lilypond-staff.cc -- implement Lilypond_staff
3 //
4 // (c) 1997--2001 Jan Nieuwenhuizen <janneke@gnu.org>
6 #include <assert.h>
7 #include <ctype.h>
8 #include "rational.hh"
9 #include "duration-convert.hh"
10 #include "string-convert.hh"
11 #include "midi2ly-proto.hh"
12 #include "midi2ly-global.hh"
13 #include "lilypond-column.hh"
14 #include "lilypond-item.hh"
15 #include "lilypond-staff.hh"
16 #include "lilypond-stream.hh"
17 #include "lilypond-voice.hh"
18 #include "lilypond-score.hh"
20 #include "killing-cons.tcc"
22 extern Lilypond_score* lilypond_score_l_g;
24 Lilypond_staff::Lilypond_staff (int number_i, String copyright_str, String track_name_str, String instrument_str)
26 number_i_ = number_i;
27 copyright_str_ = copyright_str;
28 instrument_str_ = instrument_str;
29 name_str_ = track_name_str;
30 lilypond_key_l_ = 0;
31 lilypond_time_signature_l_ = 0;
32 lilypond_tempo_l_ = 0;
35 void
36 Lilypond_staff::add_item (Lilypond_item* lilypond_item_p)
38 lilypond_item_p_list_.append (new Killing_cons <Lilypond_item> (lilypond_item_p, 0));
39 if (lilypond_item_p->lilypond_column_l_)
40 lilypond_item_p->lilypond_column_l_->add_item (lilypond_item_p);
42 /**
43 Walk ITEMS and find voices. Remove categorised items.
45 TODO:
47 * collect all channels into separate voices. Use chords for sim
48 notes on same channel.
49 * assume voices/assume chords modes.
52 void
53 Lilypond_staff::eat_voice (Cons_list<Lilypond_item>& items)
55 Lilypond_voice* voice_p = new Lilypond_voice (this);
56 lilypond_voice_p_list_.append (new Killing_cons<Lilypond_voice> (voice_p, 0));
58 Rational mom = 0;
60 Link_array<Lilypond_item> now_items;
61 for (Cons<Lilypond_item>** i = &items.head_; *i;)
63 while (*i && (*i)->car_->at_mom () < mom)
64 i = &(*i)->next_;
66 Lilypond_note* last_note = 0;
67 Link_array<Lilypond_item> now_items;
68 if (*i)
69 mom = (*i)->car_->at_mom ();
70 while (*i && (*i)->car_->at_mom () == mom)
72 Lilypond_note* note = dynamic_cast<Lilypond_note*> ((*i)->car_);
73 if (note && last_note
74 /* ugh, should sort out (whether to) channel before */
75 && (note->channel_i_ != last_note->channel_i_
76 || (note->duration_mom ()
77 != last_note->duration_mom ())))
78 break;
79 Cons<Lilypond_item>* c = items.remove_cons (i);
80 now_items.push (c->car_);
81 if (note)
82 last_note = note;
83 delete c;
86 if (now_items.size ())
87 mom = now_items.top ()->at_mom ();
88 if (last_note)
89 mom += last_note->duration_mom ();
91 voice_p->add_items (now_items);
95 String
96 Lilypond_staff::id_str ()
98 String id (name_str ());
99 char *cp = id.ch_l ();
100 char *end = cp + id.length_i ();
101 for (;cp < end; cp++)
103 if (!isalpha (*cp))
105 *cp = 'X';
108 return id;
111 String
112 Lilypond_staff::name_str ()
114 if (name_str_.length_i ())
115 return name_str_;
116 return String ("track") + to_str (char ('A' - 1 + number_i_));
121 void
122 Lilypond_staff::output (Lilypond_stream& lilypond_stream_r)
124 int c =0;
126 String trackbody = "";
127 for (Cons<Lilypond_voice>* i = lilypond_voice_p_list_.head_; i; i = i->next_)
129 String voicename = id_str () + "voice" + to_str (char (c + 'A'));
131 lilypond_stream_r << voicename << " = \\notes ";
133 trackbody += "\\context Voice = " + voicename + " \\" + voicename + "\n";
134 lilypond_stream_r << '\n';
135 i->car_->output (lilypond_stream_r);
136 c++;
137 lilypond_stream_r << '\n';
140 lilypond_stream_r << '\n';
141 lilypond_stream_r << _ ("% MIDI copyright:") << copyright_str_ << '\n';
142 lilypond_stream_r << _ ("% MIDI instrument:") << instrument_str_ << '\n';
143 lilypond_stream_r << id_str () << " = ";
144 lilypond_stream_r << "<\n" << trackbody << ">\n";
146 lilypond_stream_r << " % " << name_str () << '\n';
149 void
150 Lilypond_staff::output_lilypond_begin_bar (Lilypond_stream& lilypond_stream_r, Rational now_mom, int bar_i)
152 Rational bar_mom = lilypond_time_signature_l_->bar_mom ();
153 Rational into_bar_mom = now_mom - Rational (bar_i - 1) * bar_mom;
154 if (bar_i > 1)
156 if (!into_bar_mom)
157 lilypond_stream_r << "|\n";
159 lilypond_stream_r << "% " << String_convert::i2dec_str (bar_i, 0, ' ');
160 if (into_bar_mom)
161 lilypond_stream_r << ":" << Duration_convert::dur2_str (Duration_convert::mom2_dur (into_bar_mom));
162 lilypond_stream_r << '\n';
166 void
167 Lilypond_staff::process ()
170 group items into voices
173 assert (lilypond_score_l_g);
174 lilypond_key_l_ = lilypond_score_l_g->lilypond_key_l_;
175 lilypond_time_signature_l_ = lilypond_score_l_g->lilypond_time_signature_l_;
176 lilypond_tempo_l_ = lilypond_score_l_g->lilypond_tempo_l_;
178 Cons_list<Lilypond_item> items;
179 for (Cons<Lilypond_item>* i = lilypond_item_p_list_.head_; i; i = i->next_)
180 items.append (new Cons<Lilypond_item> (i->car_, 0));
182 while (items.size_i ())
183 eat_voice (items);