2 midi-item.cc -- implement MIDI items.
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2008 Jan Nieuwenhuizen <janneke@gnu.org>
9 #include "midi-item.hh"
11 #include "duration.hh"
12 #include "international.hh"
14 #include "midi-stream.hh"
16 #include "program-option.hh"
17 #include "string-convert.hh"
20 #define PITCH_WHEEL_TOP 0x3FFF
21 #define PITCH_WHEEL_CENTER 0x2000
22 #define PITCH_WHEEL_BOTTOM 0x0000
23 #define PITCH_WHEEL_RANGE (PITCH_WHEEL_TOP - PITCH_WHEEL_BOTTOM)
26 Midi_item::get_midi (Audio_item
*a
)
28 if (Audio_key
*i
= dynamic_cast<Audio_key
*> (a
))
29 return new Midi_key (i
);
30 else if (Audio_instrument
*i
= dynamic_cast<Audio_instrument
*> (a
))
31 return i
->str_
.length () ? new Midi_instrument (i
) : 0;
32 else if (Audio_note
*i
= dynamic_cast<Audio_note
*> (a
))
33 return new Midi_note (i
);
34 else if (Audio_dynamic
*i
= dynamic_cast<Audio_dynamic
*> (a
))
35 return new Midi_dynamic (i
);
36 else if (Audio_piano_pedal
*i
= dynamic_cast<Audio_piano_pedal
*> (a
))
37 return new Midi_piano_pedal (i
);
38 else if (Audio_tempo
*i
= dynamic_cast<Audio_tempo
*> (a
))
39 return new Midi_tempo (i
);
40 else if (Audio_time_signature
*i
= dynamic_cast<Audio_time_signature
*> (a
))
41 return new Midi_time_signature (i
);
42 else if (Audio_text
*i
= dynamic_cast<Audio_text
*> (a
))
43 return new Midi_text (i
);
52 Midi_duration::Midi_duration (Real seconds_f
)
58 Midi_duration::to_string () const
60 return string ("<duration: ") + ::to_string (seconds_
) + ">";
63 Midi_instrument::Midi_instrument (Audio_instrument
*a
)
66 audio_
->str_
= String_convert::to_lower (audio_
->str_
);
70 Midi_instrument::to_string () const
72 Byte program_byte
= 0;
75 SCM proc
= ly_lily_module_constant ("midi-program");
76 SCM program
= scm_call_1 (proc
, ly_symbol2scm (audio_
->str_
.c_str ()));
77 found
= (program
!= SCM_BOOL_F
);
79 program_byte
= scm_to_int (program
);
81 warning (_f ("no such MIDI instrument: `%s'", audio_
->str_
.c_str ()));
83 string str
= ::to_string ((char) (0xc0 + channel_
)); //YIKES! FIXME : Should be track. -rz
84 str
+= ::to_string ((char)program_byte
);
88 Midi_item::Midi_item ()
92 Midi_channel_item::Midi_channel_item ()
97 Midi_item::~Midi_item ()
102 int2midi_varint_string (int i
)
104 int buffer
= i
& 0x7f;
105 while ((i
>>= 7) > 0)
109 buffer
+= (i
& 0x7f);
115 str
+= ::to_string ((char)buffer
);
124 Midi_key::Midi_key (Audio_key
*a
)
130 Midi_key::to_string () const
132 string str
= "ff5902";
133 str
+= String_convert::int2hex (audio_
->accidentals_
, 2, '0');
135 str
+= String_convert::int2hex (0, 2, '0');
137 str
+= String_convert::int2hex (1, 2, '0');
138 return String_convert::hex2bin (str
);
141 Midi_time_signature::Midi_time_signature (Audio_time_signature
*a
)
148 Midi_time_signature::to_string () const
150 int num
= abs (audio_
->beats_
);
153 warning ("Time signature with more than 255 beats. Truncating");
157 int den
= audio_
->one_beat_
;
161 string str
= "ff5804";
162 str
+= String_convert::int2hex (num
, 2, '0');
163 str
+= String_convert::int2hex (intlog2 (den
), 2, '0');
164 str
+= String_convert::int2hex (clocks_per_1_
, 2, '0');
165 str
+= String_convert::int2hex (8, 2, '0');
166 return String_convert::hex2bin (str
);
169 Midi_note::Midi_note (Audio_note
*a
)
172 dynamic_byte_
= 0x7f;
177 Midi_note::get_fine_tuning () const
179 Rational tune
= (audio_
->pitch_
.tone_pitch ()
180 + audio_
->transposing_
.tone_pitch ()) * Rational (2);
181 tune
-= Rational (get_semitone_pitch ());
184 return (int) double (tune
);
188 Midi_note::get_semitone_pitch () const
190 return int (double ((audio_
->pitch_
.tone_pitch ()
191 + audio_
->transposing_
.tone_pitch ()) * Rational (2)));
195 Midi_note::to_string () const
197 Byte status_byte
= (char) (0x90 + channel_
);
201 // print warning if fine tuning was needed, HJJ
202 if (get_fine_tuning () != 0)
204 finetune
= PITCH_WHEEL_CENTER
;
205 // Move pitch wheel to a shifted position.
206 // The pitch wheel range (of 4 semitones) is multiplied by the cents.
207 finetune
+= (PITCH_WHEEL_RANGE
*get_fine_tuning ()) / (4 * 100);
209 str
+= ::to_string ((char) (0xE0 + channel_
));
210 str
+= ::to_string ((char) (finetune
& 0x7F));
211 str
+= ::to_string ((char) (finetune
>> 7));
212 str
+= ::to_string ((char) (0x00));
215 str
+= ::to_string ((char) status_byte
);
216 str
+= ::to_string ((char) (get_semitone_pitch () + c0_pitch_
));
217 str
+= ::to_string ((char) dynamic_byte_
);
222 Midi_note_off::Midi_note_off (Midi_note
*n
)
223 : Midi_note (n
->audio_
)
226 channel_
= n
->channel_
;
228 // Anybody who hears any difference, or knows how this works?
229 // 0 should definitely be avoided, notes stick on some sound cards.
230 // 64 is supposed to be neutral
232 aftertouch_byte_
= 64;
236 Midi_note_off::to_string () const
238 Byte status_byte
= (char) (0x80 + channel_
);
240 string str
= ::to_string ((char)status_byte
);
241 str
+= ::to_string ((char) (get_semitone_pitch () + Midi_note::c0_pitch_
));
242 str
+= ::to_string ((char)aftertouch_byte_
);
244 if (get_fine_tuning () != 0)
246 // Move pitch wheel back to the central position.
247 str
+= ::to_string ((char) 0x00);
248 str
+= ::to_string ((char) (0xE0 + channel_
));
249 str
+= ::to_string ((char) (PITCH_WHEEL_CENTER
&0x7F));
250 str
+= ::to_string ((char) (PITCH_WHEEL_CENTER
>> 7));
256 Midi_dynamic::Midi_dynamic (Audio_dynamic
*a
)
262 Midi_dynamic::to_string () const
264 Byte status_byte
= (char) (0xB0 + channel_
);
265 string str
= ::to_string ((char)status_byte
);
268 Main volume controller (per channel):
272 static Real
const full_scale
= 127;
274 int volume
= (int) (audio_
->volume_
* full_scale
);
277 if (volume
> full_scale
)
278 volume
= (int)full_scale
;
280 str
+= ::to_string ((char)0x07);
281 str
+= ::to_string ((char)volume
);
285 Midi_piano_pedal::Midi_piano_pedal (Audio_piano_pedal
*a
)
291 Midi_piano_pedal::to_string () const
293 Byte status_byte
= (char) (0xB0 + channel_
);
294 string str
= ::to_string ((char)status_byte
);
296 if (audio_
->type_string_
== "Sostenuto")
297 str
+= ::to_string ((char)0x42);
298 else if (audio_
->type_string_
== "Sustain")
299 str
+= ::to_string ((char)0x40);
300 else if (audio_
->type_string_
== "UnaCorda")
301 str
+= ::to_string ((char)0x43);
303 int pedal
= ((1 - audio_
->dir_
) / 2) * 0x7f;
304 str
+= ::to_string ((char)pedal
);
308 Midi_tempo::Midi_tempo (Audio_tempo
*a
)
314 Midi_tempo::to_string () const
316 int useconds_per_4
= 60 * (int)1e6
/ audio_
->per_minute_4_
;
317 string str
= "ff5103";
318 str
+= String_convert::int2hex (useconds_per_4
, 6, '0');
319 return String_convert::hex2bin (str
);
322 Midi_text::Midi_text (Audio_text
*a
)
328 Midi_text::to_string () const
330 string str
= "ff" + String_convert::int2hex (audio_
->type_
, 2, '0');
331 str
= String_convert::hex2bin (str
);
332 str
+= int2midi_varint_string (audio_
->text_string_
.length ());
333 str
+= audio_
->text_string_
;
338 Midi_item::name () const
340 return this->class_name ();