2 // midi-track.cc -- implement Midi_track
4 // copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
8 Midi_track::Midi_track( int number_i, String copyright_str, String track_name_str, String instrument_str )
11 copyright_str_ = copyright_str;
12 instrument_str_ = instrument_str;
13 name_str_ = track_name_str;
14 midi_time_p_ = new Midi_time( 4, 2, 24, 8 );
15 midi_tempo_p_ = new Midi_tempo( 1000000 );
16 tcol_p_list_.bottom().add( new Track_column( Moment( 0 ) ) );
19 Midi_track::~Midi_track()
26 Midi_track::add_begin_at( Pointer_list<Midi_voice*>& open_voices_r, Moment mom )
28 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
29 if ( i->begin_mom() == mom ) {
30 tor( DEBUG_ver ) << "open_voices (" << open_voices_r.size() << "): +1\n";
31 open_voices_r.bottom().add( *i );
36 Midi_track::add_event( Moment mom, Midi_event* midi_event_p )
40 tcol_l( mom - midi_event_p->mom() )->add_event( midi_event_p );
44 Midi_track::check_begin_bar_i( Moment now_mom, int open_bar_i )
46 Moment bar_mom = midi_time_p_->bar_mom();
47 int bar_i = (int)( now_mom / bar_mom ) + 1;
48 if ( bar_i > open_bar_i ) {
49 tor( NORMAL_ver ) << '[' << flush;
56 Midi_track::check_end_bar_i( Moment now_mom, int open_bar_i )
58 Moment bar_mom = midi_time_p_->bar_mom();
59 int bar_i = (int)( now_mom / bar_mom ) + 1;
60 if ( bar_i > open_bar_i ) {
61 tor( NORMAL_ver ) << ']' << flush;
72 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
73 mom = i->end_mom() >? mom;
78 Midi_track::get_free_midi_voice_l( Moment mom )
80 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
81 if ( i->end_mom() == mom )
84 Midi_voice* midi_voice_p = new Midi_voice( mom );
85 Midi_voice* midi_voice_l = midi_voice_p;
86 midi_voice_p_list_.bottom().add( midi_voice_p );
91 Midi_track::name_str()
93 if ( name_str_.length_i() )
95 return String( "track" ) + String( number_i_ );
99 Midi_track::next_begin_mom( Moment now_mom )
101 // Moment begin_mom = Midi_track::end_mom() + 1;
102 Moment begin_mom = Midi_track::end_mom();
103 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
104 // if ( i->begin_mom() >= now_mom )
105 if ( i->begin_mom() > now_mom )
106 begin_mom = begin_mom <? i->begin_mom();
111 Midi_track::next_end_mom( Moment now_mom )
113 Moment end_mom = Midi_track::end_mom();
114 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
115 if ( i->end_mom() > now_mom )
116 end_mom = end_mom <? i->end_mom();
121 Midi_track::process()
127 for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
128 int begin_bar_i = check_begin_bar_i( i->mom(), bar_i );
130 tor( NORMAL_ver ) << begin_bar_i << flush;
131 while ( i->midi_event_p_list_.size() )
132 get_free_midi_voice_l( i->mom() )->add_event( i->midi_event_p_list_.top().remove_p() );
133 bar_i = check_end_bar_i( i->mom(), bar_i );
136 tor( DEBUG_ver ) << "ends: " << endl;
138 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
139 tor( VERBOSE_ver ) << "voice " << n++ << ": " << i->end_mom() << endl;
140 tor( DEBUG_ver ) << ":sdne" << endl;
145 Midi_track::output_mudela( Lily_stream& lily_stream_r )
147 lily_stream_r << name_str() << " = \\melodic{";
148 lily_stream_r.indent();
149 lily_stream_r << "% midi copyright:" << copyright_str_;
150 lily_stream_r.newline();
151 lily_stream_r << "% instrument:" << instrument_str_;
152 lily_stream_r.newline();
156 Pointer_list<Midi_voice*> open_voices;
157 Moment now_mom = 0.0;
158 Real now_f = now_mom;
160 Real end_f = end_mom();
164 now we step through time while writing all voices
166 we can only output time slices that have a constant
167 number of open voices; each begin or end of a voice
168 starts or ends a chord or multivoice
171 voice defragmentation/concatenation could make this
175 bool start_of_track_bo = true;
177 /// ugh, avoid status track 0 full of rests...
178 while ( number_i_ && ( now_mom < end_mom() ) ) {
179 int begin_bar_i = check_begin_bar_i( now_mom, bar_i );
181 output_mudela_begin_bar( lily_stream_r, now_mom, begin_bar_i );
182 add_begin_at( open_voices, now_mom );
184 Moment begin_mom = next_begin_mom( now_mom );
187 tor( NORMAL_ver ) << begin_bar_i << flush;
189 Moment end_mom = next_end_mom( now_mom );
190 Moment then_mom = 0.0;
191 if ( ( begin_mom > now_mom ) && ( begin_mom < end_mom ) )
192 then_mom = begin_mom;
196 tor( DEBUG_ver ) << "begin: " << begin_mom << " end: " << end_mom << endl;
197 tor( DEBUG_ver ) << "slice: " << now_mom << ", " << then_mom << endl;
205 // checking for no open voice does not work for initial rests.
206 // for some reason the voice is open, but does not procuce notes?
207 if ( open_voices.size() > 1 )
208 lily_stream_r << "< ";
209 if ( start_of_track_bo ) {
210 start_of_track_bo = false;
212 for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
213 lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
214 if ( str.length_i() )
215 lily_stream_r << str;
217 output_mudela_rest( lily_stream_r, now_mom, then_mom );
220 for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
221 lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
222 if ( !open_voices.size() )
223 output_mudela_rest( lily_stream_r, now_mom, then_mom );
225 // *lily_stream_r.os_p_ << flush;
227 if ( open_voices.size() > 1 )
228 lily_stream_r << "> ";
229 remove_end_at( open_voices, then_mom );
231 bar_i = check_end_bar_i( now_mom, bar_i );
236 tor( NORMAL_ver ) << '[' << bar_i << ']' << flush;
238 lily_stream_r.tnedni();
239 lily_stream_r << "} % " << name_str();
240 lily_stream_r.newline();
245 Midi_track::output_mudela_begin_bar( Lily_stream& lily_stream_r, Moment now_mom, int bar_i )
247 Moment bar_mom = midi_time_p_->bar_mom();
248 Moment into_bar_mom = now_mom - Moment( bar_i - 1 ) * bar_mom;
251 lily_stream_r << "|";
252 lily_stream_r.newline();
254 lily_stream_r << "% " << String_convert::i2dec_str( bar_i, 0, ' ' );
256 lily_stream_r << ":" << Duration_convert::dur2_str( Duration_convert::mom2_dur( into_bar_mom ) );
257 lily_stream_r.newline();
262 Midi_track::output_mudela_rest( Lily_stream& lily_stream_r, Moment begin_mom, Moment end_mom )
264 Moment bar_mom = midi_time_p_->bar_mom();
265 Moment now_mom = begin_mom;
267 int begin_bar_i = (int)( now_mom / bar_mom ) + 1;
268 int end_bar_i = (int)( end_mom / bar_mom ) + 1;
270 if ( end_bar_i == begin_bar_i ) {
271 output_mudela_rest_remain( lily_stream_r, end_mom - begin_mom );
275 // multiple bars involved
276 int bar_i = (int)( now_mom / bar_mom ) + 1;
279 Moment begin_bar_mom = Moment( begin_bar_i - 1 ) * bar_mom;
280 if ( now_mom > begin_bar_mom ) {
281 int next_bar_i = (int)( now_mom / bar_mom ) + 2;
282 Moment next_bar_mom = Moment( next_bar_i - 1 ) * bar_mom;
283 assert( next_bar_mom <= end_mom );
285 Moment remain_mom = next_bar_mom - now_mom;
286 if ( remain_mom > Moment( 0 ) ) {
287 output_mudela_rest_remain( lily_stream_r, remain_mom );
288 now_mom += remain_mom;
291 bar_i = check_end_bar_i( now_mom, bar_i );
295 int count_i = end_bar_i - bar_i;
296 for ( int i = 0; i < count_i; i++ ) {
297 int begin_bar_i = check_begin_bar_i( now_mom, bar_i );
299 output_mudela_begin_bar( lily_stream_r, now_mom, begin_bar_i );
300 lily_stream_r << "r1 ";
301 // *lily_stream_r.os_p_ << flush;
302 tor( NORMAL_ver ) << begin_bar_i << flush;
303 bar_i = check_end_bar_i( now_mom, bar_i );
307 // use "int i" here, and gcc 2.7.2 hits internal compiler error
308 int ii = check_begin_bar_i( now_mom, bar_i );
310 output_mudela_begin_bar( lily_stream_r, now_mom, ii );
312 // bar_i = check_end_bar_i( now_mom, bar_i );
314 Moment remain_mom = end_mom - Moment( end_bar_i - 1 ) * bar_mom;
315 if ( remain_mom > Moment( 0 ) ) {
316 output_mudela_rest_remain( lily_stream_r, remain_mom );
317 now_mom += remain_mom;
319 assert( now_mom == end_mom );
323 Midi_track::output_mudela_rest_remain( Lily_stream& lily_stream_r, Moment mom )
325 if ( Duration_convert::no_quantify_b_s ) {
326 Duration dur = Duration_convert::mom2_dur( mom );
327 lily_stream_r << "r" << dur.str() << " ";
328 // assert( mom == dur.mom() );
329 assert( mom == dur.length() );
333 Duration dur = Duration_convert::mom2standardised_dur( mom );
335 lily_stream_r << "r" << dur.str() << " ";
339 Midi_track::remove_end_at( Pointer_list<Midi_voice*>& open_voices_r, Moment mom )
341 for ( PCursor<Midi_voice*> i( open_voices_r.top() ); i.ok(); i++ )
342 // if ( i->end_mom() == mom ) { }
343 if ( i->end_mom() <= mom ) {
344 tor( DEBUG_ver ) << "open_voices (" << open_voices_r.size() << "): -1\n";
352 Midi_track::set_tempo( int useconds_per_4_i )
354 delete midi_tempo_p_;
355 midi_tempo_p_ = new Midi_tempo( useconds_per_4_i );
359 Midi_track::set_time( int num_i, int den_i, int clocks_i, int count_32_i )
362 midi_time_p_ = new Midi_time( num_i, den_i, clocks_i, count_32_i );
366 Midi_track::tcol_l( Moment mom )
368 for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
369 if ( i->mom() == mom )
371 if ( i->mom() > mom ) {
372 Track_column* tcol_p = new Track_column( mom );
378 Track_column* tcol_p = new Track_column( mom );
379 tcol_p_list_.bottom().add( tcol_p );