]> git.donarmstrong.com Git - lilypond.git/blob - midi2ly/midi-score-parser.cc
a09f28fce491afe2c8f579d7ae074a4b64df17b2
[lilypond.git] / midi2ly / midi-score-parser.cc
1 /*
2   midi-score-parser.cc -- implement
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1998 Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "rational.hh"
10 #include "source-file.hh"
11 #include "source.hh"
12 #include "midi2ly-global.hh"
13 #include "midi-score-parser.hh"
14 #include "midi-track-parser.hh"
15 #include "lilypond-item.hh"
16 #include "lilypond-score.hh"
17
18
19 void
20 Midi_score_parser::open (String filename_str, Sources* sources_l)
21 {
22   info_l_->source_l_ = sources_l->get_file_l (filename_str);
23   if (!info_l_->source_l_)
24     ::error (_f ("can't find file: `%s'", filename_str));
25   info_l_->byte_L_ = (Byte const*)info_l_->source_l_->ch_C ();
26   info_l_->end_byte_L_ = info_l_->byte_L_ + info_l_->source_l_->length_i () + 1;
27 }
28
29 Lilypond_score*
30 Midi_score_parser::parse (String filename_str, Sources* sources_l)
31 {
32   Midi_parser_info info;
33   info_l_ = &info;
34   open (filename_str, sources_l);
35   parse_header ();
36   return parse_score ();
37 }
38
39 void
40 Midi_score_parser::parse_header ()
41 {
42   String str = get_str (4);
43   if ( str != "MThd" )
44     exit (_ ("MIDI header expected"));
45
46   int length_i = get_i (4);
47   // is this signed?
48   if (length_i < 6)
49     exit (_ ("invalid header length"));
50   info_l_->format_i_ = get_i (2);
51   if (info_l_->format_i_ != 0 && info_l_->format_i_ != 1)
52     exit (_("invalid MIDI format"));
53   info_l_->tracks_i_ = get_i (2);
54   if (info_l_->tracks_i_ < 0 || info_l_->tracks_i_ > 32 )
55     exit (_("invalid number of tracks"));
56   info_l_->division_1_i_ = get_i (2) * 4;
57   if (info_l_->division_1_i_ < 0)
58     exit (_ ("can't handle non-metrical time"));
59   // ugh
60   Duration::division_1_i_s = info_l_->division_1_i_;
61   forward_byte_L (length_i - 6);
62 }
63
64 int
65 Midi_score_parser::find_earliest_i (Link_array<Midi_track_parser>& tracks)
66 {
67   int earliest_i = 0;
68   Rational earliest_mom = infinity_rat;
69   for (int i = 0; i < tracks.size(); i++)
70     {
71       if ( tracks [i]->at_mom () < earliest_mom )
72         {
73           earliest_mom = tracks [i]->at_mom ();
74           earliest_i = i;
75         }
76     }
77   return earliest_i;
78 }
79
80 Lilypond_score*
81 Midi_score_parser::parse_score ()
82 {
83   int current_bar_i = 0;
84   Lilypond_time_signature m4 (4, 2, 24, 8);
85   Rational bar4_mom = m4.bar_mom ();
86
87   Lilypond_score* score_p = new Lilypond_score( 1, 1, 1 );
88   info_l_->score_l_ = score_p;
89
90   Link_array<Midi_track_parser> tracks;
91   for (int i = 0; i < info_l_->tracks_i_; i++)
92     tracks.push (new Midi_track_parser (info_l_, i));
93
94   LOGOUT (NORMAL_ver) << _ ("Parsing...");
95   LOGOUT (NORMAL_ver) << "\n";
96   while (tracks.size ())
97     {
98       int i = find_earliest_i (tracks);
99       Rational at_mom = tracks [i]->at_mom ();
100       Lilypond_column* column_l = score_p->get_column_l (at_mom);
101       Lilypond_staff* staff_p = tracks [i]->parse (column_l);
102       if ( staff_p )
103         {
104           score_p->add_staff (staff_p);
105           delete tracks [i];
106           tracks.del (i);
107         }
108
109       //  brr, musta have some progress
110       for (int ii = 0; !info_l_->bar_mom_ && ii < tracks.size (); ii++)
111         info_l_->bar_mom_ = tracks [ii]->info_l_->bar_mom_;
112
113       int bar_i = (int) (at_mom
114             / (info_l_->bar_mom_ ? info_l_->bar_mom_ : bar4_mom)) + 1;
115       if (bar_i > current_bar_i)
116         {
117           LOGOUT (NORMAL_ver) << '[' << bar_i << ']' << flush;
118           current_bar_i = bar_i;
119         }
120     }
121   return score_p;
122 }