lilypond-0.0.77.jcn1
[lilypond.git] / src / midi-item.cc
blob9d121cfcd8730aa3d4a9b55408fdf2bff8b8fb27
1 //
2 // midi-item.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 "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 "midi-item.hh"
17 #include "midi-stream.hh"
18 #include "string-convert.hh"
20 Midi_chunk::Midi_chunk()
24 void
25 Midi_chunk::add( String str )
27 data_str_ += str;
30 void
31 Midi_chunk::set( String header_str, String data_str, String footer_str )
33 data_str_ = data_str;
34 footer_str_ = footer_str;
35 header_str_ = header_str;
38 String
39 Midi_chunk::str()
41 String str = header_str_;
42 String length_str = String_convert::i2hex_str( data_str_.length_i() + footer_str_.length_i(), 8, '0' );
43 length_str = String_convert::hex2bin_str( length_str );
44 str += length_str;
45 str += data_str_;
46 str += footer_str_;
47 return str;
50 Midi_duration::Midi_duration( Real seconds_f )
52 seconds_f_ = seconds_f;
55 String
56 Midi_duration::str()
58 return String( "<duration: " ) + String( seconds_f_ ) + ">";
61 Midi_header::Midi_header( int format_i, int tracks_i, int clocks_per_4_i )
63 String str;
65 String format_str = String_convert::i2hex_str( format_i, 4, '0' );
66 str += String_convert::hex2bin_str( format_str );
68 String tracks_str = String_convert::i2hex_str( tracks_i, 4, '0' );
69 str += String_convert::hex2bin_str( tracks_str );
71 String tempo_str = String_convert::i2hex_str( clocks_per_4_i, 4, '0' );
72 str += String_convert::hex2bin_str( tempo_str );
74 set( "MThd", str, "" );
77 String
78 Midi_item::i2varint_str( int i )
80 int buffer_i = i & 0x7f;
81 while ( (i >>= 7) > 0 ) {
82 buffer_i <<= 8;
83 buffer_i |= 0x80;
84 buffer_i += (i & 0x7f);
87 String str;
88 while ( 1 ) {
89 str += (char)buffer_i;
90 if ( buffer_i & 0x80 )
91 buffer_i >>= 8;
92 else
93 break;
95 return str;
98 void
99 Midi_item::output_midi( Midi_stream& midi_stream_r )
101 midi_stream_r << str();
105 Midi_note::Midi_note( Melodic_req* melreq_l, int channel_i, bool on_bo )
107 assert(melreq_l);
108 pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;
109 channel_i_ = channel_i;
111 // poor man-s staff dynamics:
112 dynamic_byte_ = (melreq_l)? 0x64 - 0x10 * channel_i_:0;
113 on_b_ = on_bo;
116 String
117 Midi_note::str()
119 if ( pitch_i_ != INT_MAX ) {
120 Byte status_byte = ( on_b_ ? 0x90 : 0x80 ) + channel_i_;
121 String str = String( (char)status_byte );
122 str += (char)pitch_i_;
123 // poor man-s staff dynamics:
124 str += (char)dynamic_byte_;
125 return str;
127 return String( "" );
130 Midi_tempo::Midi_tempo( int tempo_i )
132 tempo_i_ = tempo_i;
135 String
136 Midi_tempo::str()
138 int useconds_per_4_i = 60 * (int)1e6 / tempo_i_;
139 String str = "ff5103";
140 str += String_convert::i2hex_str( useconds_per_4_i, 6, '0' );
141 return String_convert::hex2bin_str( str );
144 Midi_track::Midi_track( int number_i )
146 // 4D 54 72 6B MTrk
147 // 00 00 00 3B chunk length (59)
148 // 00 FF 58 04 04 02 18 08 time signature
149 // 00 FF 51 03 07 A1 20 tempo
151 // FF 59 02 sf mi Key Signature
152 // sf = -7: 7 flats
153 // sf = -1: 1 flat
154 // sf = 0: key of C
155 // sf = 1: 1 sharp
156 // sf = 7: 7 sharps
157 // mi = 0: major key
158 // mi = 1: minor key
160 number_i_ = number_i;
162 char const* data_ch_c_l = "00" "ff58" "0404" "0218" "08"
163 // "00" "ff51" "0307" "a120"
164 // why a key at all, in midi?
165 // key: C
166 "00" "ff59" "02" "00" "00"
167 // key: F (scsii-menuetto)
168 // "00" "ff59" "02" "ff" "00"
171 String data_str;
172 // only for format 0 (currently using format 1)?
173 data_str += String_convert::hex2bin_str( data_ch_c_l );
175 char const* footer_ch_c_l = "00" "ff2f" "00";
176 String footer_str = String_convert::hex2bin_str( footer_ch_c_l );
178 set( "MTrk", data_str, footer_str );
181 void
182 Midi_track::add( int delta_time_i, String event_str )
184 assert(delta_time_i >= 0);
185 Midi_chunk::add( i2varint_str( delta_time_i ) + event_str );
188 void
189 Midi_track::add( Moment delta_time_moment, Midi_item* mitem_l )
191 // use convention of 384 clocks per 4
192 // use Duration_convert
193 int delta_time_i = delta_time_moment * Moment( 384 ) / Moment( 1, 4 );
194 add( delta_time_i, mitem_l->str() );