]> git.donarmstrong.com Git - lilypond.git/blob - mi2mu/mudela-score.cc
release: 0.1.11
[lilypond.git] / mi2mu / mudela-score.cc
1 //
2 // mudela-score.cc -- implement Mudela_score
3 //
4 // copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
5
6 #include <assert.h>
7 #include "moment.hh"
8 #include "duration.hh"
9 #include "duration-convert.hh"
10 #include "mi2mu-global.hh"
11 #include "mudela-column.hh"
12 #include "mudela-item.hh"
13 #include "mudela-score.hh"
14 #include "mudela-staff.hh"
15 #include "mudela-stream.hh"
16
17 //static Mudela_key key_c (0, 0);
18 static Mudela_meter meter_4 (4, 2, 24, 8);
19 // useconds per 4: 250000 === 60 4 per minute
20 static Mudela_tempo tempo_60 (1000000);
21
22 Mudela_score::Mudela_score (int format_i, int tracks_i, int tempo_i)
23 {
24   format_i_ = format_i;
25   tracks_i_ = tracks_i;
26   tempo_i_ = tempo_i;
27   column_l_array_.push (new Mudela_column (this, Moment (0)));
28   //  mudela_key_l_ = &key_c;
29   mudela_key_l_ = 0;
30   mudela_meter_l_ = &meter_4;
31   mudela_tempo_l_ = &tempo_60;
32 }
33
34 Mudela_score::~Mudela_score()
35 {
36 }
37
38 void 
39 Mudela_score::add_item (Mudela_item* mudela_item_p)
40 {
41   mudela_staff_p_list_.bottom()->add_item (mudela_item_p);
42 }
43
44 void
45 Mudela_score::add_staff (Mudela_staff* mudela_staff_p)
46 {
47   mudela_staff_p_list_.bottom().add (mudela_staff_p);
48 }
49
50 Mudela_column*
51 Mudela_score::find_column_l (Moment mom)
52 {
53 #if 0
54   // should do binary search
55   for (int i = 0; i < column_l_array_.size (); i++ )
56     if ( column_l_array_[i]->at_mom () == mom )
57       return column_l_array_[i];
58   return 0;
59 #else
60   int upper_i = max (0, column_l_array_.size () - 1);
61   int lower_i = 0;
62   int i = 0; //upper_i;
63   while (1) 
64     {
65       Moment i_mom = column_l_array_ [i]->at_mom ();
66       if (i_mom == mom)
67         return column_l_array_ [i];
68       if (mom < i_mom)
69         upper_i = i;
70       else
71         lower_i = i;
72       if ((upper_i == lower_i) || (i == column_l_array_.size () - 1)) 
73         {
74           // we don't do inserts
75           assert (0);
76           Mudela_column* col_p = new Mudela_column (this, mom);
77           column_l_array_.push (col_p);
78           return col_p;
79         }
80       i = (upper_i + lower_i + 1 ) / 2;
81     }
82   assert (0);
83   return 0;
84 #endif
85 }
86
87 Mudela_column*
88 Mudela_score::get_column_l (Moment mom)
89 {
90   if ( column_l_array_ [column_l_array_.size() - 1]->at_mom () > mom )
91     {
92       error ("ugh");
93       exit (1);
94     }
95   if ( column_l_array_[column_l_array_.size() - 1]->at_mom () < mom )
96     column_l_array_.push (new Mudela_column (this, mom));
97
98   return column_l_array_ [column_l_array_.size() - 1];
99 }
100
101 void
102 Mudela_score::output (String filename_str)
103 {
104   LOGOUT(NORMAL_ver) << "Lily output to " << filename_str << " ..." << endl;
105   
106   // ugh, ugly midi type 1 fix
107   if  ( (mudela_staff_p_list_.size() == 1) && !mudela_staff_p_list_.top()->number_i_)
108     mudela_staff_p_list_.top()->number_i_ = 1;
109
110   int track_i = 0;
111   Mudela_stream mudela_stream (filename_str);
112   for  (PCursor<Mudela_staff*> i (mudela_staff_p_list_); i.ok(); i++) 
113     {
114       LOGOUT(NORMAL_ver) << "track " << track_i++ << ": " << flush;
115       i->output (mudela_stream);
116       mudela_stream << "\n";
117       LOGOUT(NORMAL_ver) << endl;
118     }
119
120   mudela_stream << "\\score{\n";
121   if  (mudela_staff_p_list_.size() > 1)
122     mudela_stream << "<\n\\multi 3;\n";
123   for  (PCursor<Mudela_staff*> i (mudela_staff_p_list_); i.ok(); i++) 
124     {
125       if  ( (mudela_staff_p_list_.size() != 1) 
126             &&  (i == mudela_staff_p_list_.top()))
127         continue;
128       mudela_stream << "\\melodic{ ";
129       mudela_stream << "\\$" << i->id_str();
130       mudela_stream << " }\n";
131     }
132   if  (mudela_staff_p_list_.size() > 1)
133     mudela_stream << ">\n";
134
135   mudela_stream << "\\paper{}\n";
136
137   mudela_stream << "\\midi{\n";
138   // let's not use silly 0 track
139   mudela_staff_p_list_.bottom()->mudela_tempo_p_->output (mudela_stream);
140   mudela_stream << "}\n";
141
142   mudela_stream << "}\n";
143 }
144
145 void
146 Mudela_score::process()
147 {
148   LOGOUT(NORMAL_ver) << "\nProcessing..." << endl;
149         
150   LOGOUT(DEBUG_ver) << "columns\n";
151   //  for  (PCursor<Mudela_column*> i (mudela_column_p_list_); i.ok(); i++)
152   //    LOGOUT(DEBUG_ver) << "At: " << i->at_mom() << "\n";
153
154   settle_columns();
155   filter_tempo();
156   quantify_columns();
157   quantify_durations();
158
159   LOGOUT(NORMAL_ver) << "\nCreating voices..." << endl;
160   int track_i = 0;
161   for  (PCursor<Mudela_staff*> i (mudela_staff_p_list_); i.ok(); i++)  
162     {
163       LOGOUT(NORMAL_ver) << "track " << track_i++ << ": " << flush;
164       i->process();
165       LOGOUT(NORMAL_ver) << endl;
166     }
167 }
168
169 void
170 Mudela_score::filter_tempo()
171 {
172   LOGOUT(NORMAL_ver) << "\nNOT Filtering tempo..." << endl;
173 }
174
175 void
176 Mudela_score::quantify_columns()
177 {
178   // ugh
179   if  (Duration_convert::no_quantify_b_s) 
180     {
181       LOGOUT(NORMAL_ver) << "\nNOT Quantifying columns..." << endl;
182       return;
183     }
184
185   LOGOUT(NORMAL_ver) << "\nQuantifying columns..." << endl;
186
187   int current_bar_i = 0;
188   Moment bar_mom = mudela_meter_l_->bar_mom();
189
190   int n = 5 >? Duration_convert::no_smaller_than_i_s;
191   n = Duration_convert::type2_i (n);
192   Moment s = Moment (1, n);
193   Moment sh = Moment (1, 2 * n);
194   for  (int i = 0; i < column_l_array_.size(); i++) 
195     {
196       column_l_array_ [i]->at_mom_ =
197         s * Moment( (int) ( (column_l_array_ [i]->at_mom()) / s));
198
199       int bar_i = (int) (column_l_array_ [i]->at_mom () / bar_mom) + 1;
200       if (bar_i > current_bar_i) 
201         {
202           LOGOUT (NORMAL_ver) << '[' << bar_i << ']' << flush; 
203           current_bar_i = bar_i;
204         }
205     }
206   LOGOUT(NORMAL_ver) << endl;
207 }
208
209 void
210 Mudela_score::quantify_durations()
211 {
212   //    LOGOUT(NORMAL_ver) << "\nQuantifying durations..." << endl;
213 }
214
215 void
216 Mudela_score::settle_columns()
217 {
218   //    LOGOUT(NORMAL_ver) << "\nNOT Settling columns..." << endl;
219   //    return;
220   LOGOUT(NORMAL_ver) << "\nSettling columns..." << endl;
221
222 #if 0
223   assert (!column_l_array_.size());
224   int n = mudela_column_p_list_.size();
225   // huh?
226   //    column_l_array_.set_size (n);
227   for  (PCursor<Mudela_column*> i (mudela_column_p_list_); i.ok(); i++)
228     column_l_array_.push (*i);
229 #endif
230
231   int n = column_l_array_.size();
232
233   int start_i = 0;
234   int end_i = 0;
235   Moment start_mom = 0;
236   Duration smallest_dur;
237   smallest_dur.durlog_i_ =  6;
238   Moment const noise_mom = Duration_convert::dur2_mom (smallest_dur)
239     / Moment (2);
240   for  (int i = 0; i < n; i++) 
241     {
242       if  (!start_i) 
243         {
244           start_i = end_i = i;
245           start_mom = column_l_array_ [i]->at_mom();
246           continue;
247         }
248
249       // find all columns within noise's distance
250       while  ( (i < n)
251                &&  (column_l_array_ [i]->at_mom() - start_mom < noise_mom))
252         end_i = ++i;
253
254       // bluntly set all to time of first in group
255       for  (int j = start_i; j < end_i; j++)
256         column_l_array_ [j]->at_mom_ = start_mom;
257
258       start_i = end_i = 0;
259     }
260 }
261