lilypond-0.0.50
[lilypond.git] / lily / midi-item.cc
blob04e1286197df176309c04ec81b864255bbe20305
1 //
2 // midiitem.cc
3 //
4 // source file of the LilyPond music typesetter
5 //
6 // (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
8 #include <limits.h>
9 #include "proto.hh"
10 #include "plist.hh"
11 #include "p-col.hh"
12 #include "debug.hh"
13 #include "misc.hh"
14 #include "string.hh"
15 #include "string-convert.hh"
16 #include "request.hh"
17 #include "musical-request.hh"
18 #include "voice.hh"
19 #include "midi-item.hh"
20 #include "midi-stream.hh"
22 Midi_chunk::Midi_chunk()
26 void
27 Midi_chunk::add( String str )
29 data_str_ += str;
32 void
33 Midi_chunk::set( String header_str, String data_str, String footer_str )
35 data_str_ = data_str;
36 footer_str_ = footer_str;
37 header_str_ = header_str;
40 String
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 );
46 str += length_str;
47 str += data_str_;
48 str += footer_str_;
49 return str;
52 Midi_duration::Midi_duration( Real seconds_f )
54 seconds_f_ = seconds_f;
57 String
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 )
65 String str;
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, "" );
79 String
80 Midi_item::i2varint_str( int i )
82 int buffer_i = i & 0x7f;
83 while ( (i >>= 7) > 0 ) {
84 buffer_i <<= 8;
85 buffer_i |= 0x80;
86 buffer_i += (i & 0x7f);
89 String str;
90 while ( 1 ) {
91 str += (char)buffer_i;
92 if ( buffer_i & 0x80 )
93 buffer_i >>= 8;
94 else
95 break;
97 return str;
100 void
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;
109 minor_i_ = minor_i;
112 String
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 )
123 assert(melreq_l);
124 pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;
125 channel_i_ = channel_i;
127 on_b_ = on_bo;
129 dynamic_byte_ = 0x64;
130 if ( on_b_ ) // poor man-s staff dynamics:
131 dynamic_byte_ -= 0x10 * channel_i_;
132 else
133 dynamic_byte_ += 0x32; // 0x64 is supposed to be neutral, but let-s try
136 String
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_;
145 return str;
147 return String( "" );
150 Midi_tempo::Midi_tempo( int per_minute_4_i )
152 per_minute_4_i_ = per_minute_4_i;
155 String
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 )
166 num_i_ = num_i;
167 den_i_ = den_i;
168 clocks_per_1_i_ = clocks_per_1_i;
171 String
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 )
184 type_ = type;
185 text_str_ = text_str;
188 String
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() );
194 str += text_str_;
195 return str;
198 Midi_track::Midi_track( int number_i )
200 // 4D 54 72 6B MTrk
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
206 // sf = -7: 7 flats
207 // sf = -1: 1 flat
208 // sf = 0: key of C
209 // sf = 1: 1 sharp
210 // sf = 7: 7 sharps
211 // mi = 0: major key
212 // mi = 1: minor key
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?
220 // key: C
221 // "00" "ff59" "02" "00" "00"
222 // key: F (scsii-menuetto)
223 // "00" "ff59" "02" "ff" "00"
226 String data_str;
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 );
236 void
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 );
243 void
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() );