4 // source file of the LilyPond music typesetter
6 // (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
15 #include "string-convert.hh"
17 #include "musical-request.hh"
19 #include "midi-item.hh"
20 #include "midi-stream.hh"
22 Midi_chunk::Midi_chunk()
27 Midi_chunk::add( String str
)
33 Midi_chunk::set( String header_str
, String data_str
, String footer_str
)
36 footer_str_
= footer_str
;
37 header_str_
= header_str
;
41 Midi_chunk::str() const
43 String str
= header_str_
;
44 String length_str
= String_convert::i2hex_str( data_str_
.length_i() + footer_str_
.length_i(), 8, '0' );
45 length_str
= String_convert::hex2bin_str( length_str
);
52 Midi_duration::Midi_duration( Real seconds_f
)
54 seconds_f_
= seconds_f
;
58 Midi_duration::str() const
60 return String( "<duration: " ) + String( seconds_f_
) + ">";
63 Midi_header::Midi_header( int format_i
, int tracks_i
, int clocks_per_4_i
)
67 String format_str
= String_convert::i2hex_str( format_i
, 4, '0' );
68 str
+= String_convert::hex2bin_str( format_str
);
70 String tracks_str
= String_convert::i2hex_str( tracks_i
, 4, '0' );
71 str
+= String_convert::hex2bin_str( tracks_str
);
73 String tempo_str
= String_convert::i2hex_str( clocks_per_4_i
, 4, '0' );
74 str
+= String_convert::hex2bin_str( tempo_str
);
76 set( "MThd", str
, "" );
80 Midi_item::i2varint_str( int i
)
82 int buffer_i
= i
& 0x7f;
83 while ( (i
>>= 7) > 0 ) {
86 buffer_i
+= (i
& 0x7f);
91 str
+= (char)buffer_i
;
92 if ( buffer_i
& 0x80 )
101 Midi_item::output_midi( Midi_stream
& midi_stream_r
) const
103 midi_stream_r
<< str();
106 Midi_key::Midi_key( int accidentals_i
, int minor_i
)
108 accidentals_i_
= accidentals_i
;
113 Midi_key::str() const
115 String str
= "ff5902";
116 str
+= String_convert::i2hex_str( accidentals_i_
, 2, '0' );
117 str
+= String_convert::i2hex_str( minor_i_
, 2, '0' );
118 return String_convert::hex2bin_str( str
);
121 Midi_note::Midi_note( Melodic_req
* melreq_l
, int channel_i
, bool on_bo
)
124 pitch_i_
= melreq_l
->pitch() + c0_pitch_i_c_
;
125 channel_i_
= channel_i
;
129 dynamic_byte_
= 0x64;
130 if ( on_b_
) // poor man-s staff dynamics:
131 dynamic_byte_
-= 0x10 * channel_i_
;
133 dynamic_byte_
+= 0x32; // 0x64 is supposed to be neutral, but let-s try
137 Midi_note::str() const
139 if ( pitch_i_
!= INT_MAX
) {
140 Byte status_byte
= ( on_b_
? 0x90 : 0x80 ) + channel_i_
;
141 String str
= String( (char)status_byte
);
142 str
+= (char)pitch_i_
;
143 // poor man-s staff dynamics:
144 str
+= (char)dynamic_byte_
;
150 Midi_tempo::Midi_tempo( int per_minute_4_i
)
152 per_minute_4_i_
= per_minute_4_i
;
156 Midi_tempo::str() const
158 int useconds_per_4_i
= 60 * (int)1e6
/ per_minute_4_i_
;
159 String str
= "ff5103";
160 str
+= String_convert::i2hex_str( useconds_per_4_i
, 6, '0' );
161 return String_convert::hex2bin_str( str
);
164 Midi_time::Midi_time( int num_i
, int den_i
, int clocks_per_1_i
)
168 clocks_per_1_i_
= clocks_per_1_i
;
172 Midi_time::str() const
174 String str
= "ff5804";
175 str
+= String_convert::i2hex_str( num_i_
, 2, '0' );
176 str
+= String_convert::i2hex_str( intlog2( den_i_
) , 2, '0' );
177 str
+= String_convert::i2hex_str( clocks_per_1_i_
, 2, '0' );
178 str
+= String_convert::i2hex_str( 8, 2, '0' );
179 return String_convert::hex2bin_str( str
);
182 Midi_text::Midi_text( Midi_text::Type type
, String text_str
)
185 text_str_
= text_str
;
189 Midi_text::str() const
191 String str
= "ff" + String_convert::i2hex_str( type_
, 2, '0' );
192 str
= String_convert::hex2bin_str( str
);
193 str
+= i2varint_str( text_str_
.length_i() );
198 Midi_track::Midi_track( int number_i
)
201 // 00 00 00 3B chunk length (59)
202 // 00 FF 58 04 04 02 18 08 time signature
203 // 00 FF 51 03 07 A1 20 tempo
205 // FF 59 02 sf mi Key Signature
214 number_i_
= number_i
;
216 char const* data_ch_C
= ""
217 // "00" "ff58" "0404" "0218" "08"
218 // "00" "ff51" "0307" "a120"
219 // why a key at all, in midi?
221 // "00" "ff59" "02" "00" "00"
222 // key: F (scsii-menuetto)
223 // "00" "ff59" "02" "ff" "00"
227 // only for format 0 (currently using format 1)?
228 data_str
+= String_convert::hex2bin_str( data_ch_C
);
230 char const* footer_ch_C
= "00" "ff2f" "00";
231 String footer_str
= String_convert::hex2bin_str( footer_ch_C
);
233 set( "MTrk", data_str
, footer_str
);
237 Midi_track::add( int delta_time_i
, String event_str
)
239 assert(delta_time_i
>= 0);
240 Midi_chunk::add( i2varint_str( delta_time_i
) + event_str
);
244 Midi_track::add( Moment delta_time_moment
, Midi_item
* mitem_l
)
246 // use convention of 384 clocks per 4
247 // use Duration_convert
248 int delta_time_i
= delta_time_moment
* Moment( 384 ) / Moment( 1, 4 );
249 add( delta_time_i
, mitem_l
->str() );