]> git.donarmstrong.com Git - lilypond.git/blob - mi2mu/midi-track.cc
release: 0.0.46.jcn1
[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 // too much red tape?
47 String
48 Midi_track::name_str()
49 {
50         return name_str_;
51 }
52
53 Moment
54 Midi_track::end_mom()
55 {
56         // heu..
57         Moment mom = 0.0;
58         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ ) 
59                 mom = i->end_mom() >? mom;
60         return mom;
61 }
62
63 Midi_voice*
64 Midi_track::get_free_midi_voice_l( Moment mom )
65 {
66         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
67                 if ( i->end_mom() == mom )
68                         return *i;
69
70         Midi_voice* midi_voice_p = new Midi_voice( mom );
71         Midi_voice* midi_voice_l = midi_voice_p;
72         midi_voice_p_list_.bottom().add( midi_voice_p );
73         return midi_voice_l; 
74 }
75
76 Moment
77 Midi_track::next_begin_mom( Moment now_mom )
78 {
79 //      Moment begin_mom = Midi_track::end_mom() + 1;
80         Moment begin_mom = Midi_track::end_mom();
81         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
82 //              if ( i->begin_mom() >= now_mom )
83                 if ( i->begin_mom() > now_mom )
84                         begin_mom = begin_mom <? i->begin_mom();
85         return begin_mom;
86 }
87
88 Moment
89 Midi_track::next_end_mom( Moment now_mom )
90 {
91         Moment end_mom = Midi_track::end_mom();
92         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ ) 
93                 if ( i->end_mom() > now_mom )
94                         end_mom = end_mom <? i->end_mom();
95         return end_mom;
96 }
97
98 void
99 Midi_track::process()
100 {
101         int bar_i = 1;
102         Moment bar_mom = midi_time_p_->bar_mom();
103
104         for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
105                 int bars_i = (int)( i->mom() / bar_mom );
106                 if ( bars_i > bar_i )
107                         tor( NORMAL_ver ) << '[' << bar_i << flush; 
108                 while ( i->midi_event_p_list_.size() ) 
109                         get_free_midi_voice_l( i->mom() )->add_event( i->midi_event_p_list_.top().remove_p() );
110                 if ( bars_i > bar_i ) {
111                         bar_i = bars_i;
112                         tor( NORMAL_ver ) << ']' << flush; 
113                 }
114         }
115
116         tor( DEBUG_ver ) << "ends: " << endl;
117         int n = 0;
118         for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ ) 
119                 tor( VERBOSE_ver ) << "voice " << n++ << ": " << i->end_mom() << endl;
120         tor( DEBUG_ver ) << ":sdne" << endl;
121 }
122
123
124 void
125 Midi_track::output_mudela( Lily_stream& lily_stream_r )
126 {
127         lily_stream_r << name_str_ << " = \\melodic{";
128         lily_stream_r.indent();
129         lily_stream_r << "% midi copyright:" << copyright_str_;
130         lily_stream_r.newline();
131         lily_stream_r << "% instrument:" << instrument_str_;
132         lily_stream_r.newline();
133
134         int bar_i = 0;
135         Moment bar_mom = midi_time_p_->bar_mom();
136
137         PointerList<Midi_voice*> open_voices;
138         Moment now_mom = 0.0;
139         Moment then_mom = 0.0;
140         while ( now_mom < end_mom() ) {
141                 int bars_i = (int)( now_mom / bar_mom ) + 1;
142                 if ( bars_i > bar_i )
143                         tor( NORMAL_ver ) << '[' << flush; 
144
145                 if ( bars_i > bar_i ) { 
146                         Moment into_bar_mom = now_mom - Moment( bars_i - 1 ) * bar_mom;
147                         if ( bars_i > 1 ) {
148                                 if ( !into_bar_mom )
149                                         lily_stream_r << "|";
150                                 lily_stream_r.newline();
151                         }
152                         lily_stream_r << "% " << String_convert::i2dec_str( bars_i, 0, ' ' );
153                         if ( into_bar_mom )
154                                 lily_stream_r << ":" << Duration_convert::dur2_str( Duration_convert::mom2_dur( into_bar_mom ) );
155                         lily_stream_r.newline();
156                 }
157
158                 add_begin_at( open_voices, now_mom );
159
160                 Moment begin_mom = next_begin_mom( now_mom ); 
161
162                 if ( bars_i > bar_i )
163                         tor( NORMAL_ver ) << bars_i << flush; 
164
165                 Moment end_mom = next_end_mom( now_mom ); 
166                 if ( ( begin_mom > now_mom ) && ( begin_mom < end_mom ) )
167                         then_mom = begin_mom;
168                 else 
169                         then_mom = end_mom;
170
171                 tor( DEBUG_ver ) << "begin: " << begin_mom << " end: " << end_mom << endl;
172                 tor( DEBUG_ver ) << "slice: " << now_mom << ", " << then_mom << endl;
173
174                 if ( open_voices.size() > 1 )
175                         lily_stream_r << "< ";
176                 for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
177                         lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
178                 if ( open_voices.size() > 1 )
179                         lily_stream_r << "> ";
180                 now_mom = then_mom;
181
182                 remove_end_at( open_voices, now_mom );
183                 if ( bars_i > bar_i ) {
184                         bar_i = bars_i;
185                         tor( NORMAL_ver ) << ']' << flush; 
186                 }
187         }
188         bar_i++;
189         tor( NORMAL_ver ) << '[' << bar_i << ']' << flush; 
190
191         lily_stream_r.tnedni();
192         lily_stream_r << "} % " << name_str_;
193         lily_stream_r.newline();
194 }
195
196 void
197 Midi_track::remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
198 {
199         for ( PCursor<Midi_voice*> i( open_voices_r.top() ); i.ok(); i++ )
200 //              if ( i->end_mom() == mom ) {
201                 if ( i->end_mom() <= mom ) {
202                         tor( DEBUG_ver ) << "open_voices (" << open_voices_r.size() << "): -1\n";
203                         i.remove_p();
204                         if ( !i.ok() )
205                                 break;
206                 }
207 }
208
209 void
210 Midi_track::set_tempo( int useconds_per_4_i )
211 {
212         delete midi_tempo_p_;
213         midi_tempo_p_ = new Midi_tempo( useconds_per_4_i );
214 }
215
216 void
217 Midi_track::set_time( int num_i, int den_i, int clocks_i, int count_32_i )
218 {
219         delete midi_time_p_;
220         midi_time_p_ = new Midi_time( num_i, den_i, clocks_i, count_32_i );
221 }
222
223 Track_column*
224 Midi_track::tcol_l( Moment mom )
225 {
226         for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
227                 if ( i->mom() == mom )
228                         return *i;
229                 if ( i->mom() > mom ) {
230                         Track_column* tcol_p = new Track_column( mom );
231                         i.insert( tcol_p );
232                         return tcol_p;
233                 }
234         }
235
236         Track_column* tcol_p = new Track_column( mom );
237         tcol_p_list_.bottom().add( tcol_p );
238         return tcol_p;
239 }
240