lilypond-0.0.33
[lilypond.git] / src / midiitem.cc
blobe7d5ccc92f48556ba0a063af5799f1c4986b0717
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 "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"
19 Midi_chunk::Midi_chunk()
23 void
24 Midi_chunk::add( String str )
26 data_str_ += str;
29 void
30 Midi_chunk::set( String header_str, String data_str, String footer_str )
32 data_str_ = data_str;
33 footer_str_ = footer_str;
34 header_str_ = header_str;
37 String
38 Midi_chunk::str()
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;
49 Midi_duration::Midi_duration( Real seconds_f )
51 seconds_f_ = seconds_f;
54 String
55 Midi_duration::str()
57 return String( "<duration: " ) + String( seconds_f_ ) + ">";
60 Midi_header::Midi_header( int format_i, int tracks_i, int tempo_i )
62 String str;
64 String format_str = StringConversion::int2hex_str( format_i, 4, '0' );
65 str += StringConversion::hex2bin_str( format_str );
67 String tracks_str = StringConversion::int2hex_str( tracks_i, 4, '0' );
68 str += StringConversion::hex2bin_str( tracks_str );
70 String tempo_str = StringConversion::int2hex_str( tempo_i, 4, '0' );
71 str += StringConversion::hex2bin_str( tempo_str );
73 set( "MThd", str, "" );
76 String
77 Midi_item::int2varlength_str( int i )
79 int buffer_i = i & 0x7f;
80 while ( (i >>= 7) > 0 ) {
81 buffer_i <<= 8;
82 buffer_i |= 0x80;
83 buffer_i += (i & 0x7f);
86 String str;
87 while ( 1 ) {
88 str += (char)buffer_i;
89 if ( buffer_i & 0x80 )
90 buffer_i >>= 8;
91 else
92 break;
94 return str;
97 void
98 Midi_item::output_midi( Midi_stream& midi_stream_r )
100 midi_stream_r << str();
104 Midi_note::Midi_note( Melodic_req* melreq_l, int channel_i, bool on_bo )
106 pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;
107 channel_i_ = channel_i;
108 on_bo_ = on_bo;
111 String
112 Midi_note::str()
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;
123 return String( "" );
126 Midi_track::Midi_track( int number_i )
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
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
142 number_i_ = number_i;
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"
153 String data_str;
154 // only for format 0 (currently using format 1)?
155 data_str += StringConversion::hex2bin_str( data_ch_c_l );
157 char const* footer_ch_c_l = "00" "ff2f" "00";
158 String footer_str = StringConversion::hex2bin_str( footer_ch_c_l );
160 set( "MTrk", data_str, footer_str );
163 void
164 Midi_track::add( int delta_time_i, String event_str )
166 Midi_chunk::add( int2varlength_str( delta_time_i ) + event_str );
169 void
170 Midi_track::add( Moment delta_time_moment, Midi_item* mitem_l )
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() );