From 6cea332dd176e75dd6c2ab2d92505cadfdfcd99f Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Fri, 15 Aug 1997 13:50:30 +0200 Subject: [PATCH] partial: 0.1.8.jcn --- mi2mu/include/mi2mu-global.hh | 32 ++++ mi2mu/include/mudela-column.hh | 29 ++++ mi2mu/include/mudela-item.hh | 130 +++++++++++++++ mi2mu/include/mudela-score.hh | 53 ++++++ mi2mu/include/mudela-staff.hh | 48 ++++++ mi2mu/include/mudela-stream.hh | 40 +++++ mi2mu/include/mudela-voice.hh | 29 ++++ mi2mu/mudela-column.cc | 24 +++ mi2mu/mudela-item.cc | 295 +++++++++++++++++++++++++++++++++ mi2mu/mudela-score.cc | 200 ++++++++++++++++++++++ mi2mu/mudela-staff.cc | 237 ++++++++++++++++++++++++++ mi2mu/mudela-stream.cc | 165 ++++++++++++++++++ mi2mu/mudela-voice.cc | 74 +++++++++ 13 files changed, 1356 insertions(+) create mode 100644 mi2mu/include/mi2mu-global.hh create mode 100644 mi2mu/include/mudela-column.hh create mode 100644 mi2mu/include/mudela-item.hh create mode 100644 mi2mu/include/mudela-score.hh create mode 100644 mi2mu/include/mudela-staff.hh create mode 100644 mi2mu/include/mudela-stream.hh create mode 100644 mi2mu/include/mudela-voice.hh create mode 100644 mi2mu/mudela-column.cc create mode 100644 mi2mu/mudela-item.cc create mode 100644 mi2mu/mudela-score.cc create mode 100644 mi2mu/mudela-staff.cc create mode 100644 mi2mu/mudela-stream.cc create mode 100644 mi2mu/mudela-voice.cc diff --git a/mi2mu/include/mi2mu-global.hh b/mi2mu/include/mi2mu-global.hh new file mode 100644 index 0000000000..cb577d0bdf --- /dev/null +++ b/mi2mu/include/mi2mu-global.hh @@ -0,0 +1,32 @@ +// +// mi2mu-global.hh -- declare global (sic) stuff for mi2mu +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MI2MU_GLOBAL_HH +#define MI2MU_GLOBAL_HH + +#include "string.hh" +#include "proto.hh" + +#define monitor_p_g &cout +enum Verbose { QUIET_ver, BRIEF_ver, NORMAL_ver, VERBOSE_ver, DEBUG_ver }; +extern Verbose level_ver; +#if 0 // NPRINT + // not what i want, all output goes through tors. + // set verbosity level. + #define LOGOUT(threshold) if (0) *monitor_p_g +#else + #define LOGOUT(threshold) if (level_ver >= threshold) *monitor_p_g +#endif + +extern Sources* source_l_g; +// huh? +void message (String message_str); //, char const* context_ch_C); +void warning (String message_str); //, char const* context_ch_C); +void error (String message_str); //, char const* context_ch_C); + +String mi2mu_version_str(); + +#endif // MI2MU_GLOBAL_HH + diff --git a/mi2mu/include/mudela-column.hh b/mi2mu/include/mudela-column.hh new file mode 100644 index 0000000000..24d5196308 --- /dev/null +++ b/mi2mu/include/mudela-column.hh @@ -0,0 +1,29 @@ +// +// mudela-column.hh -- declare Mudela_column +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MUDELA_COLUMN_HH +#define MUDELA_COLUMN_HH + +#include "proto.hh" +#include "mi2mu-proto.hh" +#include "moment.hh" +#include "plist.hh" + +/// (mudela_column) +class Mudela_column +{ +public: + Mudela_column (Mudela_score* mudela_score_l, Moment mom); + + void add_item (Mudela_item* mudela_item_l); + Moment at_mom(); + + Link_list mudela_item_l_list_; + Moment at_mom_; + Mudela_score* mudela_score_l_; +}; + +#endif // MUDELA_COLUMN_HH + diff --git a/mi2mu/include/mudela-item.hh b/mi2mu/include/mudela-item.hh new file mode 100644 index 0000000000..ba0d77c518 --- /dev/null +++ b/mi2mu/include/mudela-item.hh @@ -0,0 +1,130 @@ +// +// mudela-item.hh -- declare mudela_item +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MUDELA_ITEM_HH +#define MUDELA_ITEM_HH + +#include "mi2mu-proto.hh" +#include "string.hh" +#include "moment.hh" +#include "duration.hh" + +// should these: +// * be Mudela_items +// * be Voice_elements/requests +// * get a name-change +// ? + +/// (mudela_item) +class Mudela_item +{ +public: + Mudela_item (Mudela_column* mudela_column_l); + + virtual Moment at_mom(); + virtual Moment duration_mom(); + void output (Mudela_stream& mudela_stream_r); + virtual String str() = 0; + + Mudela_column* mudela_column_l_; +}; + +class Mudela_key : public Mudela_item +{ +public: + Mudela_key (int accidentals_i, int minor_i); + + String notename_str (int pitch_i); + virtual String str(); + +private: + int accidentals_i_; + int minor_i_; + int key_i_; +}; + +class Mudela_meter : public Mudela_item +{ +public: + Mudela_meter (int num_i, int den_i, int division_4_i, int count_32_i); + + Duration i2_dur (int time_i, int division_1_i); + int clocks_1_i(); + int den_i(); + int num_i(); + virtual String str(); + Moment bar_mom(); + +private: + Real sync_f_; + Duration sync_dur_; + int clocks_1_i_; + int num_i_; + int den_i_; +}; + +class Mudela_note : public Mudela_item +{ +public: + Mudela_note (Mudela_column* mudela_column_l, int channel_i, int pitch_i, int dyn_i); + + Duration duration(); + virtual Moment duration_mom(); + virtual String str(); + +// int const c0_pitch_i_c_ = 60; // huh? + int const c0_pitch_i_c_ = 48; + + static bool const simple_plet_b_s = false; + int channel_i_; + int pitch_i_; + Mudela_column* end_column_l_; +}; + +class Mudela_skip : public Mudela_item +{ +public: + Mudela_skip (Mudela_column* mudela_column_l, Moment skip_mom); + + Duration duration(); + virtual Moment duration_mom(); + virtual String str(); + +private: + Moment mom_; +}; + + +class Mudela_tempo : public Mudela_item +{ +public: + Mudela_tempo (int useconds_per_4_i); + + int get_tempo_i (Moment moment); + virtual String str(); + int useconds_per_4_i(); + +private: + int useconds_per_4_i_; + Real seconds_per_1_f_; +}; + +class Mudela_text : public Mudela_item +{ +public: + enum Type { + TEXT = 1, COPYRIGHT, TRACK_NAME, INSTRUMENT_NAME, LYRIC, + MARKER, CUE_POINT + }; + Mudela_text (Mudela_text::Type type, String str); + virtual String str(); + +private: + Type type_; + String text_str_; +}; + +#endif // MUDELA_ITEM_HH + diff --git a/mi2mu/include/mudela-score.hh b/mi2mu/include/mudela-score.hh new file mode 100644 index 0000000000..6d752fe1d6 --- /dev/null +++ b/mi2mu/include/mudela-score.hh @@ -0,0 +1,53 @@ +// +// mudela-score.hh -- declare Mudela_score +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MUDELA_SCORE_HH +#define MUDELA_SCORE_HH + +#include "mi2mu-proto.hh" +#include "proto.hh" +#include "plist.hh" +#include "parray.hh" + +/// (mudela_score) +class Mudela_score { +public: + Mudela_score (int format_i, int tracks_i, int tempo_i); + ~Mudela_score(); + + void add_item (Mudela_item* mudela_item_p); + void add_staff (Mudela_staff* mudela_staff_p); + + Mudela_column* mudela_column_l (Moment mom); + + void output (String filename_str); + void process(); + + // ugh + Mudela_key* mudela_key_l_; + Mudela_meter* mudela_meter_l_; + Mudela_tempo* mudela_tempo_l_; + +private: + void filter_tempo(); + void quantify_columns(); + void quantify_durations(); + void settle_columns(); + + Pointer_list mudela_column_p_list_; + Pointer_list mudela_staff_p_list_; +// Link_array column_l_array_; + // huh? + Link_array column_l_array_; + +// ugh, ugh, ugh +public: + int format_i_; + int tracks_i_; + int tempo_i_; +}; + +#endif // MUDELA_SCORE_HH + diff --git a/mi2mu/include/mudela-staff.hh b/mi2mu/include/mudela-staff.hh new file mode 100644 index 0000000000..06fc8b25c7 --- /dev/null +++ b/mi2mu/include/mudela-staff.hh @@ -0,0 +1,48 @@ +// +// mudela-staff.hh -- declare mudela_staff +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MUDELA_STAFF_HH +#define MUDELA_STAFF_HH + +#include "mi2mu-proto.hh" +#include "proto.hh" +#include "plist.hh" +#include "string.hh" + +/// (mudela_staff) +class Mudela_staff { +public: + Mudela_staff (int number_i, String copyright_str, String track_name_str, String instrument_str); + ~Mudela_staff(); + + void add_item (Mudela_item* mudela_item_p); + void eat_voice (Link_list& items); + String id_str(); + String name_str(); + void output (Mudela_stream& mudela_stream_r); + void process(); + void set_meter (int num_i, int den_i, int clocks_i, int count_32_i); + void set_tempo (int useconds_i); + + String copyright_str_; + String instrument_str_; + String name_str_; + Mudela_meter* mudela_meter_p_; + Mudela_tempo* mudela_tempo_p_; + int number_i_; + +private: + void output_mudela_begin_bar (Mudela_stream& mudela_stream_r, Moment now_mom, int bar_i); +#if 0 + void output_mudela_rest (Mudela_stream& mudela_stream_r, Moment begin_mom, Moment end_mom); + void output_mudela_rest_remain (Mudela_stream& mudela_stream_r, Moment mom); +#endif + + Pointer_list mudela_voice_p_list_; + Pointer_list mudela_item_p_list_; +}; + +#endif // MUDELA_STAFF_HH + diff --git a/mi2mu/include/mudela-stream.hh b/mi2mu/include/mudela-stream.hh new file mode 100644 index 0000000000..f353838ea6 --- /dev/null +++ b/mi2mu/include/mudela-stream.hh @@ -0,0 +1,40 @@ +// +// mudela-stream.hh -- part of LilyPond +// +// copyright 1997 Jan Nieuwenhuizen + +// should i be named Mudela_stream? + +#ifndef MUDELA_STREAM_HH +#define MUDELA_STREAM_HH + +#include "mi2mu-proto.hh" +#include "string.hh" + +/// Lily output +class Mudela_stream { +public: + Mudela_stream (String filename_str); + ~Mudela_stream(); + + Mudela_stream& operator << (String str); + Mudela_stream& operator << (Mudela_item& mudela_item_r); + +private: + void handle_pending_indent(); + void header(); + void open(); + void output (String str); + void output_wrapped (String str); + + ostream* os_p_; + String filename_str_; + int indent_i_; + int column_i_; + int pending_indent_i_; + int wrap_column_i_; + bool comment_mode_b_; +}; + +#endif // MUDELA_STREAM_HH + diff --git a/mi2mu/include/mudela-voice.hh b/mi2mu/include/mudela-voice.hh new file mode 100644 index 0000000000..ab4aef142d --- /dev/null +++ b/mi2mu/include/mudela-voice.hh @@ -0,0 +1,29 @@ +// +// mudela-voice.hh -- declare Mudela_voice +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MUDELA_VOICE_HH +#define MUDELA_VOICE_HH + +#include "mi2mu-proto.hh" +#include "plist.hh" + +/// (mudela_voice) +class Mudela_voice { +public: + Mudela_voice (Mudela_staff* mudela_staff_l); + + void add_item (Mudela_item* mudela_item_l); + Moment begin_mom(); + Moment end_mom(); + + void output (Mudela_stream& mudela_stream_r); + +private: + Mudela_staff* mudela_staff_l_; + Link_list mudela_item_l_list_; +}; + +#endif // MUDELA_VOICE_HH + diff --git a/mi2mu/mudela-column.cc b/mi2mu/mudela-column.cc new file mode 100644 index 0000000000..871be0cc61 --- /dev/null +++ b/mi2mu/mudela-column.cc @@ -0,0 +1,24 @@ +// +// mudela-column.cc -- implement Mudela_column +// +// copyright 1997 Jan Nieuwenhuizen + +#include "mudela-column.hh" + +Mudela_column::Mudela_column (Mudela_score* mudela_score_l, Moment mom) +{ + mudela_score_l_ = mudela_score_l; + at_mom_ = mom; +} + +void +Mudela_column::add_item (Mudela_item* mudela_item_l) +{ + mudela_item_l_list_.bottom().add (mudela_item_l); +} + +Moment +Mudela_column::at_mom() +{ + return at_mom_; +} diff --git a/mi2mu/mudela-item.cc b/mi2mu/mudela-item.cc new file mode 100644 index 0000000000..4e8f7ccf98 --- /dev/null +++ b/mi2mu/mudela-item.cc @@ -0,0 +1,295 @@ +// +// mudela-item.cc -- implement Mudela_item +// +// copyright 1997 Jan Nieuwenhuizen + +#include "mi2mu-global.hh" +#include "string-convert.hh" +#include "duration-convert.hh" +#include "mudela-column.hh" +#include "mudela-item.hh" +#include "mudela-stream.hh" +#include "mudela-score.hh" + +Mudela_item::Mudela_item (Mudela_column* mudela_column_l) +{ + mudela_column_l_ = mudela_column_l; +} + +Moment +Mudela_item::at_mom() +{ + return mudela_column_l_->at_mom(); +} + +Moment +Mudela_item::duration_mom() +{ + return Moment (0); +} + +void +Mudela_item::output (Mudela_stream& mudela_stream_r) +{ + mudela_stream_r << str() << String (" "); +} + +Mudela_key::Mudela_key (int accidentals_i, int minor_i) + : Mudela_item (0) +{ + accidentals_i_ = accidentals_i; + minor_i_ = minor_i; + if (accidentals_i >= 0) + key_i_ = ((accidentals_i % 7)[ "cgdaebf" ] - 'a' - 2) % 7; + else + key_i_ = ((-accidentals_i % 7)[ "cfbeadg" ] - 'a' - 2) % 7; +} + +String +Mudela_key::str() +{ + String str = "\\key "; + if (!minor_i_) + str += String ((char) ((key_i_ + 2) % 7 + 'A')); + else // heu, -2: should be - 1 1/2: A -> fis + str += String ((char) ((key_i_ + 2 - 2) % 7 + 'a')); + str = String ("% \"") + str + + String('"') + "; % not supported yet\n"; + return str; +} + +String +Mudela_key::notename_str (int pitch_i) +{ + // this may seem very smart, + // but it-s only an excuse not to read a notename table + + // major scale: do-do + // minor scale: la-la (= + 5) + static int notename_i_a[ 12 ] = { 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6 }; + int notename_i = notename_i_a[ (minor_i_ * 5 + pitch_i) % 12 ]; + + static int accidentals_i_a[ 12 ] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 }; + int accidental_i = accidentals_i_a[ minor_i_ * 5 + pitch_i % 12 ]; + if (accidental_i && (accidentals_i_ < 0)) { + accidental_i = - accidental_i; + notename_i = (notename_i + 1) % 7; + } + + String notename_str = (char) ( ((notename_i + 2) % 7) + 'a'); + while (accidental_i-- > 0) + notename_str += "is"; + accidental_i++; + while (accidental_i++ < 0) + if ((notename_str == "a") || (notename_str == "e")) + notename_str += "s"; + else + notename_str += "es"; + accidental_i--; + + String de_octavate_str = String ('\'', (Mudela_note::c0_pitch_i_c_ + 11 - pitch_i) / 12); + String octavate_str = String ('\'', (pitch_i - Mudela_note::c0_pitch_i_c_) / 12); + return de_octavate_str + notename_str + octavate_str; +} + +Mudela_meter::Mudela_meter (int num_i, int den_i, int clocks_4_i, int count_32_i) + : Mudela_item (0) +{ + sync_dur_.type_i_ = 8 ; + sync_f_ = 1.0; + if (count_32_i != 8) + warning (String ("#32 in quarter: ") + String (count_32_i)); + num_i_ = num_i; + den_i_ = den_i; + clocks_1_i_ = clocks_4_i * 4; +} + +Moment +Mudela_meter::bar_mom() +{ + Duration d; + d.type_i_ = (1 << den_i_); + return Moment (num_i_) * Duration_convert::dur2_mom (d); +} + +int +Mudela_meter::clocks_1_i() +{ + return clocks_1_i_; +} + +int +Mudela_meter::den_i() +{ + return den_i_; +} + +int +Mudela_meter::num_i() +{ + return num_i_; +} + +String +Mudela_meter::str() +{ + String str = "\\meter " + + String (num_i_) + "/" + String (1 << den_i_) + + ";\n"; + return str; +} + + +// statics Mudela_note +/* + this switch can be used to write simple plets like + c4*2/3 + as + \plet 2/3; c4 \plet 1/1; + */ +bool const Mudela_note::simple_plet_b_s = true; + +Mudela_note::Mudela_note (Mudela_column* mudela_column_l, int channel_i, int pitch_i, int dyn_i) + : Mudela_item (mudela_column_l) +{ + // junk dynamics + (void)dyn_i; + channel_i_ = channel_i; + pitch_i_ = pitch_i; + end_column_l_ = 0; +} + +String +Mudela_note::str() +{ + Duration dur = duration(); + if (!dur.type_i_) + return ""; + + String name_str = mudela_column_l_->mudela_score_l_->mudela_key_l_->notename_str (pitch_i_); + + if (simple_plet_b_s) + return name_str + Duration_convert::dur2_str (dur) + " "; + + //ugh + String str; + if (dur.plet_b()) + str += String ("\\plet ") + + String_convert::i2dec_str (dur.plet_.iso_i_, 0, 0) + + "/" + + String_convert::i2dec_str (dur.plet_.type_i_, 0, 0) + + "; "; + + str += name_str; + + Duration tmp = dur; + tmp.set_plet (1,1); + str += Duration_convert::dur2_str (tmp); + + if (dur.plet_b()) + str += String (" \\plet 1/1;"); + + return str + " "; +} + +Duration +Mudela_note::duration() +{ + assert (end_column_l_); + Moment mom = end_column_l_->at_mom() - at_mom(); + if (Duration_convert::no_quantify_b_s) + return Duration_convert::mom2_dur (mom); + + return Duration_convert::mom2standardised_dur (mom); +} + +Moment +Mudela_note::duration_mom() +{ +// ugh +// return Duration_convert::dur2_mom (duration()); + return end_column_l_->at_mom() - at_mom(); +} + +Mudela_skip::Mudela_skip (Mudela_column* mudela_column_l, Moment skip_mom) + : Mudela_item (mudela_column_l) +{ + mom_ = skip_mom; +} + +Duration +Mudela_skip::duration() +{ + if (Duration_convert::no_quantify_b_s) + return Duration_convert::mom2_dur (mom_); + + return Duration_convert::mom2standardised_dur (mom_); +} + +Moment +Mudela_skip::duration_mom() +{ + return Duration_convert::dur2_mom (duration()); +} + +String +Mudela_skip::str() +{ + if (!mom_) + return String (""); + + Duration dur = duration(); + if (!dur.type_i_) + return ""; + + String str = "\\skip "; + str += Duration_convert::dur2_str (dur) + "; "; + + return str; +} + +Mudela_tempo::Mudela_tempo (int useconds_per_4_i) + : Mudela_item (0) +{ + useconds_per_4_i_ = useconds_per_4_i; + seconds_per_1_f_ = (Real)useconds_per_4_i_ * 4 / 1e6; +} + +String +Mudela_tempo::str() +{ + String str = "\\tempo 4="; + str += String (get_tempo_i (Moment (1, 4))); + str += ";\n"; + return str; +} + +int +Mudela_tempo::useconds_per_4_i() +{ + return useconds_per_4_i_; +} + +int +Mudela_tempo::get_tempo_i (Moment moment) +{ + return Moment (60) / moment / Moment (seconds_per_1_f_); +} + +Mudela_text::Mudela_text (Mudela_text::Type type, String text_str) + : Mudela_item (0) +{ + type_ = type; + text_str_ = text_str; +} + +String +Mudela_text::str() +{ + if (!text_str_.length_i() + || (text_str_.length_i() != (int)strlen (text_str_.ch_C()))) + return ""; + + return "% " + text_str_ + "\n"; +} + diff --git a/mi2mu/mudela-score.cc b/mi2mu/mudela-score.cc new file mode 100644 index 0000000000..2a82a630c1 --- /dev/null +++ b/mi2mu/mudela-score.cc @@ -0,0 +1,200 @@ +// +// mudela-score.cc -- implement Mudela_score +// +// copyright 1997 Jan Nieuwenhuizen + +#include "moment.hh" +#include "duration.hh" +#include "duration-convert.hh" +#include "mi2mu-global.hh" +#include "mudela-column.hh" +#include "mudela-item.hh" +#include "mudela-score.hh" +#include "mudela-staff.hh" +#include "mudela-stream.hh" + +Mudela_score::Mudela_score (int format_i, int tracks_i, int tempo_i) +{ + format_i_ = format_i; + tracks_i_ = tracks_i; + tempo_i_ = tempo_i; + mudela_column_p_list_.bottom().add (new Mudela_column (this, Moment (0))); +} + +Mudela_score::~Mudela_score() +{ +} + +void +Mudela_score::add_item (Mudela_item* mudela_item_p) +{ + mudela_staff_p_list_.bottom()->add_item (mudela_item_p); +} + +void +Mudela_score::add_staff (Mudela_staff* mudela_staff_p) +{ + mudela_staff_p_list_.bottom().add (mudela_staff_p); +} + +Mudela_column* +Mudela_score::mudela_column_l (Moment mom) +{ + for (PCursor i (mudela_column_p_list_); i.ok(); i++) { + if (i->at_mom() > mom) { + Mudela_column* p = new Mudela_column (this, mom); + i.insert (p); + return p; + } + if (i->at_mom() == mom) + return *i; + } + + Mudela_column* p = new Mudela_column (this, mom); + mudela_column_p_list_.bottom().add (p); + return p; +} + +void +Mudela_score::output (String filename_str) +{ + LOGOUT(NORMAL_ver) << "Lily output to " << filename_str << " ..." << endl; + + // ugh, ugly midi type 1 fix + if ( (mudela_staff_p_list_.size() == 1) && !mudela_staff_p_list_.top()->number_i_) + mudela_staff_p_list_.top()->number_i_ = 1; + + int track_i = 0; + Mudela_stream mudela_stream (filename_str); + for (PCursor i (mudela_staff_p_list_); i.ok(); i++) { + LOGOUT(NORMAL_ver) << "track " << track_i++ << ": " << flush; + i->output (mudela_stream); + mudela_stream << "\n"; + LOGOUT(NORMAL_ver) << endl; + } + + mudela_stream << "\\score{\n"; + if (mudela_staff_p_list_.size() > 1) + mudela_stream << "<\n\\multi 3;\n"; + for (PCursor i (mudela_staff_p_list_); i.ok(); i++) { + if ( (mudela_staff_p_list_.size() != 1) + && (i == mudela_staff_p_list_.top())) + continue; + mudela_stream << "\\melodic{ "; + mudela_stream << "\\$" << i->id_str(); + mudela_stream << " }\n"; + } + if (mudela_staff_p_list_.size() > 1) + mudela_stream << ">\n"; + + mudela_stream << "\\paper{}\n"; + + mudela_stream << "\\midi{ "; + // let's not use silly 0 track + mudela_staff_p_list_.bottom()->mudela_tempo_p_->output (mudela_stream); + mudela_stream << "}\n"; + + mudela_stream << "}\n"; +} + +void +Mudela_score::process() +{ + LOGOUT(NORMAL_ver) << "\nProcessing..." << endl; + + LOGOUT(DEBUG_ver) << "columns\n"; + for (PCursor i (mudela_column_p_list_); i.ok(); i++) + LOGOUT(DEBUG_ver) << "At: " << i->at_mom() << "\n"; + + settle_columns(); + filter_tempo(); + quantify_columns(); + quantify_durations(); + + LOGOUT(NORMAL_ver) << "\nCreating voices..." << endl; + int track_i = 0; + for (PCursor i (mudela_staff_p_list_); i.ok(); i++) { + LOGOUT(NORMAL_ver) << "track " << track_i++ << ": " << flush; + i->process(); + LOGOUT(NORMAL_ver) << endl; + } +} + +void +Mudela_score::filter_tempo() +{ + LOGOUT(NORMAL_ver) << "\nNOT Filtering tempo..." << endl; +} + +void +Mudela_score::quantify_columns() +{ + // ugh + if (Duration_convert::no_quantify_b_s) { + LOGOUT(NORMAL_ver) << "\nNOT Quantifying columns..." << endl; + return; + } + + LOGOUT(NORMAL_ver) << "\nQuantifying columns..." << endl; + + int n = 32 >? Duration_convert::no_smaller_than_i_s; + Moment s = Moment (1, n); + Moment sh = Moment (1, 2 * n); + for (int i = 0; i < column_l_array_.size(); i++) { +// Moment mom = column_l_array_[ i ]->at_mom(); +// column_l_array_[ i ]->at_mom_ = Duration_convert::dur2_mom (dur); + column_l_array_[ i ]->at_mom_ = +// s * (int) ( (sh + column_l_array_[ i ]->at_mom()) / s); + s * (int) ( (column_l_array_[ i ]->at_mom()) / s); + LOGOUT(NORMAL_ver) << '.'; + } + LOGOUT(NORMAL_ver) << endl; +} + +void +Mudela_score::quantify_durations() +{ +// LOGOUT(NORMAL_ver) << "\nQuantifying durations..." << endl; +} + +void +Mudela_score::settle_columns() +{ +// LOGOUT(NORMAL_ver) << "\nNOT Settling columns..." << endl; +// return; + LOGOUT(NORMAL_ver) << "\nSettling columns..." << endl; + + assert (!column_l_array_.size()); + int n = mudela_column_p_list_.size(); +// huh? +// column_l_array_.set_size (n); + for (PCursor i (mudela_column_p_list_); i.ok(); i++) + column_l_array_.push (*i); + + int start_i = 0; + int end_i = 0; + Moment start_mom = 0; + Duration smallest_dur; + smallest_dur.type_i_ = 64; + Moment const noise_mom = Duration_convert::dur2_mom (smallest_dur) + / Moment (2); + for (int i = 0; i < n; i++) { + if (!start_i) { + start_i = end_i = i; + start_mom = column_l_array_[ i ]->at_mom(); + continue; + } + + // find all columns within noise's distance + while ( (i < n) + && (column_l_array_[ i ]->at_mom() - start_mom < noise_mom)) + end_i = ++i; + + // bluntly set all to time of first in group + for (int j = start_i; j < end_i; j++) + column_l_array_[ j ]->at_mom_ = start_mom; + + start_i = end_i = 0; + } +} + diff --git a/mi2mu/mudela-staff.cc b/mi2mu/mudela-staff.cc new file mode 100644 index 0000000000..0c13ec4aac --- /dev/null +++ b/mi2mu/mudela-staff.cc @@ -0,0 +1,237 @@ +// +// mudela-staff.cc -- implement Mudela_staff +// +// copyright 1997 Jan Nieuwenhuizen + +#include +#include "moment.hh" +#include "duration-convert.hh" +#include "string-convert.hh" +#include "mi2mu-proto.hh" +#include "mi2mu-global.hh" +#include "mudela-column.hh" +#include "mudela-item.hh" +#include "mudela-staff.hh" +#include "mudela-stream.hh" +#include "mudela-voice.hh" + +Mudela_staff::Mudela_staff (int number_i, String copyright_str, String track_name_str, String instrument_str) +{ + number_i_ = number_i; + copyright_str_ = copyright_str; + instrument_str_ = instrument_str; + name_str_ = track_name_str; + mudela_meter_p_ = new Mudela_meter (4, 2, 24, 8); + mudela_tempo_p_ = new Mudela_tempo (1000000); +} + +Mudela_staff::~Mudela_staff() +{ + delete mudela_meter_p_; + delete mudela_tempo_p_; +} + +void +Mudela_staff::add_item (Mudela_item* mudela_item_p) +{ + mudela_item_p_list_.bottom().add (mudela_item_p); + if (mudela_item_p->mudela_column_l_) + mudela_item_p->mudela_column_l_->add_item (mudela_item_p); +} + +void +Mudela_staff::eat_voice (Link_list& items) +{ + Mudela_voice* voice_p = new Mudela_voice (this); + mudela_voice_p_list_.bottom().add (voice_p); + +// Moment mom = items.top()->at_mom(); + Moment mom = 0; + + for (PCursor i (items); i.ok();) { + LOGOUT(DEBUG_ver) << "At: " << i->at_mom() << "; "; + LOGOUT(DEBUG_ver) << "dur: " << i->duration_mom() << "; "; + LOGOUT(DEBUG_ver) << "mom: " << mom << " -> "; + if (i->at_mom() > mom) { + // ugh, liek + voice_p->add_item (new Mudela_skip (i->mudela_column_l_, i->at_mom() - mom)); + mom = i->at_mom(); + } + if (i->at_mom() == mom) { + mom = i->at_mom() + i->duration_mom(); + voice_p->add_item (i.remove_p()); + // ugh + } + else if (i.ok()) + i++; + LOGOUT(DEBUG_ver) << "mom: " << mom << "\n"; + } +} + +String +Mudela_staff::id_str() +{ + String str = name_str(); + for (int i = 0; i < str.length_i(); i++) + if ( (!i && !isalpha (str[ i ])) + || !isalnum (str[ i ])) + * (str.ch_l() + i) = '_'; + return str; +} + +String +Mudela_staff::name_str() +{ + if (name_str_.length_i()) + return name_str_; + return String ("track") + String (number_i_); +} + +void +Mudela_staff::output (Mudela_stream& mudela_stream_r) +{ + mudela_stream_r << "$" << id_str() << " = \\melodic"; + mudela_stream_r << (mudela_voice_p_list_.size() > 1 ? "<" : "{"); + mudela_stream_r << "\n"; + mudela_stream_r << "% midi copyright:" << copyright_str_ << "\n"; + mudela_stream_r << "% instrument:" << instrument_str_ << "\n"; + + if (mudela_voice_p_list_.size() == 1) + mudela_voice_p_list_.top()->output (mudela_stream_r); + else + for (PCursor i (mudela_voice_p_list_); i.ok(); i++) { + mudela_stream_r << "{ "; + i->output (mudela_stream_r); + mudela_stream_r << "} "; + } + + mudela_stream_r << (mudela_voice_p_list_.size() > 1 ? "\n>" : "\n}"); + mudela_stream_r << " % " << name_str() << "\n"; +} + +void +Mudela_staff::output_mudela_begin_bar (Mudela_stream& mudela_stream_r, Moment now_mom, int bar_i) +{ + Moment bar_mom = mudela_meter_p_->bar_mom(); + Moment into_bar_mom = now_mom - Moment (bar_i - 1) * bar_mom; + if (bar_i > 1) { + if (!into_bar_mom) + mudela_stream_r << "|\n"; + } + mudela_stream_r << "% " << String_convert::i2dec_str (bar_i, 0, ' '); + if (into_bar_mom) + mudela_stream_r << ":" << Duration_convert::dur2_str (Duration_convert::mom2_dur (into_bar_mom)); + mudela_stream_r << "\n"; +} + + +#if 0 // not used for now +void +Mudela_staff::output_mudela_rest (Mudela_stream& mudela_stream_r, Moment begin_mom, Moment end_mom) +{ + Moment bar_mom = mudela_meter_p_->bar_mom(); + Moment now_mom = begin_mom; + + int begin_bar_i = (int) (now_mom / bar_mom) + 1; + int end_bar_i = (int) (end_mom / bar_mom) + 1; + + if (end_bar_i == begin_bar_i) { + output_mudela_rest_remain (mudela_stream_r, end_mom - begin_mom); + return; + } + + // multiple bars involved + int bar_i = (int) (now_mom / bar_mom) + 1; + + //fill current bar + Moment begin_bar_mom = Moment (begin_bar_i - 1) * bar_mom; + if (now_mom > begin_bar_mom) { + int next_bar_i = (int) (now_mom / bar_mom) + 2; + Moment next_bar_mom = Moment (next_bar_i - 1) * bar_mom; + assert (next_bar_mom <= end_mom); + + Moment remain_mom = next_bar_mom - now_mom; + if (remain_mom > Moment (0)) { + output_mudela_rest_remain (mudela_stream_r, remain_mom); + now_mom += remain_mom; + } + + bar_i = check_end_bar_i (now_mom, bar_i); + } + + // fill whole bars + int count_i = end_bar_i - bar_i; + for (int i = 0; i < count_i; i++) { + int begin_bar_i = check_begin_bar_i (now_mom, bar_i); + if (begin_bar_i) + output_mudela_begin_bar (mudela_stream_r, now_mom, begin_bar_i); + mudela_stream_r << "r1 "; +// *mudela_stream_r.os_p_ << flush; + if (begin_bar_i) + LOGOUT(NORMAL_ver) << begin_bar_i << flush; + bar_i = check_end_bar_i (now_mom, bar_i); + now_mom += bar_mom; + } + + // use "int i" here, and gcc 2.7.2 hits internal compiler error + int ii = check_begin_bar_i (now_mom, bar_i); + if (ii) + output_mudela_begin_bar (mudela_stream_r, now_mom, ii); + +// bar_i = check_end_bar_i (now_mom, bar_i); + + Moment remain_mom = end_mom - Moment (end_bar_i - 1) * bar_mom; + if (remain_mom > Moment (0)) { + output_mudela_rest_remain (mudela_stream_r, remain_mom); + now_mom += remain_mom; + } + assert (now_mom == end_mom); +} + +void +Mudela_staff::output_mudela_rest_remain (Mudela_stream& mudela_stream_r, Moment mom) +{ + if (Duration_convert::no_quantify_b_s) { + Duration dur = Duration_convert::mom2_dur (mom); + mudela_stream_r << "r" << dur.str() << " "; +// assert (mom == dur.mom()); + assert (mom == dur.length()); + return; + } + + Duration dur = Duration_convert::mom2standardised_dur (mom); + if (dur.type_i_) + mudela_stream_r << "r" << dur.str() << " "; +} +#endif + + +void +Mudela_staff::process() +{ + /* + group items into voices + */ + + Link_list items; + for (PCursor i (mudela_item_p_list_); i.ok(); i++) + items.bottom().add (*i); + + while (items.size()) + eat_voice (items); +} + +void +Mudela_staff::set_tempo (int useconds_per_4_i) +{ + delete mudela_tempo_p_; + mudela_tempo_p_ = new Mudela_tempo (useconds_per_4_i); +} + +void +Mudela_staff::set_meter (int num_i, int den_i, int clocks_i, int count_32_i) +{ + delete mudela_meter_p_; + mudela_meter_p_ = new Mudela_meter (num_i, den_i, clocks_i, count_32_i); +} + diff --git a/mi2mu/mudela-stream.cc b/mi2mu/mudela-stream.cc new file mode 100644 index 0000000000..7b7dbb8244 --- /dev/null +++ b/mi2mu/mudela-stream.cc @@ -0,0 +1,165 @@ +// +// mudela-stream.cc +// +// source file of the LilyPond music typesetter +// +// (c) 1997 Jan Nieuwenhuizen + +#include +#include +#include "mi2mu-global.hh" +#include "my-midi-parser.hh" +#include "mudela-item.hh" +#include "mudela-stream.hh" + +static int const INDENT_i = 8; + +Mudela_stream::Mudela_stream (String filename_str) +{ + filename_str_ = filename_str; + os_p_ = 0; + indent_i_ = 0; + comment_mode_b_ = false; + column_i_ = 0; + wrap_column_i_ = 68; + open(); + header(); +} + +Mudela_stream::~Mudela_stream() +{ + delete os_p_; + if (indent_i_) + warning ("lily indent level: " + String (indent_i_)); +} + +Mudela_stream& +Mudela_stream::operator << (String str) +{ + static String word_sep_str = "{} \t\n"; + while (str.length_i()) { + int i = str.index_any_i (word_sep_str) + 1; + if (!i) + i = str.length_i(); + String word = str.left_str (i); + str = str.mid_str (i, str.length_i()); + output_wrapped (word); + } + return *this; +} + +Mudela_stream& +Mudela_stream::operator << (Mudela_item& mudela_item_r) +{ + mudela_item_r.output (*this); + *os_p_ << flush; + return *this; +} + +void +Mudela_stream::handle_pending_indent() +{ + *os_p_ << String ('\t', pending_indent_i_); + column_i_ += pending_indent_i_ * INDENT_i; + pending_indent_i_ = 0; +} + +void +Mudela_stream::header() +{ + *os_p_ << "% Creator: " << mi2mu_version_str() << "\n"; + *os_p_ << "% Automatically generated, at "; + time_t t (time (0)); + *os_p_ << ctime (&t); + *os_p_ << "% from input file: "; + *os_p_ << midi_parser_l_g->filename_str_; + *os_p_ << "\n\n"; + // ugh + *os_p_ << "\\version \"0.1.1\";\n"; +} + +void +Mudela_stream::open() +{ + os_p_ = new ofstream (filename_str_); + if (!*os_p_) + error ("can't open: `" + filename_str_ + "\'"); +} + +void +Mudela_stream::output (String str) +{ + for (int i = 0; i < str.length_i(); i++) { + char c = str[ i ]; + switch (c) { + case '{' : + case '<' : + handle_pending_indent(); + if (column_i_ == indent_i_ * INDENT_i) + output ("\t"); + indent_i_++; + *os_p_ << c; + column_i_++; + break; + case '}' : + case '>' : + assert (indent_i_); + indent_i_--; + if (pending_indent_i_) + pending_indent_i_--; + handle_pending_indent(); + *os_p_ << c; + column_i_++; + break; + case '%' : + handle_pending_indent(); + comment_mode_b_ = true; + *os_p_ << c; + column_i_++; + break; + case '\t' : + handle_pending_indent(); + *os_p_ << c; + column_i_ += INDENT_i; + break; + case '\n' : + *os_p_ << endl; + pending_indent_i_ = indent_i_; + column_i_ = 0; + comment_mode_b_ = false; + break; + default : + handle_pending_indent(); + *os_p_ << c; + column_i_++; + break; + } + } +} + +void +Mudela_stream::output_wrapped (String str) +{ + // enough room left -> doit + if (column_i_ + str.length_i() <= wrap_column_i_) { + output (str); + return; + } + + // we're at BOL already; this will never fit -> doit + if (column_i_ == indent_i_ * INDENT_i) { + output (str); + return; + } + + // ok, let's wrap + // preserve comment mode + if (comment_mode_b_) + output (String ("\n%")); + else + output (String ("\n")); + + output (str); +} + + diff --git a/mi2mu/mudela-voice.cc b/mi2mu/mudela-voice.cc new file mode 100644 index 0000000000..5fd2704726 --- /dev/null +++ b/mi2mu/mudela-voice.cc @@ -0,0 +1,74 @@ +// +// mudela-voice.cc -- implement Mudela_voice +// +// copyright 1997 Jan Nieuwenhuizen + +#include "string-convert.hh" +#include "mi2mu-global.hh" +#include "mudela-column.hh" +#include "mudela-item.hh" +#include "mudela-staff.hh" +#include "mudela-stream.hh" +#include "mudela-voice.hh" + +Mudela_voice::Mudela_voice (Mudela_staff* mudela_staff_l) +{ + mudela_staff_l_ = mudela_staff_l; +} + +void +Mudela_voice::add_item (Mudela_item* mudela_item_l) +{ + mudela_item_l_list_.bottom().add (mudela_item_l); +} + +Moment +Mudela_voice::begin_mom() +{ + return mudela_item_l_list_.size() ? + mudela_item_l_list_.top()->at_mom() : Moment (0); +} + +Moment +Mudela_voice::end_mom() +{ + return mudela_item_l_list_.size() ? + mudela_item_l_list_.bottom()->at_mom() : Moment (0); +} + +static int const FAIRLY_LONG_VOICE_i = 6; + +void +Mudela_voice::output (Mudela_stream& mudela_stream_r) +{ + if (!mudela_item_l_list_.size()) + return; + + if (mudela_item_l_list_.size() > FAIRLY_LONG_VOICE_i) + mudela_stream_r << "\n"; + + int current_bar_i = 0; + Moment bar_mom = mudela_staff_l_->mudela_meter_p_->bar_mom(); + + for (PCursor i (mudela_item_l_list_); i.ok(); i++) { + Moment at_mom = i->mudela_column_l_->at_mom(); + int bar_i = (int) (at_mom / bar_mom) + 1; + if (bar_i > current_bar_i) { + if (current_bar_i) { + if (at_mom == Moment (bar_i - 1) * bar_mom) + mudela_stream_r << "|"; + mudela_stream_r << "\n% "; + mudela_stream_r << String_convert::i2dec_str (bar_i, 0, ' '); + mudela_stream_r << "\n"; + } + LOGOUT(NORMAL_ver) << '[' << bar_i << ']' << flush; + current_bar_i = bar_i; + } + + mudela_stream_r << i->str(); + } + + if (mudela_item_l_list_.size() > FAIRLY_LONG_VOICE_i) + mudela_stream_r << "\n"; +} + -- 2.39.5