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 if ( track_name_str.length_i() )
14 name_str_ = track_name_str;
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 ) ) );
22 Midi_track::~Midi_track()
29 Midi_track::add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
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 );
39 Midi_track::add_event( Moment mom, Midi_event* midi_event_p )
43 tcol_l( mom - midi_event_p->mom() )->add_event( midi_event_p );
47 Midi_track::check_begin_bar_i( Moment now_mom, int open_bar_i )
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;
59 Midi_track::check_end_bar_i( Moment now_mom, int open_bar_i )
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;
75 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
76 mom = i->end_mom() >? mom;
81 Midi_track::get_free_midi_voice_l( Moment mom )
83 for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
84 if ( i->end_mom() == mom )
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 );
95 Midi_track::name_str()
101 Midi_track::next_begin_mom( Moment now_mom )
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();
113 Midi_track::next_end_mom( Moment now_mom )
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();
123 Midi_track::process()
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 );
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 );
135 tor( DEBUG_ver ) << "ends: " << endl;
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;
144 Midi_track::output_mudela( Lily_stream& lily_stream_r )
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();
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 );
161 output_mudela_begin_bar( lily_stream_r, now_mom, begin_bar_i );
162 add_begin_at( open_voices, now_mom );
164 Moment begin_mom = next_begin_mom( now_mom );
167 tor( NORMAL_ver ) << begin_bar_i << flush;
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;
176 tor( DEBUG_ver ) << "begin: " << begin_mom << " end: " << end_mom << endl;
177 tor( DEBUG_ver ) << "slice: " << now_mom << ", " << then_mom << endl;
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;
191 output_mudela_rest( lily_stream_r, now_mom, then_mom );
193 if ( open_voices.size() > 1 )
194 lily_stream_r << "> ";
195 remove_end_at( open_voices, then_mom );
197 bar_i = check_end_bar_i( now_mom, bar_i );
202 tor( NORMAL_ver ) << '[' << bar_i << ']' << flush;
204 lily_stream_r.tnedni();
205 lily_stream_r << "} % " << name_str_;
206 lily_stream_r.newline();
211 Midi_track::output_mudela_begin_bar( Lily_stream& lily_stream_r, Moment now_mom, int bar_i )
213 Moment bar_mom = midi_time_p_->bar_mom();
214 Moment into_bar_mom = now_mom - Moment( bar_i - 1 ) * bar_mom;
217 lily_stream_r << "|";
218 lily_stream_r.newline();
220 lily_stream_r << "% " << String_convert::i2dec_str( bar_i, 0, ' ' );
222 lily_stream_r << ":" << Duration_convert::dur2_str( Duration_convert::mom2_dur( into_bar_mom ) );
223 lily_stream_r.newline();
228 Midi_track::output_mudela_rest( Lily_stream& lily_stream_r, Moment begin_mom, Moment end_mom )
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 );
237 int end_bar_i = (int)( end_mom / bar_mom ) + 1;
238 now_mom += remain_mom;
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 );
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 );
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 );
254 output_mudela_begin_bar( lily_stream_r, now_mom, ii );
255 bar_i = check_end_bar_i( now_mom, bar_i );
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 );
264 Midi_track::output_mudela_rest_remain( Lily_stream& lily_stream_r, Moment mom )
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() << " ";
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 ) )
283 Midi_track::remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
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";
296 Midi_track::set_tempo( int useconds_per_4_i )
298 delete midi_tempo_p_;
299 midi_tempo_p_ = new Midi_tempo( useconds_per_4_i );
303 Midi_track::set_time( int num_i, int den_i, int clocks_i, int count_32_i )
306 midi_time_p_ = new Midi_time( num_i, den_i, clocks_i, count_32_i );
310 Midi_track::tcol_l( Moment mom )
312 for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
313 if ( i->mom() == mom )
315 if ( i->mom() > mom ) {
316 Track_column* tcol_p = new Track_column( mom );
322 Track_column* tcol_p = new Track_column( mom );
323 tcol_p_list_.bottom().add( tcol_p );