source file of the GNU LilyPond music typesetter
- (c) 1997--1998 Jan Nieuwenhuizen <janneke@gnu.org>
+ (c) 1997--1999 Jan Nieuwenhuizen <janneke@gnu.org>
*/
#include "proto.hh"
-#include "plist.hh"
-#include "pcursor.hh"
#include "debug.hh"
#include "misc.hh"
#include "string.hh"
#include "string-convert.hh"
-#include "command-request.hh"
-#include "musical-request.hh"
#include "midi-item.hh"
#include "midi-stream.hh"
#include "audio-item.hh"
+#include "duration.hh"
+#include "killing-cons.tcc"
-
-
-
-
-
-
-
-
-
-
-
-
-Midi_chunk::Midi_chunk ()
- : Midi_item (0)
+Midi_item*
+Midi_item::midi_p (Audio_item* a)
{
+ if (Audio_key* i = dynamic_cast<Audio_key*> (a))
+ return new Midi_key (i);
+ else if (Audio_instrument* i = dynamic_cast<Audio_instrument*> (a))
+ return i->str_.length_i () ? new Midi_instrument (i) : 0;
+ else if (Audio_note* i = dynamic_cast<Audio_note*> (a))
+ return new Midi_note (i);
+ else if (Audio_tempo* i = dynamic_cast<Audio_tempo*> (a))
+ return new Midi_tempo (i);
+ else if (Audio_time_signature* i = dynamic_cast<Audio_time_signature*> (a))
+ return new Midi_time_signature (i);
+ else if (Audio_text* i = dynamic_cast<Audio_text*> (a))
+ return i->text_str_.length_i () ? new Midi_text (i) : 0;
+ else
+ assert (0);
+
+ // isn't C++ grand?
+ return 0;
}
void
{
String str = header_str_;
String dat = data_str ();
-#if 1
String length_str = String_convert::i2hex_str (dat.length_i ()
-#else
- // huh, huh??
- String length_str = String_convert::i2hex_str (data_str_.length_i ()
-#endif
+ footer_str_.length_i (), 8, '0');
length_str = String_convert::hex2bin_str (length_str);
str += length_str;
}
Midi_duration::Midi_duration (Real seconds_f)
- : Midi_item (0)
{
seconds_f_ = seconds_f;
}
return String ("<duration: ") + to_str (seconds_f_) + ">";
}
-Midi_event::Midi_event (Moment delta_mom, Midi_item* mitem_p)
+Midi_event::Midi_event (Moment delta_mom, Midi_item* midi_p)
{
delta_mom_ = delta_mom;
- mitem_p_ = mitem_p;
-}
-
-Midi_event::~Midi_event ()
-{
-// uhuh
-// delete mitem_p_;
+ midi_p_ = midi_p;
}
String
{
int delta_i = delta_mom_ * Moment (Duration::division_1_i_s);
String delta_str = Midi_item::i2varint_str (delta_i);
- String mitem_str = mitem_p_->str ();
- assert (mitem_str.length_i ());
- return delta_str + mitem_str;
+ String midi_str = midi_p_->str ();
+ assert (midi_str.length_i ());
+ return delta_str + midi_str;
}
Midi_header::Midi_header (int format_i, int tracks_i, int clocks_per_4_i)
- : Midi_chunk ()
{
String str;
set ("MThd", str, "");
}
+/* why doesn't this start at 0 ?
+ */
char const* const instrument_name_sz_a_[ ] = {
-
/* default is usually piano */
/* 0 "piano", */
- /* (1-8 piano) */
- /* 1 */ "acoustic grand",
+ /* (1-8 piano) */
+ /* 1 */ "acoustic grand",
/* 2 */ "bright acoustic",
/* 3 */ "electric grand",
/* 4 */ "honky-tonk",
0
};
-Midi_instrument::Midi_instrument (int channel_i, String instrument_str)
- : Midi_item (0)
-{
- instrument_str_ = instrument_str;
- instrument_str_.to_lower ();
- channel_i_ = channel_i;
-}
-
-Midi_item::~Midi_item ()
+Midi_instrument::Midi_instrument (Audio_instrument* a)
{
+ audio_l_ = a;
+ audio_l_->str_.to_lower ();
}
String
Midi_instrument::str () const
{
Byte program_byte = 0;
- for (int i = 0; instrument_name_sz_a_[i]; i++)
- if (instrument_str_ == String (instrument_name_sz_a_[ i ]))
+ bool found = false;
+ for (int i = 0; !found && instrument_name_sz_a_[i]; i++)
+ if (audio_l_->str_ == String (instrument_name_sz_a_[ i ]))
{
program_byte = (Byte)i;
- break;
+ found = true;
}
+ if (!found)
+ {
+ warning (_f("No such instrument: `%s'", audio_l_->str_.ch_C ()));
+ }
+
String str = to_str ((char) (0xc0 + channel_i_));
str += to_str ((char)program_byte);
return str;
}
-Midi_item::Midi_item (Audio_item* audio_item_l)
+Midi_item::Midi_item ()
{
- audio_item_l_ = audio_item_l;
channel_i_ = 0;
}
+Midi_item::~Midi_item ()
+{
+}
+
String
Midi_item::i2varint_str (int i)
{
return str;
}
-Midi_key::Midi_key (Audio_item* audio_item_l)
- : Midi_item (audio_item_l)
+Midi_key::Midi_key (Audio_key*a)
{
+ audio_l_ = a;
}
String
Midi_key::str () const
{
- Key_change_req* k = dynamic_cast <Key_change_req *> (audio_item_l_->req_l_);
- int sharps_i = k->sharps_i ();
- int flats_i = k->flats_i ();
+ int sharps_i = audio_l_->key_.sharps_i ();
+ int flats_i = audio_l_->key_.flats_i ();
// midi cannot handle non-conventional keys
if (flats_i && sharps_i)
String str = "ff5902";
str += String_convert::i2hex_str (accidentals_i, 2, '0');
- int minor_i = k->minor_b ();
- str += String_convert::i2hex_str (minor_i, 2, '0');
+ str += String_convert::i2hex_str ((int)audio_l_->key_.minor_b (), 2, '0');
return String_convert::hex2bin_str (str);
}
-Midi_time_signature::Midi_time_signature (Audio_item* audio_item_l)
- : Midi_item (audio_item_l)
+Midi_time_signature::Midi_time_signature (Audio_time_signature* a)
{
+ audio_l_ = a;
clocks_per_1_i_ = 18;
}
String
Midi_time_signature::str () const
{
- Time_signature_change_req* m = dynamic_cast <Time_signature_change_req *> (audio_item_l_->req_l_);
- int num_i = m->beats_i_;
- int den_i = m->one_beat_i_;
+ int num_i = audio_l_->beats_i_;
+ int den_i = audio_l_->one_beat_i_;
String str = "ff5804";
str += String_convert::i2hex_str (num_i, 2, '0');
return String_convert::hex2bin_str (str);
}
-Midi_note::Midi_note (Audio_item* audio_item_l)
- : Midi_item (audio_item_l)
+Midi_note::Midi_note (Audio_note* a)
{
+ audio_l_ = a;
dynamic_byte_ = 0x7f;
- assert (dynamic_cast<Audio_note*> (audio_item_l));
}
Moment
Midi_note::length_mom () const
{
- Moment m = dynamic_cast <Rhythmic_req *> (audio_item_l_->req_l_)->length_mom ();
+ Moment m = audio_l_->length_mom_;
+#if 0
if (m < Moment (1, 1000))
{
warning (_ ("silly duration"));
m = 1;
}
+#endif
return m;
}
int
Midi_note::pitch_i () const
{
- int p = dynamic_cast <Melodic_req*> (audio_item_l_->req_l_)->pitch_.semitone_pitch ()
- + dynamic_cast<Audio_note*>(audio_item_l_)->transposing_i_;
+ int p = audio_l_->pitch_.semitone_pitch () + audio_l_->transposing_i_;
if (p == INT_MAX)
{
warning (_ ("silly pitch"));
String str = to_str ((char)status_byte);
str += to_str ((char) (pitch_i () + c0_pitch_i_c_));
- // poor man's staff dynamics:
- str += to_str ((char) (dynamic_byte_ - 0x10 * channel_i_));
-
+ str += to_str ((char)dynamic_byte_);
return str;
}
-Midi_note_off::Midi_note_off (Midi_note* midi_note_l)
- : Midi_item (midi_note_l->audio_item_l_)
+Midi_note_off::Midi_note_off (Midi_note* n)
+ : Midi_note (n->audio_l_)
{
- // 0x64 is supposed to be neutral, but let's try
- aftertouch_byte_ = 0x64;
- channel_i_ = midi_note_l->channel_i_;
-}
+ on_l_ = n;
+ channel_i_ = n->channel_i_;
+
+ // Anybody who hears any difference, or knows how this works?
+ // 0 should definitely be avoided, notes stick on some sound cards.
+ // 64 is supposed to be neutral
+ aftertouch_byte_ = 64;
-int
-Midi_note_off::pitch_i () const
-{
- return dynamic_cast <Melodic_req *> (audio_item_l_->req_l_)->pitch_.semitone_pitch ()
- + dynamic_cast<Audio_note*>(audio_item_l_)->transposing_i_;
}
String
return str;
}
-Midi_tempo::Midi_tempo (Audio_item* audio_item_l)
- : Midi_item (audio_item_l)
+Midi_tempo::Midi_tempo (Audio_tempo* a)
{
- per_minute_4_i_ = dynamic_cast<Audio_tempo*>(audio_item_l_)->per_minute_4_i_;
-}
-
-Midi_tempo::Midi_tempo (int per_minute_4_i)
- : Midi_item (0)
-{
- per_minute_4_i_ = per_minute_4_i;
+ audio_l_ = a;
}
String
Midi_tempo::str () const
{
- int useconds_per_4_i = 60 * (int)1e6 / per_minute_4_i_;
+ int useconds_per_4_i = 60 * (int)1e6 / audio_l_->per_minute_4_i_;
String str = "ff5103";
str += String_convert::i2hex_str (useconds_per_4_i, 6, '0');
return String_convert::hex2bin_str (str);
}
-Midi_text::Midi_text (Audio_item* audio_item_l)
- : Midi_item (audio_item_l)
+Midi_text::Midi_text (Audio_text* a)
{
- text_str_ = dynamic_cast<Audio_text*>(audio_item_l_)->text_str_;
- type_ = (Type) dynamic_cast<Audio_text*>(audio_item_l_)->type_;
+ audio_l_ = a;
}
+#if 0
Midi_text::Midi_text (Midi_text::Type type, String text_str)
- : Midi_item (0)
+ : Audio_text ()
{
text_str_ = text_str;
type_ = type;
}
+#endif
String
Midi_text::str () const
{
- String str = "ff" + String_convert::i2hex_str (type_, 2, '0');
+ String str = "ff" + String_convert::i2hex_str (audio_l_->type_, 2, '0');
str = String_convert::hex2bin_str (str);
- str += i2varint_str (text_str_.length_i ());
- str += text_str_;
+ str += i2varint_str (audio_l_->text_str_.length_i ());
+ str += audio_l_->text_str_;
return str;
}
}
void
-Midi_track::add (Moment delta_time_mom, Midi_item* mitem_p)
+Midi_track::add (Moment delta_time_mom, Midi_item* midi_p)
{
assert (delta_time_mom >= Moment (0));
- event_p_list_.bottom ().add (new Midi_event (delta_time_mom, mitem_p));
+ Midi_event * e = new Midi_event (delta_time_mom, midi_p);
+ event_p_list_.append (new Killing_cons<Midi_event> (e, 0));
}
String
Midi_track::data_str () const
{
String str = Midi_chunk::data_str ();
- if (check_debug && !monitor->silent_b ("Midistrings"))
+ if (check_debug && !lily_monitor->silent_b ("Midistrings"))
str += "\n";
- for (PCursor<Midi_event*> i (event_p_list_); i.ok (); i++)
+ for (Cons<Midi_event> *i=event_p_list_.head_; i; i = i->next_)
{
- str += i->str ();
- if (check_debug && !monitor->silent_b ("Midistrings"))
+ str += i->car_->str ();
+ if (check_debug && !lily_monitor->silent_b ("Midistrings"))
str += "\n";
}
return str;
}
-
-Midi_track::~Midi_track ()
-{
-}