]> git.donarmstrong.com Git - lilypond.git/blob - lily/midi-walker.cc
release: 0.0.68pre
[lilypond.git] / lily / midi-walker.cc
1 /*
2   midi-walker.cc -- implement Midi_walker
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>, Jan Nieuwenhuizen <jan@digicash.com>
7   
8   TODO
9
10   Ideally this should also use a register system, to process slurs,
11   dynamics, etc.
12   
13 */
14
15 #include "command-request.hh"
16 #include "musical-request.hh"
17 #include "p-score.hh"
18 #include "midi-walker.hh"
19 #include "midi-item.hh"
20 #include "midi-stream.hh"
21 #include "debug.hh"
22 #if 0
23 Midi_walker::Midi_walker(Staff *st_l, Midi_track* track_l)
24     : PCursor<Staff_column*>(st_l->cols_)
25 {
26     track_l_ = track_l;
27     last_moment_= 0;
28 }
29
30 /**
31   output notestop events for all notes which end before #max_moment#
32  */
33 void
34 Midi_walker::do_stop_notes(Moment max_moment)
35 {
36     while (stop_notes.size() && stop_notes.front().key <= max_moment) {
37         Note_event  ent=stop_notes.get();
38         if (ent.ignore_b_) 
39             continue;
40         
41         Moment stop_moment = ent.key;
42         Melodic_req * req_l = ent.val;
43         
44         Midi_note note(req_l, track_l_->number_i_, false);
45         output_event(note, stop_moment);
46     }
47 }
48 /**
49   Find out if start_note event is needed,  and do it if needed.
50  */
51 void 
52 Midi_walker::do_start_note(Note_req*note_l)
53 {
54     Moment stop = note_l->duration() + ptr()->when();
55     for(int i=0; i < stop_notes.size(); i++) {
56         if (stop_notes[i].val->melodic()->pitch() ==
57             note_l->pitch()) {
58             if ( stop_notes[i].key < stop){
59                 stop_notes[i].ignore_b_=true;
60             }
61             else
62                 return; // skip the stop note 
63         }
64     }
65     Note_event e;
66     e.val = note_l;
67     e.key = stop;
68     
69     stop_notes.insert(e);
70     
71     Midi_note note(note_l, track_l_->number_i_, true);
72     output_event(note, ptr()->when());
73 }
74
75
76 /** advance the track to #now#, output the item, and adjust current
77   "moment".  */
78 void
79 Midi_walker::output_event(Midi_item &i, Moment now)
80 {
81     Moment delta_t = now - last_moment_ ;
82     last_moment_ += delta_t;
83     track_l_->add(delta_t, &i );    
84 }
85
86 void
87 Midi_walker::do_process_requests()
88 {
89     do_stop_notes(ptr()->when());
90
91     for ( int i = 0; i < ptr()->commandreq_l_arr_.size(); i++ )  {
92         Command_req *c_l = ptr()->commandreq_l_arr_[i]->command();
93         Meter_change_req* meter_l = c_l->meterchange();
94         if ( meter_l )
95             output_event( Midi_time( meter_l->beats_i_, meter_l->one_beat_i_, 18 ),  ptr()->when() );
96         Key_change_req* key_l = c_l->keychange();
97         if ( key_l ) {
98             int sharps_i = key_l->sharps_i();
99             int flats_i = key_l->flats_i();
100             // midi cannot handle non-conventional keys
101             if ( !( flats_i && sharps_i ) )
102                 output_event( Midi_key( sharps_i - flats_i, key_l->minor_b() ), ptr()->when() );
103         }
104     }
105
106     for ( int i = 0; i < ptr()->musicalreq_l_arr_.size(); i++ )  {
107         Musical_req *m = ptr()->musicalreq_l_arr_[i]->musical();
108         if (!m)
109             return;
110         Rhythmic_req *n = m->rhythmic();
111         if ( !n)
112             continue;
113         Note_req * note_l = n->note();
114         if (!note_l)
115             continue;
116         do_start_note(note_l);
117     }
118 }
119
120 Midi_walker::~Midi_walker()
121 {
122     do_stop_notes( last_moment_ + Moment(10,1)); // ugh
123 }
124
125
126 int
127 compare(Note_event const&e1, Note_event const&e2)
128 {
129     return sign(e1.key - e2.key);
130 }
131 #endif