]> git.donarmstrong.com Git - lilypond.git/blob - mi2mu/midi-track.cc
436bec8aa3d2bfcae85ab77dabdd44b0123329ed
[lilypond.git] / mi2mu / midi-track.cc
1 //
2 // midi-track.cc -- implement Midi_track
3 //
4 // copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
5
6 #include "mi2mu.hh"
7
8 Midi_track::Midi_track( int number_i, String copyright_str, String track_name_str, String instrument_str )
9 {
10         number_i_ = number_i;
11         copyright_str_ = copyright_str;
12         instrument_str_ = instrument_str;
13         if ( track_name_str.length_i() )
14                 name_str_ = track_name_str;
15         else
16                 name_str_ = String( "track" ) + String( number_i_ );
17         midi_time_p_ = new Midi_time( 4, 2, 24, 8 );
18         midi_tempo_p_ = new Midi_tempo( 1000000 );
19         tcol_p_list_.bottom().add( new Track_column( Moment( 0 ) ) );
20 }
21
22 Midi_track::~Midi_track()
23 {
24         delete midi_time_p_;
25         delete midi_tempo_p_;
26 }
27
28 void
29 Midi_track::add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
30 {
31         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
32                 if ( i->begin_mom() == mom ) {
33                         tor( DEBUG_ver ) << "open_voices (" << open_voices_r.size() << "): +1\n";
34                         open_voices_r.bottom().add( *i );
35                 }
36 }
37
38 void
39 Midi_track::add_event( Moment mom, Midi_event* midi_event_p )
40 {
41         if ( ! midi_event_p )
42                 return;
43         tcol_l( mom - midi_event_p->mom() )->add_event( midi_event_p );
44 }
45
46 int
47 Midi_track::check_begin_bar_i( Moment now_mom, int open_bar_i )
48 {
49         Moment bar_mom = midi_time_p_->bar_mom();
50         int bar_i = (int)( now_mom / bar_mom ) + 1;
51         if ( bar_i > open_bar_i ) { 
52                 tor( NORMAL_ver ) << '[' << flush; 
53                 return bar_i;
54         }
55         return 0;
56 }
57
58 int
59 Midi_track::check_end_bar_i( Moment now_mom, int open_bar_i )
60 {
61         Moment bar_mom = midi_time_p_->bar_mom();
62         int bar_i = (int)( now_mom / bar_mom ) + 1;
63         if ( bar_i > open_bar_i ) {
64                 tor( NORMAL_ver ) << ']' << flush; 
65                 return bar_i;
66         }
67         return open_bar_i;
68 }
69
70 Moment
71 Midi_track::end_mom()
72 {
73         // heu..
74         Moment mom = 0.0;
75         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ ) 
76                 mom = i->end_mom() >? mom;
77         return mom;
78 }
79
80 Midi_voice*
81 Midi_track::get_free_midi_voice_l( Moment mom )
82 {
83         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
84                 if ( i->end_mom() == mom )
85                         return *i;
86
87         Midi_voice* midi_voice_p = new Midi_voice( mom );
88         Midi_voice* midi_voice_l = midi_voice_p;
89         midi_voice_p_list_.bottom().add( midi_voice_p );
90         return midi_voice_l; 
91 }
92
93 // too much red tape?
94 String
95 Midi_track::name_str()
96 {
97         return name_str_;
98 }
99
100 Moment
101 Midi_track::next_begin_mom( Moment now_mom )
102 {
103 //      Moment begin_mom = Midi_track::end_mom() + 1;
104         Moment begin_mom = Midi_track::end_mom();
105         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
106 //              if ( i->begin_mom() >= now_mom )
107                 if ( i->begin_mom() > now_mom )
108                         begin_mom = begin_mom <? i->begin_mom();
109         return begin_mom;
110 }
111
112 Moment
113 Midi_track::next_end_mom( Moment now_mom )
114 {
115         Moment end_mom = Midi_track::end_mom();
116         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ ) 
117                 if ( i->end_mom() > now_mom )
118                         end_mom = end_mom <? i->end_mom();
119         return end_mom;
120 }
121
122 void
123 Midi_track::process()
124 {
125         int bar_i = 1;
126         for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
127                 int begin_bar_i = check_begin_bar_i( i->mom(), bar_i );
128                 if ( begin_bar_i )
129                         tor( NORMAL_ver ) << begin_bar_i << flush; 
130                 while ( i->midi_event_p_list_.size() ) 
131                         get_free_midi_voice_l( i->mom() )->add_event( i->midi_event_p_list_.top().remove_p() );
132                 bar_i = check_end_bar_i( i->mom(), bar_i );
133         }
134
135         tor( DEBUG_ver ) << "ends: " << endl;
136         int n = 0;
137         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ ) 
138                 tor( VERBOSE_ver ) << "voice " << n++ << ": " << i->end_mom() << endl;
139         tor( DEBUG_ver ) << ":sdne" << endl;
140 }
141
142
143 void
144 Midi_track::output_mudela( Lily_stream& lily_stream_r )
145 {
146         lily_stream_r << name_str_ << " = \\melodic{";
147         lily_stream_r.indent();
148         lily_stream_r << "% midi copyright:" << copyright_str_;
149         lily_stream_r.newline();
150         lily_stream_r << "% instrument:" << instrument_str_;
151         lily_stream_r.newline();
152
153         int bar_i = 0;
154
155         PointerList<Midi_voice*> open_voices;
156         Moment now_mom = 0.0;
157         /// ugh, avoid status track 0...
158         while ( number_i_ && ( now_mom < end_mom() ) ) {
159                 int begin_bar_i = check_begin_bar_i( now_mom, bar_i );
160                 if ( begin_bar_i )
161                         output_mudela_begin_bar( lily_stream_r, now_mom, begin_bar_i );
162                 add_begin_at( open_voices, now_mom );
163
164                 Moment begin_mom = next_begin_mom( now_mom ); 
165
166                 if ( begin_bar_i )
167                         tor( NORMAL_ver ) << begin_bar_i << flush; 
168
169                 Moment end_mom = next_end_mom( now_mom ); 
170                 Moment then_mom = 0.0;
171                 if ( ( begin_mom > now_mom ) && ( begin_mom < end_mom ) )
172                         then_mom = begin_mom;
173                 else 
174                         then_mom = end_mom;
175
176                 tor( DEBUG_ver ) << "begin: " << begin_mom << " end: " << end_mom << endl;
177                 tor( DEBUG_ver ) << "slice: " << now_mom << ", " << then_mom << endl;
178
179 // rests, ugh
180                 String str;
181 //              if ( !open_voices.size() )
182 //                      output_mudela_rest( lily_stream_r, now_mom, then_mom );
183                 if ( open_voices.size() > 1 )
184                         lily_stream_r << "< ";
185                 for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
186 //                      lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
187                         str += i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
188                 if ( str.length_i() )
189                         lily_stream_r << str;
190                 else
191                         output_mudela_rest( lily_stream_r, now_mom, then_mom );
192                         
193                 if ( open_voices.size() > 1 )
194                         lily_stream_r << "> ";
195                 remove_end_at( open_voices, then_mom );
196
197                 bar_i = check_end_bar_i( now_mom, bar_i );
198
199                 now_mom = then_mom;
200         }
201         bar_i++;
202         tor( NORMAL_ver ) << '[' << bar_i << ']' << flush; 
203
204         lily_stream_r.tnedni();
205         lily_stream_r << "} % " << name_str_;
206         lily_stream_r.newline();
207 }
208
209
210 void
211 Midi_track::output_mudela_begin_bar( Lily_stream& lily_stream_r, Moment now_mom, int bar_i )
212 {
213         Moment bar_mom = midi_time_p_->bar_mom();
214         Moment into_bar_mom = now_mom - Moment( bar_i - 1 ) * bar_mom;
215         if ( bar_i > 1 ) {
216                 if ( !into_bar_mom )
217                         lily_stream_r << "|";
218                 lily_stream_r.newline();
219         }
220         lily_stream_r << "% " << String_convert::i2dec_str( bar_i, 0, ' ' );
221         if ( into_bar_mom )
222                 lily_stream_r << ":" << Duration_convert::dur2_str( Duration_convert::mom2_dur( into_bar_mom ) );
223         lily_stream_r.newline();
224 }
225
226
227 void 
228 Midi_track::output_mudela_rest( Lily_stream& lily_stream_r, Moment begin_mom, Moment end_mom )
229 {
230         Moment bar_mom = midi_time_p_->bar_mom();
231         Moment now_mom = begin_mom;
232         int begin_bar_i =(int)( now_mom / bar_mom ) + 1; 
233         Moment remain_mom = now_mom - Moment( begin_bar_i - 1 ) * bar_mom;
234         if ( remain_mom > Moment( 0 ) )
235                 output_mudela_rest_remain( lily_stream_r, remain_mom );
236
237         int end_bar_i = (int)( end_mom / bar_mom ) + 1;
238         now_mom += remain_mom;
239
240         int bar_i = (int)( now_mom / bar_mom ) + 1;
241         bar_i = check_end_bar_i( now_mom, bar_i );
242         for ( int i = 0; i < end_bar_i - begin_bar_i; i++ ) {
243                 int begin_bar_i = check_begin_bar_i( now_mom, bar_i );
244                 if ( begin_bar_i )
245                         output_mudela_begin_bar( lily_stream_r, now_mom, begin_bar_i );
246                 lily_stream_r << "r1 ";
247                 tor( NORMAL_ver ) << begin_bar_i << flush; 
248                 bar_i = check_end_bar_i( now_mom, bar_i );
249                 now_mom += bar_mom;
250         }
251         // use "int i" here, and gcc 2.7.2 hits internal compiler error
252         int ii = check_begin_bar_i( now_mom, bar_i );
253         if ( ii )
254                 output_mudela_begin_bar( lily_stream_r, now_mom, ii );
255         bar_i = check_end_bar_i( now_mom, bar_i );
256
257         remain_mom = end_mom - Moment( end_bar_i - 1 ) * bar_mom;
258         if ( remain_mom > Moment( 0 ) )
259                 output_mudela_rest_remain( lily_stream_r, remain_mom );
260 }
261
262
263 void
264 Midi_track::output_mudela_rest_remain( Lily_stream& lily_stream_r, Moment mom )
265 {
266         int type_i = 2;
267         while ( mom > Moment( 0 ) ) {
268                 Duration dur( type_i );
269                 Moment type_mom = Duration_convert::dur2_mom( dur );
270                 int count_i = (int)( mom / type_mom ); 
271                 for( int i = 0; i < count_i; i++ )
272                         lily_stream_r << "r" << dur.str() << " ";
273                 type_i *= 2;
274                 mom -= Moment( count_i ) * type_mom;
275                 if ( Duration_convert::no_smaller_than_i_s
276                         && ( type_i > Duration_convert::no_smaller_than_i_s ) ) 
277                         break;  
278         }
279
280 }
281
282 void
283 Midi_track::remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
284 {
285         for ( PCursor<Midi_voice*> i( open_voices_r.top() ); i.ok(); i++ )
286 //              if ( i->end_mom() == mom ) { }
287                 if ( i->end_mom() <= mom ) {
288                         tor( DEBUG_ver ) << "open_voices (" << open_voices_r.size() << "): -1\n";
289                         i.remove_p();
290                         if ( !i.ok() )
291                                 break;
292                 }
293 }
294
295 void
296 Midi_track::set_tempo( int useconds_per_4_i )
297 {
298         delete midi_tempo_p_;
299         midi_tempo_p_ = new Midi_tempo( useconds_per_4_i );
300 }
301
302 void
303 Midi_track::set_time( int num_i, int den_i, int clocks_i, int count_32_i )
304 {
305         delete midi_time_p_;
306         midi_time_p_ = new Midi_time( num_i, den_i, clocks_i, count_32_i );
307 }
308
309 Track_column*
310 Midi_track::tcol_l( Moment mom )
311 {
312         for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
313                 if ( i->mom() == mom )
314                         return *i;
315                 if ( i->mom() > mom ) {
316                         Track_column* tcol_p = new Track_column( mom );
317                         i.insert( tcol_p );
318                         return tcol_p;
319                 }
320         }
321
322         Track_column* tcol_p = new Track_column( mom );
323         tcol_p_list_.bottom().add( tcol_p );
324         return tcol_p;
325 }
326