--- /dev/null
+//
+// main.cc -- implement silly main () entry point
+// should have Root class.
+//
+// copyright 1997 Jan Nieuwenhuizen <janneke@gnu.org>
+
+#include <assert.h>
+#include <locale.h>
+#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 <libintl.h>
+#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 <hanwen@cs.uu.nl>") + "\n";
+ LOGOUT(NORMAL_ver) << " " + _ ("Jan Nieuwenhuizen <janneke@gnu.org>") + "\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;
+}
--- /dev/null
+/*
+ midi-track-parser.cc -- implement
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997--1998 Jan Nieuwenhuizen <janneke@gnu.org>
+*/
+
+#include <assert.h>
+#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<Mudela_note>** pp = &open_note_l_list_.head_; *pp;)
+ {
+ Cons<Mudela_note>* 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<Mudela_note>* 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<Mudela_note> (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_;
+}
--- /dev/null
+//
+// mudela-item.cc -- implement Mudela_item
+//
+// copyright 1997 Jan Nieuwenhuizen <janneke@gnu.org>
+
+#include <assert.h>
+#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 <bf250@freenet.carleton.ca>
+
+ 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";
+}
--- /dev/null
+//
+// mudela-voice.cc -- implement Mudela_voice
+//
+// copyright 1997 Jan Nieuwenhuizen <janneke@gnu.org>
+
+#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> (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<Mudela_item>* 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<Mudela_key*> (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';
+}
+