From 9aa705b2bdd27d83e3d9b9020b673cc4902a4dd2 Mon Sep 17 00:00:00 2001 From: fred Date: Mon, 5 Jul 1999 09:41:22 +0000 Subject: [PATCH] lilypond-1.1.55 --- midi2ly/main.cc | 271 ++++++++++++++++++++++++++ midi2ly/midi-track-parser.cc | 360 ++++++++++++++++++++++++++++++++++ midi2ly/mudela-item.cc | 363 +++++++++++++++++++++++++++++++++++ midi2ly/mudela-voice.cc | 69 +++++++ 4 files changed, 1063 insertions(+) create mode 100644 midi2ly/main.cc create mode 100644 midi2ly/midi-track-parser.cc create mode 100644 midi2ly/mudela-item.cc create mode 100644 midi2ly/mudela-voice.cc diff --git a/midi2ly/main.cc b/midi2ly/main.cc new file mode 100644 index 0000000000..26e0c66b8e --- /dev/null +++ b/midi2ly/main.cc @@ -0,0 +1,271 @@ +// +// main.cc -- implement silly main () entry point +// should have Root class. +// +// copyright 1997 Jan Nieuwenhuizen + +#include +#include +#include "config.hh" +#include "string-convert.hh" +#include "getopt-long.hh" +#include "file-path.hh" +#include "duration-convert.hh" +#include "source.hh" + +#include "mi2mu-global.hh" +#include "midi-score-parser.hh" +#include "mudela-item.hh" +#include "mudela-score.hh" + +#if HAVE_GETTEXT +#include +#endif + + +// ugh +String filename_str_g; + +// ugh +Mudela_score* mudela_score_l_g = 0; + +bool no_timestamps_b_g = false; + +Sources source; + +static File_path path; + +Verbose level_ver = NORMAL_ver; + +void +usage() +{ + cout << _f ("Usage: %s [OPTION]... [FILE]", "mi2mu"); + cout << '\n'; + cout << _ ("Translate midi-file to mudela"); + cout << '\n'; + cout << '\n'; + cout << _ ("Options:"); + cout << '\n'; + cout << _ ( + " -b, --no-quantify write exact durations, e.g.: a4*385/384\n" + ); + cout << _ ( + " -D, --debug enable debugging output\n" + ); + cout << _ ( + " -h, --help this help\n" + ); + cout << _ ( + " -I, --include=DIR add DIR to search path\n" + ); + cout << _ ( + " -k, --key=ACC[:MINOR] set key: ACC +sharps/-flats; :1 minor\n" + ); + cout << _ ( + " -n, --no-silly assume no plets or double dots, smallest is 32\n" + ); + cout << _ ( + " -o, --output=FILE set FILE as default output\n" + ); + cout << _ ( + " -p, --no-plets assume no plets\n" + ); + cout << _ ( + " -q, --quiet be quiet\n" + ); + cout << _ ( + " -T, --no-timestamps don't timestamp the output\n" + ); + cout << _ ( + " -s, --smallest=N assume no shorter (reciprocal) durations than N\n" + ); + cout << _ ( + " -v, --verbose be verbose\n" + ); + cout << _ ( + " -w, --warranty show warranty and copyright\n" + ); + cout << _ ( + " -x, --no-double-dots assume no double dotted notes\n" + ); + ; +} + +void +identify() +{ + LOGOUT(NORMAL_ver) << mi2mu_version_str() << endl; +} + +void +notice() +{ + LOGOUT(NORMAL_ver) << '\n'; + LOGOUT(NORMAL_ver) << _ ("Mi2mu, translate midi to mudela"); + LOGOUT(NORMAL_ver) << '\n'; + LOGOUT(NORMAL_ver) << _f ("Copyright (c) %s by", "1997, 1998"); + LOGOUT(NORMAL_ver) << '\n'; + LOGOUT(NORMAL_ver) << " " + _ ("Han-Wen Nienhuys ") + "\n"; + LOGOUT(NORMAL_ver) << " " + _ ("Jan Nieuwenhuizen ") + "\n"; + LOGOUT(NORMAL_ver) << '\n'; + LOGOUT(NORMAL_ver) << _ ( + " This program is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU General Public License version 2\n" + "as published by the Free Software Foundation.\n" + "\n" + " This program is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "General Public License for more details.\n" + "\n" + " You should have received a copy (refer to the file COPYING) of the\n" + "GNU General Public License along with this program; if not, write to\n" + "the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,\n" + "USA.\n"); +} + +int +main (int argc_i, char* argv_sz_a[]) +{ + +#if HAVE_GETTEXT + setlocale (LC_ALL, ""); /* enable locales */ + setlocale (LC_NUMERIC, "C"); /* musn't have comma's in output */ + String name (PACKAGE); + name.to_lower (); + bindtextdomain (name.ch_C (), DIR_LOCALEDIR); + textdomain (name.ch_C ()) ; +#endif + + bool key_override_b = false; + Mudela_key key (0, 0); + + Long_option_init long_option_init_a[] = + { + {0, "no-quantify", 'b'}, + {0, "debug", 'D'}, + {0, "help", 'h'}, + {1, "key", 'k'}, + {0, "no-silly", 'n'}, + {1, "output", 'o'}, + {0, "no-plets", 'p'}, + {0, "quiet", 'q'}, + {1, "smallest", 's'}, + {0, "no-timestamps", 'T'}, + {0, "verbose", 'v'}, + {0, "warranty", 'w'}, + {0, "no-double-dots", 'x'}, + {0,0,0} + }; + Getopt_long getopt_long (argc_i, argv_sz_a, long_option_init_a); + + String output_str; + while (Long_option_init const* long_option_init_p = getopt_long()) + switch (long_option_init_p->shortname) + { + case 'b': + Duration_convert::no_quantify_b_s = true; + break; + case 'D': + level_ver = DEBUG_ver; + break; + case 'h': + identify(); + usage(); + exit (0); + break; +// case 'I': +// path->push (getopt_long.optional_argument_ch_C_); +// break; + case 'k': + { + String str = getopt_long.optional_argument_ch_C_; + int i = str.index_i (':'); + i = (i >=0 ? i : str.length_i ()); + key.accidentals_i_ = String_convert::dec2_i (str.left_str (i)); + key.minor_i_ = (int)(bool)String_convert::dec2_i (str.cut_str (i + 1, str.length_i ())); + key_override_b = true; + break; + } + case 'n': + Duration_convert::no_double_dots_b_s = true; + Duration_convert::no_triplets_b_s = true; + Duration_convert::no_smaller_than_i_s = 5; + break; + case 'o': + output_str = getopt_long.optional_argument_ch_C_; + break; + case 'p': + Duration_convert::no_triplets_b_s = true; + break; + case 'q': + level_ver = QUIET_ver; + break; + case 'T': + no_timestamps_b_g = true; + break; + case 's': + { + int i = String_convert::dec2_i (getopt_long.optional_argument_ch_C_); + if (!i) + { + identify(); + usage(); + exit (2); //usage + } + Duration_convert::no_smaller_than_i_s = + Duration_convert::i2_type(i); + } + break; + case 'v': + level_ver = VERBOSE_ver; + break; + case 'w': + identify(); + notice(); + exit (0); + break; + case 'x': + Duration_convert::no_double_dots_b_s = true; + break; + default: + assert (0); + break; + } + + // flag -q must be checked first + identify(); + + path.add (""); + source.set_binary (true); + source.set_path (&path); + + char const* arg_sz = 0; + while ( (arg_sz = getopt_long.get_next_arg ())) + { + filename_str_g = arg_sz; + Midi_score_parser midi_parser; + Mudela_score* score_p = midi_parser.parse (arg_sz, &source); + + if (!score_p) + return 1; + + // if given on command line: override + if (key_override_b || !score_p->mudela_key_l_) + score_p->mudela_key_l_ = &key; + mudela_score_l_g = score_p; + score_p->process(); + + if (!output_str.length_i ()) + { + String d, dir, base, ext; + split_path (arg_sz, d, dir, base, ext); + output_str = base + ext + ".ly"; + } + + score_p->output (output_str); + delete score_p; + } + return 0; +} diff --git a/midi2ly/midi-track-parser.cc b/midi2ly/midi-track-parser.cc new file mode 100644 index 0000000000..49840ec77c --- /dev/null +++ b/midi2ly/midi-track-parser.cc @@ -0,0 +1,360 @@ +/* + midi-track-parser.cc -- implement + + source file of the GNU LilyPond music typesetter + + (c) 1997--1998 Jan Nieuwenhuizen +*/ + +#include +#include "string-convert.hh" +#include "mi2mu-global.hh" +#include "midi-track-parser.hh" +#include "mudela-column.hh" +#include "mudela-item.hh" +#include "mudela-score.hh" +#include "mudela-staff.hh" + +Midi_track_parser::Midi_track_parser (Midi_parser_info* info_l, int i) +{ + info_l_ = info_l; + at_mom_ = 0; + track_info_p_ = 0; + mudela_staff_p_ = new Mudela_staff (i, "", "", ""); + parse_header (); + parse_delta_time (); +} + +Midi_track_parser::~Midi_track_parser () +{ + delete mudela_staff_p_; + delete track_info_p_; +} + +Moment +Midi_track_parser::at_mom () +{ + return at_mom_; +} + +bool +Midi_track_parser::eot () +{ + if ( info_l_->byte_L_ < info_l_->end_byte_L_ ) + return false; + return true; +} + +void +Midi_track_parser::note_end (Mudela_column* col_l, int channel_i, int pitch_i, int aftertouch_i ) +{ + // junk dynamics + (void)aftertouch_i; + + assert (col_l); + + for (Cons** pp = &open_note_l_list_.head_; *pp;) + { + Cons* i = *pp; + if ((i->car_->pitch_i_ == pitch_i) && (i->car_->channel_i_ == channel_i)) + { + i->car_->end_column_l_ = col_l; + delete open_note_l_list_.remove_cons (pp); + return; + } + else + pp = &i->next_; + } + warning (_f ("junking note-end event: channel = %d, pitch = %d", + channel_i, pitch_i)); +} + +void +Midi_track_parser::note_end_all (Mudela_column* col_l) +{ + // find + assert (col_l); + for (Cons* i = open_note_l_list_.head_; i; i = i->next_) + { + i->car_->end_column_l_ = col_l; + } + // UGH UGH. MEMORY LEAK. + open_note_l_list_.init (); +} + +Mudela_staff* +Midi_track_parser::parse (Mudela_column* col_l) +{ + Moment mom = at_mom (); + while (!eot () && (mom == at_mom ())) + { + Mudela_item* p = parse_event (col_l); + if (p) + mudela_staff_p_->add_item (p); + } + + if (!eot()) + return 0; + + // catch-all + note_end_all (col_l); + + Mudela_staff* p = mudela_staff_p_; + mudela_staff_p_ = 0; + return p; +} + +void +Midi_track_parser::parse_delta_time () +{ + if (eot ()) + return; + int delta_i = get_var_i (); + at_mom_ += Moment (delta_i, info_l_->division_1_i_); +} + +Mudela_item* +Midi_track_parser::parse_event (Mudela_column* col_l) +{ + Byte byte = peek_byte (); + // RUNNING_STATUS [\x00-\x5f] + if (byte <= 0x5f) + { + if (running_byte_ <= 0x5f) + exit (_ ("invalid running status")); + /* + 'running status' rather means 'missing status'. + we'll just pretend we read the running status byte. + */ + byte = running_byte_; + } + else + byte = next_byte (); + + Mudela_item* item_p = 0; + // DATA_ENTRY [\x60-\x79] + if ((byte >= 0x60) && (byte <= 0x79)) + { + next_byte (); + } + // ALL_NOTES_OFF [\x7a-\x7f] + else if ((byte >= 0x7a) && (byte <= 0x7f)) + { + next_byte (); + next_byte (); + note_end_all (col_l); + } + // NOTE_OFF [\x80-\x8f] + else if ((byte >= 0x80) && (byte <= 0x8f)) + { + running_byte_ = byte; + int channel_i = byte & ~0x90; + int pitch_i = (int)next_byte (); + int dyn_i = (int)next_byte (); + note_end (col_l, channel_i, pitch_i, dyn_i); + } + // NOTE_ON [\x90-\x9f] + else if ((byte >= 0x90) && (byte <= 0x9f)) + { + running_byte_ = byte; + int channel_i = byte & ~0x90; + int pitch_i = (int)next_byte (); + int dyn_i = (int)next_byte (); + /* + sss: some broken devices encode NOTE_OFF as + NOTE_ON with zero volume + */ + if (dyn_i) + { + Mudela_note* p = new Mudela_note (col_l, channel_i, pitch_i, dyn_i); + item_p = p; + open_note_l_list_.append (new Cons (p, 0)); + } + else + { + note_end (col_l, channel_i, pitch_i, dyn_i); + } + } + + // POLYPHONIC_AFTERTOUCH [\xa0-\xaf] + else if ((byte >= 0xa0) && (byte <= 0xaf)) + { + running_byte_ = byte; + next_byte (); + next_byte (); + } + // CONTROLMODE_CHANGE [\xb0-\xbf] + else if ((byte >= 0xb0) && (byte <= 0xbf)) + { + running_byte_ = byte; + next_byte (); + next_byte (); + } + // PROGRAM_CHANGE [\xc0-\xcf] + else if ((byte >= 0xc0) && (byte <= 0xcf)) + { + running_byte_ = byte; + next_byte (); + } + // CHANNEL_AFTERTOUCH [\xd0-\xdf] + else if ((byte >= 0xd0) && (byte <= 0xdf)) + { + running_byte_ = byte; + next_byte (); + next_byte (); + } + // PITCHWHEEL_RANGE [\xe0-\xef] + else if ((byte >= 0xe0) && (byte <= 0xef)) + { + running_byte_ = byte; + next_byte (); + next_byte (); + } + // SYSEX_EVENT1 [\xf0] + else if (byte == 0xf0) + { + int length_i = get_var_i (); + String str = get_str (length_i); + } + // SYSEX_EVENT2 [\xf7] + else if (byte == 0xf7) + { + int length_i = get_var_i (); + String str = get_str (length_i); + } + // META_EVENT [\xff] + else if (byte == 0xff) + { + // SEQUENCE [\x00][\x02] + byte = next_byte (); + if (byte == 0) + { + next_byte (); + get_i (2); + } + // YYTEXT [\x01] + // YYCOPYRIGHT [\x02] + // YYTRACK_NAME [\x03] + // YYINSTRUMENT_NAME [\x04] + // YYLYRIC [\x05] + // YYMARKER [\x06] + // YYCUE_POINT [\x07] + else if ((byte >= 0x01) && (byte <= 0x07)) + { + // LOGOUT (DEBUG_ver) << "\n% Text(" << (int)byte << "):" << flush; + int length_i = get_var_i (); + String str = get_str (length_i); + // LOGOUT (DEBUG_ver) << str << endl; + Mudela_text::Type t = (Mudela_text::Type)byte; + Mudela_text* p = new Mudela_text (t, str); + item_p = p; + if (t == Mudela_text::COPYRIGHT) + mudela_staff_p_->copyright_str_ = p->text_str_; + else if (t == Mudela_text::TRACK_NAME) + mudela_staff_p_->name_str_ = p->text_str_; + else if (t == Mudela_text::INSTRUMENT_NAME) + mudela_staff_p_->instrument_str_ = p->text_str_; + } + // END_OF_TRACK [\x2f][\x00] + else + { + Byte next = peek_byte (); + if ((byte == 0x2f) && (next == 0x00)) + { + next_byte (); + info_l_->byte_L_ = info_l_->end_byte_L_; + } + // TEMPO [\x51][\x03] + else if ((byte == 0x51) && (next == 0x03)) + { + next_byte (); + unsigned useconds_per_4_u = get_u (3); + // $$ = new Mudela_tempo ( ($2 << 16) + ($3 << 8) + $4); + // LOGOUT (DEBUG_ver) << $$->str() << endl; + Mudela_tempo* p = new Mudela_tempo ( useconds_per_4_u ); + item_p = p; + info_l_->score_l_->mudela_tempo_l_ = p; + mudela_staff_p_->mudela_tempo_l_ = p; + } + // SMPTE_OFFSET [\x54][\x05] + else if ((byte == 0x54) && (next == 0x05)) + { + next_byte (); + (int)next_byte (); + (int)next_byte (); + (int)next_byte (); + (int)next_byte (); + (int)next_byte (); + } + // TIME [\x58][\x04] + else if ((byte == 0x58) && (next == 0x04)) + { + next_byte (); + int num_i = (int)next_byte (); + int den_i = (int)next_byte (); + int clocks_4_i = (int)next_byte (); + int count_32_i = (int)next_byte (); + Mudela_time_signature* p = new Mudela_time_signature ( num_i, den_i, clocks_4_i, count_32_i ); + item_p = p; + info_l_->score_l_->mudela_time_signature_l_ = p; + info_l_->bar_mom_ = p->bar_mom (); + mudela_staff_p_->mudela_time_signature_l_ = p; + } + // KEY [\x59][\x02] + else if ((byte == 0x59) && (next == 0x02)) + { + next_byte (); + int accidentals_i = (int)(signed char)next_byte (); + int minor_i = (int)(bool)next_byte (); + Mudela_key* p = new Mudela_key (accidentals_i, minor_i); + item_p = p; +#if 0 + info_l_->score_l_->mudela_key_l_ = p; + mudela_staff_p_->mudela_key_l_ = p; +#endif + } + // SSME [\0x7f][\x03] + else if ((byte == 0x7f) && (next == 0x03)) + { + next_byte (); + int length_i = get_var_i (); + String str = get_str (length_i); + item_p = new Mudela_text ((Mudela_text::Type)byte, str); + } + else + { + next_byte (); + next_byte (); + warning (_ ("unimplemented MIDI meta-event")); + } + } + } + else + exit (_ ("invalid MIDI event")); + + if (item_p) + item_p->mudela_column_l_ = col_l; + + parse_delta_time (); + + return item_p; +} + +void +Midi_track_parser::parse_header () +{ + String str = get_str (4); + if ( str != "MTrk" ) + exit (_ ("MIDI track expected")); + + int length_i = get_i (4); + // is this signed? + if (length_i < 0) + exit (_ ("invalid track length")); + assert (!track_info_p_); + track_info_p_ = new Midi_parser_info (*info_l_); + track_info_p_->end_byte_L_ = track_info_p_->byte_L_ + length_i; + forward_byte_L (length_i); + // forward_byte_L (length_i-1); + info_l_ = track_info_p_; +} diff --git a/midi2ly/mudela-item.cc b/midi2ly/mudela-item.cc new file mode 100644 index 0000000000..58a1db586b --- /dev/null +++ b/midi2ly/mudela-item.cc @@ -0,0 +1,363 @@ +// +// mudela-item.cc -- implement Mudela_item +// +// copyright 1997 Jan Nieuwenhuizen + +#include +#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; +} + +Mudela_item::~Mudela_item () +{ +} + +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 () << " "; +} + +Mudela_key::Mudela_key (int accidentals_i, int minor_i) + : Mudela_item (0) +{ + accidentals_i_ = accidentals_i; + minor_i_ = minor_i; +} + +char const *accname[] = {"eses", "es", "", "is" , "isis"}; + +String +Mudela_key::str () +{ + int key_i = accidentals_i_ >= 0 + ? ((accidentals_i_ % 7) ["cgdaebf"] - 'a' - 2 -2 * minor_i_ + 7) % 7 + : ((-accidentals_i_ % 7) ["cfbeadg"] - 'a' - 2 -2 * minor_i_ + 7) % 7; + + String notename_str = !minor_i_ + ? to_str ((char) ((key_i + 2) % 7 + 'A')) + : to_str ((char) ((key_i + 2) % 7 + 'a')); + + // fis cis gis dis ais eis bis + static int sharps_i_a [7] = { 2, 4, 6, 1, 3, 5, 7 }; + // bes es as des ges ces fes + static int flats_i_a [7] = { 6, 4, 2, 7, 5, 3, 1 }; + int accidentals_i = accidentals_i_ >= 0 + ? sharps_i_a [key_i] <= accidentals_i_ ? 1 : 0 + : flats_i_a [key_i] <= -accidentals_i_ ? -1 : 0; + + if (accidentals_i) + notename_str += String (accname [accidentals_i + 2]); + + return "\\key " + notename_str + (minor_i_ ? "\\minor" : "") + ";\n"; +} + +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 [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 *= -1; + notename_i = (notename_i + 1) % 7; + } + + String notename_str = to_str ((char)(((notename_i + 2) % 7) + 'a')); + if (accidental_i) + notename_str += String (accname [accidental_i + 2]); + + /* + By tradition, all scales now consist of a sequence of 7 notes each + with a distinct name, from amongst a b c d e f g. But, minor scales + have a wide second interval at the top - the 'leading note' is + sharped. (Why? it just works that way! Anything else doesn't sound as + good and isn't as flexible at saying things. In medieval times, + scales only had 6 notes to avoid this problem - the hexachords.) + + So, the d minor scale is d e f g a b-flat c-sharp d - using d-flat + for the leading note would skip the name c and duplicate the name d. + Why isn't c-sharp put in the key signature? Tradition. (It's also + supposedly based on the Pythagorean theory of the cycle of fifths, + but that really only applies to major scales...) + + Anyway, g minor is g a b-flat c d e-flat f-sharp g, and all the other + flat minor keys end up with a natural leading note. And there you + have it. + + John Sankey + + Let's also do a-minor: a b c d e f gis a + + --jcn + + */ + + /* ok, bit ugly, but here we go -- jcn */ + + + if (minor_i_) + { + if ((accidentals_i_ == 0) && (notename_str == "as")) + notename_str = "gis"; + else if ((accidentals_i_ == -1) && (notename_str == "des")) + notename_str = "cis"; + else if ((accidentals_i_ == -2) && (notename_str == "ges")) + notename_str = "fis"; + else if ((accidentals_i_ == 5) && (notename_str == "g")) + notename_str = "fisis"; + else if ((accidentals_i_ == 6) && (notename_str == "d")) + notename_str = "cisis"; + else if ((accidentals_i_ == 7) && (notename_str == "a")) + notename_str = "gisis"; + + if ((accidentals_i_ <= -6) && (notename_str == "b")) + notename_str = "ces"; + if ((accidentals_i_ <= -7) && (notename_str == "e")) + notename_str = "fes"; + } + + String de_octavate_str = to_str (',', (Mudela_note::c0_pitch_i_c_ + 11 - pitch_i) / 12); + String octavate_str = to_str ('\'', (pitch_i - Mudela_note::c0_pitch_i_c_) / 12); + return notename_str +de_octavate_str + octavate_str; +} + +Mudela_time_signature::Mudela_time_signature (int num_i, int den_i, int clocks_4_i, int count_32_i) + : Mudela_item (0) +{ + sync_dur_.durlog_i_ = 3; + sync_f_ = 1.0; + if (count_32_i != 8) + warning (_f ("#32 in quarter: %d", count_32_i)); + num_i_ = num_i; + den_i_ = den_i; + clocks_1_i_ = clocks_4_i * 4; +} + +Moment +Mudela_time_signature::bar_mom () +{ + Duration d; + d.durlog_i_ = den_i_; + return Moment (num_i_) * Duration_convert::dur2_mom (d); +} + +int +Mudela_time_signature::clocks_1_i () +{ + return clocks_1_i_; +} + +int +Mudela_time_signature::den_i () +{ + return den_i_; +} + +int +Mudela_time_signature::num_i () +{ + return num_i_; +} + +String +Mudela_time_signature::str () +{ + String str = "\\time " + + to_str (num_i_) + "/" + to_str (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; + */ +/* + UGH: .hh says false, .cc says true. + FIXME. + */ +bool const Mudela_note::simple_plet_b_s; + +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; +} + +Duration +Mudela_note::duration () +{ + assert (end_column_l_); + Moment mom = end_column_l_->at_mom () - at_mom (); + return Duration_convert::mom2_dur (mom); +} + +Moment +Mudela_note::duration_mom () +{ + assert (end_column_l_); + return end_column_l_->at_mom () - at_mom (); +} + +String +Mudela_note::str () +{ + Duration dur = duration (); + if (dur.durlog_i_ < -10) + 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) + " "; + + String str; + + //ugh + if (dur.plet_b ()) + str += String ("\\times ") + + 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 (" }"); + + /* + note of zero duration is nonsense, + but let's output anyway for convenient debugging + */ + if (!duration_mom ()) + return String ("\n% ") + str + "\n"; + + return str + " "; +} + +Mudela_skip::Mudela_skip (Mudela_column* mudela_column_l, Moment skip_mom) + : Mudela_item (mudela_column_l) +{ + mom_ = skip_mom; +} + +Duration +Mudela_skip::duration () +{ + return Duration_convert::mom2_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.durlog_i_<-10) + 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_mom_ = Moment(useconds_per_4_i_ *4, 1e6); +} + +String +Mudela_tempo::str () +{ + String str = "\\tempo 4="; + str += to_str (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) +{ + Moment m1 = Moment (60) / moment; + Moment m2 = seconds_per_1_mom_; + return m1 / m2; +} + +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/midi2ly/mudela-voice.cc b/midi2ly/mudela-voice.cc new file mode 100644 index 0000000000..286d2176c9 --- /dev/null +++ b/midi2ly/mudela-voice.cc @@ -0,0 +1,69 @@ +// +// 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" +#include "mudela-score.hh" + +extern Mudela_score* mudela_score_l_g; + +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_.append (new Cons (mudela_item_l, 0)); +} + + +static int const FAIRLY_LONG_VOICE_i = 6; + +void +Mudela_voice::output (Mudela_stream& mudela_stream_r) +{ + if (!mudela_item_l_list_.size_i ()) + return; + + if (mudela_item_l_list_.size_i () > FAIRLY_LONG_VOICE_i) + mudela_stream_r << '\n'; + + int current_bar_i = 0; + Moment bar_mom = mudela_staff_l_->mudela_time_signature_l_->bar_mom (); + + for (Cons* i = mudela_item_l_list_.head_; i; i = i->next_) + { + Moment at_mom = i->car_->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->car_; + if (Mudela_key* k = dynamic_cast (i->car_)) + mudela_staff_l_->mudela_key_l_ = mudela_score_l_g->mudela_key_l_ = k; + } + + if (mudela_item_l_list_.size_i () > FAIRLY_LONG_VOICE_i) + mudela_stream_r << '\n'; +} + -- 2.39.5