]> git.donarmstrong.com Git - lilypond.git/blob - src/midiitem.cc
e7d5ccc92f48556ba0a063af5799f1c4986b0717
[lilypond.git] / src / midiitem.cc
1 //
2 // midiitem.cc
3 //
4 // source file of the LilyPond music typesetter
5 //
6 // (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
7
8 #include <limits.h>
9 #include "plist.hh"
10 #include "pcol.hh"
11 #include "debug.hh"
12 #include "misc.hh"
13 #include "request.hh"
14 #include "musicalrequest.hh"
15 #include "voice.hh"
16 #include "midiitem.hh"
17 #include "midistream.hh"
18
19 Midi_chunk::Midi_chunk()
20 {
21 }
22
23 void
24 Midi_chunk::add( String str )
25 {
26         data_str_ += str;
27 }
28
29 void
30 Midi_chunk::set( String header_str, String data_str, String footer_str )
31 {
32         data_str_ = data_str;
33         footer_str_ = footer_str;
34         header_str_ = header_str;
35 }
36   
37 String
38 Midi_chunk::str()
39 {
40         String str = header_str_;
41         String length_str = StringConversion::int2hex_str( data_str_.length_i() + footer_str_.length_i(), 8, '0' );
42         length_str = StringConversion::hex2bin_str( length_str );
43         str += length_str;
44         str += data_str_;
45         str += footer_str_;
46         return str;
47 }
48
49 Midi_duration::Midi_duration( Real seconds_f )
50 {
51         seconds_f_ = seconds_f;
52 }
53
54 String
55 Midi_duration::str()
56 {
57         return String( "<duration: " ) + String( seconds_f_ ) + ">";
58 }
59
60 Midi_header::Midi_header( int format_i, int tracks_i, int tempo_i )
61 {
62         String str;
63         
64         String format_str = StringConversion::int2hex_str( format_i, 4, '0' );
65         str += StringConversion::hex2bin_str( format_str );
66         
67         String tracks_str = StringConversion::int2hex_str( tracks_i, 4, '0' );
68         str += StringConversion::hex2bin_str( tracks_str );
69
70         String tempo_str = StringConversion::int2hex_str( tempo_i, 4, '0' );
71         str += StringConversion::hex2bin_str( tempo_str );
72
73         set( "MThd", str, "" );
74 }
75
76 String
77 Midi_item::int2varlength_str( int i )
78 {
79         int buffer_i = i & 0x7f;
80         while ( (i >>= 7) > 0 ) {
81                 buffer_i <<= 8;
82                 buffer_i |= 0x80;
83                 buffer_i += (i & 0x7f);
84         }
85
86         String str;
87         while ( 1 ) {
88                 str += (char)buffer_i;
89                 if ( buffer_i & 0x80 )
90                         buffer_i >>= 8;
91                 else
92                         break;
93         }
94         return str;
95 }
96
97 void 
98 Midi_item::output_midi( Midi_stream& midi_stream_r )
99 {
100         midi_stream_r << str();
101 }
102
103
104 Midi_note::Midi_note( Melodic_req* melreq_l, int channel_i, bool on_bo  )
105 {
106         pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;   
107         channel_i_ = channel_i;
108         on_bo_ = on_bo;
109 }
110
111 String
112 Midi_note::str()
113 {
114         if ( pitch_i_ != INT_MAX ) {
115                 Byte status_by = ( on_bo_ ? 0x90 : 0x80 ) + channel_i_;
116                 String str = String( (char)status_by );
117                 str += (char)pitch_i_;
118                 // poor man-s staff dynamics:
119                 Byte dynamic_by = 0x64 - 0x10 * channel_i_;
120                 str += (char)dynamic_by;
121                 return str;
122         }
123         return String( "" );
124 }
125
126 Midi_track::Midi_track( int number_i )
127 {
128 //                4D 54 72 6B     MTrk
129 //                00 00 00 3B     chunk length (59)
130 //        00      FF 58 04 04 02 18 08    time signature
131 //        00      FF 51 03 07 A1 20       tempo
132  
133 // FF 59 02 sf mi  Key Signature
134 //         sf = -7:  7 flats
135 //         sf = -1:  1 flat
136 //         sf = 0:  key of C
137 //         sf = 1:  1 sharp
138 //         sf = 7: 7 sharps
139 //         mi = 0:  major key
140 //         mi = 1:  minor key
141
142         number_i_ = number_i;
143         
144         char const* data_ch_c_l = "00" "ff58" "0404" "0218" "08"
145                                   "00" "ff51" "0307" "a120"
146 // why a key at all, in midi?
147 // key: C
148                                   "00" "ff59" "02" "00" "00"
149 // key: F (scsii-menuetto)
150 //                                "00" "ff59" "02" "ff" "00"
151                                   ;
152
153         String data_str;
154         // only for format 0 (currently using format 1)?
155         data_str += StringConversion::hex2bin_str( data_ch_c_l );
156
157         char const* footer_ch_c_l = "00" "ff2f" "00";
158         String footer_str = StringConversion::hex2bin_str( footer_ch_c_l );
159
160         set( "MTrk", data_str, footer_str );
161 }
162
163 void 
164 Midi_track::add( int delta_time_i, String event_str )
165 {
166         Midi_chunk::add( int2varlength_str( delta_time_i ) + event_str );
167 }
168
169 void 
170 Midi_track::add( Moment delta_time_moment, Midi_item* mitem_l )
171 {
172         // silly guess: 24 midi clocks per 4 note
173         // huh?
174 //      int delta_time_i = delta_time_moment / Moment( 1, 4 ) * Moment( 24 );
175         int delta_time_i = delta_time_moment / Moment( 1, 4 ) * Moment( 96 );
176         add( delta_time_i, mitem_l->str() );
177 }
178