+++ /dev/null
-//
-// lily-stream.hh -- part of LilyPond
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-// should i be named Mudela_stream?
-
-#ifndef LILY_STREAM_HH
-#define LILY_STREAM_HH
-
-/// Lily output
-struct Lily_stream {
- ostream* os_p_;
- String filename_str_;
- int indent_i_;
- int column_i_;
- int wrap_column_i_;
- bool comment_mode_bo_;
-
- Lily_stream( String filename_str );
- ~Lily_stream();
-
- Lily_stream& operator <<( String str );
- Lily_stream& operator <<( Midi_event& midi_event_r );
-
- void check_comment( String str );
- void header();
- void indent();
- void newline();
- void open();
- void tnedni();
-};
-
-#endif // LILY_STREAM_HH
-
+++ /dev/null
-//
-// m2m.hh -- generic m2m include file
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef M2M_HH
-#define M2M_HH
-
-// yes, i know this hurts the dependency calc, however,
-// having includes in headers sucks, and long trial and error
-// include lists also suck.
-// if you want less dependecies, break lib/exe down in smaller
-// modules.
-
-#include <assert.h>
-#include <iostream.h>
-#include <fstream.h>
-#include <limits.h>
-#include <ctype.h>
-#include <time.h>
-
-#include "proto.hh"
-#include "plist.hh"
-#include "debug.hh"
-#ifdef mtor
-#undef mtor
-#endif
-
-#include "string.hh"
-#include "string-convert.hh"
-
-#include "lgetopt.hh"
-
-#include "moment.hh"
-#include "duration.hh"
-#include "input-file.hh"
-#include "source-file.hh"
-#include "source.hh"
-
-// mustn-t do, these get touched!
-// #include "fversion.hh"
-// #include "version.hh"
-
-#include "midi-global.hh"
-
-#include "lily-stream.hh"
-#include "midi-event.hh"
-#include "midi-main.hh"
-#include "midi-score.hh"
-#include "midi-track.hh"
-#include "midi-voice.hh"
-#include "my-midi-lexer.hh"
-#include "my-midi-parser.hh"
-#include "track-column.hh"
-
-#endif // M2M_HH
-
+++ /dev/null
-//
-// midi-event.hh -- declare midi_event
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef MIDI_EVENT_HH
-#define MIDI_EVENT_HH
-
-
-// should these:
-// * be Midi_items
-// * be Voice_elements/requests
-// * get a name-change
-// ?
-
-/// (midi_event)
-class Midi_event {
-public:
- Midi_event();
-
- virtual String mudela_str( bool command_mode_bo ) = 0;
- void output_mudela( Lily_stream& lily_stream_r, bool command_mode_bo );
- virtual Moment mom();
-};
-
-class Midi_key : public Midi_event {
-public:
- Midi_key( int accidentals_i, int minor_i );
-
- String notename_str( int pitch_i );
- virtual String mudela_str( bool command_mode_bo );
-
-private:
- int accidentals_i_;
- int minor_i_;
- int key_i_;
-};
-
-class Midi_note : public Midi_event {
-public:
- int const c0_pitch_i_c_ = 60;
-
- Midi_note( String name_str, Duration dur );
- virtual Moment mom();
- virtual String mudela_str( bool command_mode_bo );
-
-private:
- bool const simple_plet_bo_ = false;
- Duration dur_;
- String name_str_;
-};
-
-class Midi_tempo : public Midi_event {
-public:
- Midi_tempo( int useconds_per_4_i );
-
- int get_tempo_i( Moment moment );
- virtual String mudela_str( bool command_mode_bo );
-
-private:
- int useconds_per_4_i_;
- Real seconds_per_1_f_;
-};
-
-class Midi_text : public Midi_event {
-public:
- enum Type {
- TEXT = 1, COPYRIGHT, TRACK_NAME, INSTRUMENT_NAME, LYRIC,
- MARKER, CUE_POINT
- };
- Midi_text( Midi_text::Type type, String str );
- virtual String mudela_str( bool command_mode_bo );
-private:
- Type type_;
- String text_str_;
-};
-
-class Midi_time : public Midi_event {
-public:
- Midi_time( 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();
- virtual String mudela_str( bool command_mode_bo );
-
-private:
- Real sync_f_;
- Duration sync_dur_;
- int clocks_1_i_;
- int num_i_;
- int den_i_;
-};
-
-#endif // MIDI_EVENT_HH
-
+++ /dev/null
-//
-// midi-global.hh -- declare global (sic) stuff for m2m
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef MIDI_GLOBAL_HH
-#define MIDI_GLOBAL_HH
-
-#include "string.hh"
-
-#define monitor_p_g &cout
-enum Verbose { QUIET_ver, BRIEF_ver, NORMAL_ver, VERBOSE_ver, DEBUG_ver };
-extern Verbose level_ver;
-#ifdef NPRINT
-#define dtor if ( 0 ) *monitor_p_g
-#define mtor if ( 0 ) *monitor_p_g
-#else
-#define dtor if ( level_ver >= DEBUG_ver ) *monitor_p_g
-#define vtor if ( level_ver >= VERBOSE_ver ) *monitor_p_g
-#define mtor if ( level_ver >= NORMAL_ver ) *monitor_p_g
-#define btor if ( level_ver >= BRIEF_ver ) *monitor_p_g
-#define qtor if ( level_ver >= QUIET_ver ) *monitor_p_g
-#endif
-
-extern Source* source_l_g;
-extern bool no_triplets_bo_g;
-void message( String message_str, char const* context_ch_c_l );
-void warning( String message_str, char const* context_ch_c_l );
-void error( String message_str, char const* context_ch_c_l );
-
-String version_str();
-
-#endif // MIDI_GLOBAL_HH
-
+++ /dev/null
-//
-// midi-score.hh -- declare midi_score
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef MIDI_SCORE_HH
-#define MIDI_SCORE_HH
-
-/// (midi_score)
-class Midi_score {
-public:
- Midi_score( int format_i, int tracks_i, int tempo_i );
- ~Midi_score();
-
- void add_track( Midi_track* midi_track_p );
-
- int output_mudela( String filename_str );
- void process();
-
-private:
- IPointerList<Midi_track*> midi_track_p_list_;
- int format_i_;
- int tracks_i_;
- int tempo_i_;
-};
-
-#endif // MIDI_SCORE_HH
-
+++ /dev/null
-//
-// midi-track.hh -- declare midi_track
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef MIDI_TRACK_HH
-#define MIDI_TRACK_HH
-
-/// (midi_track)
-class Midi_track {
-public:
- Midi_track( int number_i, String copyright_str, String track_name_str, String instrument_str );
-
- void add_event( Moment mom, Midi_event* midi_event_p );
- Moment end_mom();
- String name_str();
- void output_mudela( Lily_stream& lily_stream_r );
- Moment next_begin_mom( Moment now_mom );
- Moment next_end_mom( Moment now_mom );
- void process();
- Track_column* tcol_l( Moment mom );
-
- String copyright_str_;
- String instrument_str_;
- String name_str_;
-
-private:
- void add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom );
- Midi_voice* get_free_midi_voice_l( Moment mom );
- void remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom );
- IPointerList<Track_column*> tcol_p_list_;
- IPointerList<Midi_voice*> midi_voice_p_list_;
- int number_i_;
-
-};
-
-#endif // MIDI_TRACK_HH
-
+++ /dev/null
-//
-// midi-voice.hh -- declare midi_voice
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-/// (midi_voice)
-#ifndef MIDI_VOICE_HH
-#define MIDI_VOICE_HH
-
-class Midi_voice {
-public:
- Midi_voice( Moment begin_mom );
-
- void add_event( Midi_event* midi_event_p );
- Moment begin_mom();
- Moment end_mom();
-
- String mudela_str( Moment from_mom, Moment to_mom, bool multiple_bo );
-
-private:
- Moment begin_mom_;
- IPointerList<Midi_event*> midi_event_p_list_;
-};
-
-#endif // MIDI_VOICE_HH
-
+++ /dev/null
-//
-// my-midi-lexer.hh -- declare My_midi_lexer
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef MY_MIDI_LEXER_HH
-#define MY_MIDI_LEXER_HH
-
-#include <FlexLexer.h>
-#include "proto.hh"
-// #include "fproto.hh"
-#include "varray.hh"
-#include "string.hh"
-
-int yylex();
-void yyerror(const char *s);
-// bool busy_parsing();
-// void kill_lexer();
-// void set_lexer();
-
-/// (midi_lexer)
-class My_midi_lexer : yyFlexLexer {
-public:
- My_midi_lexer( String filename_str );
- ~My_midi_lexer();
-
- int close_i();
- void error( char const* sz_l );
- char const* here_ch_c_l();
- static int varint2_i( String str );
- int yylex();
-
-private:
- Input_file* input_file_p_;
-
-public: // ugh
- int errorlevel_i_;
-};
-
-extern My_midi_lexer* midi_lexer_l_g;
-
-#endif // MY_MIDI_LEXER_HH
-
+++ /dev/null
-//
-// my-midi-parser.hh -- declare My_midi_parser
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef MY_MIDI_PARSER_HH
-#define MY_MIDI_PARSER_HH
-
-// #include "proto.hh"
-// #include "string.hh"
-
-int yyparse();
-
-/// (midi_parser)
-class My_midi_parser {
-public:
- My_midi_parser( String filename_str );
- ~My_midi_parser();
-
- void add_score( Midi_score* midi_score_p );
- void error( char const* sz_l );
- int parse();
- void forward( int i );
- Moment mom();
- void note_begin( int channel_i, int pitch_i, int dyn_i );
- Midi_event* note_end_midi_event_p( int channel_i, int pitch_i, int dyn_i );
- int output_mudela( String filename_str );
- void reset();
- void set_division_4( int division_4_i );
- void set_key( int accidentals_i, int minor_i );
- void set_tempo( int useconds_i );
- void set_time( int num_i, int den_i, int clocks_i, int count_32_i );
-
- int track_i_;
- String filename_str_;
- String copyright_str_;
- String instrument_str_;
- String track_name_str_;
-
- Midi_key* midi_key_p_;
- Midi_tempo* midi_tempo_p_;
- Midi_time* midi_time_p_;
-
-private:
- Int64 now_i64_; // 31 bits yields tipically about 1000 bars
-
- static int const CHANNELS_i = 16;
- static int const PITCHES_i = 128;
- Int64 running_i64_i64_a_[ CHANNELS_i ][ PITCHES_i ];
-
- Midi_score* midi_score_p_;
- int division_1_i_;
-
- char const* defined_ch_c_l_;
- int fatal_error_i_;
- My_midi_lexer* midi_lexer_p_;
-};
-
-extern My_midi_parser* midi_parser_l_g;
-
-#endif // MY_MIDI_PARSER_HH
-
+++ /dev/null
-//
-// track-column.hh -- declare Track_column
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#ifndef TRACK_COLUMN_HH
-#define TRACK_COLUMN_HH
-
-/// (tcol)
-class Track_column {
-public:
- Track_column( Moment mom );
-
- void add_event( Midi_event* midi_event_p );
- Moment mom();
-
-//private:
- IPointerList<Midi_event*> midi_event_p_list_;
- Moment mom_;
-};
-
-#endif // TRACK_COLUMN_HH
-
+++ /dev/null
-//
-// lily-stream.cc
-//
-// source file of the LilyPond music typesetter
-//
-// (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-// should i be named Mudela_stream?
-
-#include "m2m.hh"
-
-Lily_stream::Lily_stream( String filename_str )
-{
- filename_str_ = filename_str;
- os_p_ = 0;
- indent_i_ = 0;
- comment_mode_bo_ = false;
- column_i_ = 0;
- wrap_column_i_ = 78;
- open();
- header();
-}
-
-Lily_stream::~Lily_stream()
-{
- delete os_p_;
- if ( indent_i_ )
- warning( "lily indent level: " + String( indent_i_ ), 0 );
-}
-
-Lily_stream&
-Lily_stream::operator <<( String str )
-{
- while ( str.length_i() ) {
- int max_i = wrap_column_i_ - column_i_;
- String line = str.left_str( max_i );
-
- while ( max_i && ( max_i < line.length_i() )
- && ( isalnum( line[ max_i ] )
- || ( line[ max_i ] == '\\' ) ) )
- max_i--;
- if ( max_i )
- line = str.left_str( max_i + 1 );
- else // cannot break neatly...
- max_i = wrap_column_i_ - column_i_ - 1;
-
- str = str.mid_str( max_i + 1, INT_MAX );
- *os_p_ << line;
- check_comment( line );
- column_i_ += line.length_i();
- if ( column_i_ >= wrap_column_i_ ) {
- //brr.
- if ( comment_mode_bo_ )
- str = "%" + str;
- newline();
- }
- }
- return *this;
-}
-
-Lily_stream&
-Lily_stream::operator <<( Midi_event& midi_event_r )
-{
- midi_event_r.output_mudela( *this, false );
- return *this;
-}
-
-void
-Lily_stream::check_comment( String str )
-{
- int newline_i = str.index_last_i( '\n' );
- if ( newline_i != -1 ) {
- str = str.mid_str( newline_i +1, INT_MAX );
- comment_mode_bo_ = false;
- }
- if ( str.index_i( '%' ) != -1 )
- comment_mode_bo_ = true;
-}
-
-void
-Lily_stream::header()
-{
- *os_p_ << "% Creator: " << 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";
-}
-
-void
-Lily_stream::indent()
-{
- indent_i_++;
- newline();
-}
-
-void
-Lily_stream::newline()
-{
- *os_p_ << "\n" << String( '\t', indent_i_ );
- column_i_ = indent_i_ * 8;
- comment_mode_bo_ = false;
-}
-
-void
-Lily_stream::open()
-{
- os_p_ = new ofstream( filename_str_ );
- if ( !*os_p_ )
- error ( "can't open `" + filename_str_ + "\'", 0 );
-}
-
-void
-Lily_stream::tnedni()
-{
- assert( indent_i_ > 0 );
- indent_i_--;
- newline();
-}
-
+++ /dev/null
-//
-// midi-event.cc -- implement Midi_event
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-Midi_event::Midi_event()
-{
-}
-
-Moment
-Midi_event::mom()
-{
- return Moment( 0 );
-}
-
-void
-Midi_event::output_mudela( Lily_stream& lily_stream_r, bool command_mode_bo )
-{
- lily_stream_r << mudela_str( command_mode_bo ) << String( " " );
-}
-
-Midi_key::Midi_key( int accidentals_i, int minor_i )
-{
- accidentals_i_ = accidentals_i;
- minor_i_ = minor_i;
- if ( !minor_i_ )
- key_i_ = ( ( accidentals_i % 7 )[ "cgdaebf" ] - 'a' + 2 ) % 7;
- else
- key_i_ = ( ( -accidentals_i % 7 )[ "fbeadg" ] - 'a' + 2 ) % 7;
-}
-
-String
-Midi_key::mudela_str( bool command_mode_bo )
-{
- String str = "key\\";
- if ( !minor_i_ )
- str += String( (char)( key_i_ - 2 + 'A' ) );
- else
- str += String( (char)( key_i_ - 2 + 'a' ) );
- if ( !command_mode_bo )
- str = String( '\\' ) + str;
- return str;
-}
-
-String
-Midi_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 ( accidentals_i_ < 0 ) {
- accidental_i = - accidental_i;
- notename_i = ( notename_i + 1 ) % 7;
- }
-
- String notename_str = (char)( ( ( notename_i + key_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 octave_str;
-
- octave_str += String( '\'', ( pitch_i - Midi_note::c0_pitch_i_c_ ) / 12 );
- octave_str += String( '`', ( Midi_note::c0_pitch_i_c_ - pitch_i ) / 12 );
- return octave_str + notename_str;
-}
-
-Midi_note::Midi_note( String name_str, Duration dur )
-{
- // do i want pitch too?
- dur_ = dur;
- name_str_ = name_str;
-}
-
-String
-Midi_note::mudela_str( bool command_mode_bo )
-{
-// assert( !command_mode_bo );
-// undefined ref to simple_plet_bo_ ??
-// if ( simple_plet_bo_ )
-// return name_str_ + Duration_convert::dur2_str( dur_ );
-
- //ugh
- String str;
- if ( dur_.plet_p_ )
- str += String( "\\plet{ " )
- + String_convert::i2dec_str( dur_.plet_p_->iso_i_, 0, 0 )
- + "/"
- + String_convert::i2dec_str( dur_.plet_p_->type_i_, 0, 0 )
- + " } ";
-
- str += name_str_;
-
- Duration dur = dur_;
- dur.set_plet( 0 );
- str += Duration_convert::dur2_str( dur );
-
- if ( dur_.plet_p_ )
- str += String( " \\plet{ 1/1 }" );
-
- return str;
-}
-
-Moment
-Midi_note::mom()
-{
- return Duration_convert::dur2_mom( dur_ );
-}
-
-Midi_tempo::Midi_tempo( int useconds_per_4_i )
-{
- useconds_per_4_i_ = useconds_per_4_i;
- seconds_per_1_f_ = (Real)useconds_per_4_i_ * 4 / 1e6;
-}
-
-String
-Midi_tempo::mudela_str( bool command_mode_bo )
-{
-// assert( command_mode_bo );
- if ( !command_mode_bo )
- return "";
- String str = "tempo 4:";
- str += String( get_tempo_i( Moment( 1, 4 ) ) );
- return str;
-}
-
-int
-Midi_tempo::get_tempo_i( Moment moment )
-{
- return Moment( 60 ) / moment / Moment( seconds_per_1_f_ );
-}
-
-Midi_text::Midi_text( Midi_text::Type type, String text_str )
-{
- type_ = type;
- text_str_ = text_str;
-}
-
-String
-Midi_text::mudela_str( bool command_mode_bo )
-{
- (void)command_mode_bo;
- if ( !text_str_.length_i()
- || ( text_str_.length_i() != (int)strlen( text_str_.ch_c_l() ) ) )
- return "";
-
- return "% " + text_str_ + "\n\t";
-}
-
-Midi_time::Midi_time( int num_i, int den_i, int clocks_4_i, int count_32_i )
- : sync_dur_( 8 )
-{
- sync_f_ = 1.0;
- if ( count_32_i != 8 )
- warning( String( "#32 in quarter: " ) + String( count_32_i ), 0 );
- num_i_ = num_i;
- den_i_ = 2 << den_i;
- clocks_1_i_ = clocks_4_i * 4;
-}
-
-int
-Midi_time::clocks_1_i()
-{
- return clocks_1_i_;
-}
-
-Duration
-Midi_time::i2_dur( int time_i, int division_1_i )
-{
- Moment mom = Duration_convert::i2_mom( time_i, division_1_i );
- mom /= sync_f_;
-
- dtor << "\n% (" << time_i << ", " << mom << "): "
- << sync_f_ << endl;
-
- Duration dur = Duration_convert::mom2_dur( mom );
- if ( !dur.type_i_ ) {
- vtor << "\n% resyncing(" << time_i << ", " << mom << "): "
- << sync_f_ << " -> ";
- mom *= sync_f_;
- sync_f_ = Duration_convert::sync_f( sync_dur_, mom );
- vtor << sync_f_ << endl;
- mom /= sync_f_;
- dur = Duration_convert::mom2_dur( mom );
- }
-
- return dur;
-}
-
-String
-Midi_time::mudela_str( bool command_mode_bo )
-{
- String str = "meter { "
- + String( num_i_ ) + "*" + String( den_i_ )
- + " }";
- if ( !command_mode_bo )
- str = String( '\\' ) + str;
- return str;
-}
-
+++ /dev/null
-//
-// midi-main.cc -- implement silly main() entry point
-// should have Root class.
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-#include "fversion.hh"
-#include "version.hh"
-
-Source source;
-Source* source_l_g = &source;
-
-Verbose level_ver = NORMAL_ver;
-
-// ugh
-bool no_triplets_bo_g = false;
-
-//ugh
-char const* defined_ch_c_l = 0;
-
-// ugh, another global
-String
-find_file( String str )
-{
- return str;
-}
-
-// ugh, copied from warn.cc, cannot use
-void
-message( String message_str, char const* context_ch_c_l )
-{
- String str = "m2m: ";
- Source_file* sourcefile_l = source_l_g->sourcefile_l( context_ch_c_l );
- if ( sourcefile_l ) {
- str += sourcefile_l->file_line_no_str(context_ch_c_l) + String(": ");
- }
- str += message_str;
- if ( sourcefile_l ) {
- str += ":\n";
- str += sourcefile_l->error_str( context_ch_c_l );
- }
-// if ( busy_parsing() )
-// cerr << endl;
- cerr << str << endl;
-}
-
-void
-warning( String message_str, char const* context_ch_c_l )
-{
- message( "warning: " + message_str, context_ch_c_l );
-}
-
-void
-error( String message_str, char const* context_ch_c_l )
-{
- message( message_str, context_ch_c_l );
- // since when exits error again?
- // i-d say: error: errorlevel |= 1; -> no output upon error
- // warning: recovery -> output (possibly wrong)
- if ( midi_lexer_l_g )
- midi_lexer_l_g->errorlevel_i_ |= 1;
-}
-
-void
-help()
-{
- btor <<
- "--debug, -d be really verbose\n"
- "--help, -h this help\n"
- "--include=DIR, -I DIR add DIR to search path\n"
- "--no-triplets, -n assume no triplets\n"
- "--output=FILE, -o FILE set FILE as default output\n"
- "--quiet, -q be quiet\n"
- "--verbose, -v be verbose\n"
- "--warranty, -w show warranty & copyright\n"
- ;
-}
-
-void
-identify()
-{
- mtor << version_str() << endl;
-}
-
-void
-notice()
-{
- mtor <<
- "\n"
- "M2m, translate midi to mudela.\n"
- "Copyright (C) 1997 by\n"
- " Han-Wen Nienhuys <hanwen@stack.nl>\n"
-// "Contributors\n"
- " Jan Nieuwenhuizen <jan@digicash.com>\n"
-// " Mats Bengtsson <matsb@s3.kth.se>\n"
- "\n"
- " 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";
-}
-
-// should simply have Root class...
-String
-version_str()
-{
- return String ( "This is m2m " ) + VERSIONSTR
- + "/FlowerLib " + FVERSIONSTR
- + " of " + __DATE__ + " " + __TIME__;
-}
-
-int
-main( int argc_i, char* argv_sz_a[] )
-{
- Long_option_init long_option_init_a[] = {
- 0, "debug", 'd',
- 0, "help", 'h',
-// 1, "include", 'I',
- 0, "no-triplets", 'n',
- 1, "output", 'o',
- 0, "quiet", 'q',
- 0, "verbose", 'v',
- 0, "warranty", 'w',
- 0,0,0
- };
- Getopt_long getopt_long( argc_i, argv_sz_a, long_option_init_a );
- identify();
-
- String output_str;
- while ( Long_option_init* long_option_init_p = getopt_long() )
- switch ( long_option_init_p->shortname ) {
- case 'd':
- level_ver = DEBUG_ver;
- break;
- case 'h':
- help();
- exit( 0 );
- break;
-// case 'I':
-// path->push( getopt_long.optarg );
-// break;
- case 'n':
- no_triplets_bo_g = true;
- break;
- case 'o':
- output_str = getopt_long.optarg;
- break;
- case 'q':
- level_ver = QUIET_ver;
- break;
- case 'v':
- level_ver = VERBOSE_ver;
- break;
- case 'w':
- notice();
- exit( 0 );
- break;
- default:
- assert( 0 );
- break;
- }
-
- char* arg_sz = 0;
- while ( ( arg_sz = getopt_long.get_next_arg() ) ) {
- My_midi_parser midi_parser( arg_sz );
- int error_i = midi_parser.parse();
- if ( error_i )
- return error_i;
- if ( !output_str.length_i() ) {
- output_str = String( arg_sz ) + ".ly";
- // i-m sure there-s already some routine for this
- int name_i; // too bad we can-t declare local to if
- if ( ( name_i = output_str.index_last_i( '/' ) ) != -1 )
- output_str = output_str.mid_str( name_i + 1, INT_MAX );
- }
- error_i = midi_parser.output_mudela( output_str );
- if ( error_i )
- return error_i;
- }
- return 0;
-}
+++ /dev/null
-//
-// midi-score.cc -- implement Midi_score
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-Midi_score::Midi_score( int format_i, int tracks_i, int tempo_i )
-{
- format_i_ = format_i;
- tracks_i_ = tracks_i;
- tempo_i_ = tempo_i;
-}
-
-Midi_score::~Midi_score()
-{
-}
-
-void
-Midi_score::add_track( Midi_track* midi_track_p )
-{
- midi_track_p_list_.bottom().add( midi_track_p );
-}
-
-int
-Midi_score::output_mudela( String filename_str )
-{
- mtor << "Lily output to " << filename_str << " ..." << endl;
-
- Lily_stream lily_stream( filename_str );
- for ( PCursor<Midi_track*> midi_track_l_pcur( midi_track_p_list_.top() ); midi_track_l_pcur.ok(); midi_track_l_pcur++ ) {
- midi_track_l_pcur->output_mudela( lily_stream );
- lily_stream.newline();
- }
-
- lily_stream << "score {";
- lily_stream.newline();
-
- for ( PCursor<Midi_track*> midi_track_l_pcur( midi_track_p_list_.top() ); midi_track_l_pcur.ok(); midi_track_l_pcur++ ) {
- lily_stream << "\tstaff { melodic music { ";
- lily_stream << midi_track_l_pcur->name_str();
- lily_stream << " } }";
- lily_stream.newline();
- }
-
- lily_stream.indent();
- lily_stream << "commands {";
- lily_stream.indent();
- midi_parser_l_g->midi_time_p_->output_mudela( lily_stream, true );
- lily_stream.tnedni();
- lily_stream << "}";
- lily_stream.newline();
- lily_stream << "midi {";
- lily_stream.indent();
- midi_parser_l_g->midi_tempo_p_->output_mudela( lily_stream, true );
- lily_stream.tnedni();
- lily_stream << "}";
- lily_stream.tnedni();
-
- lily_stream << "}";
- lily_stream.newline();
-
- return 0;
-}
-
-void
-Midi_score::process()
-{
- for ( PCursor<Midi_track*> i( midi_track_p_list_.top() ); i.ok(); i++ )
- i->process();
-}
-
+++ /dev/null
-//
-// midi-template.cc -- implementemplate
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "proto.hh"
-#include "list.hh"
-#include "list.tcc"
-#include "cursor.tcc"
-
-L_instantiate(void *);
-
-class istream;
-class ostream;
-
-#include "m2m.hh"
-#include "plist.hh"
-#include "plist.tcc"
-
-IPL_instantiate(Midi_event);
-IPL_instantiate(Midi_track);
-PL_instantiate(Midi_voice);
-IPL_instantiate(Midi_voice);
-IPL_instantiate(Source_file);
-IPL_instantiate(Track_column);
-
+++ /dev/null
-//
-// midi-track.cc -- implement Midi_track
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-Midi_track::Midi_track( 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;
- if ( track_name_str.length_i() )
- name_str_ = track_name_str;
- else
- name_str_ = String( "track" ) + String( number_i_ );
- tcol_p_list_.bottom().add( new Track_column( Moment( 0 ) ) );
-}
-
-void
-Midi_track::add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
-{
- for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
- if ( i->begin_mom() == mom )
- open_voices_r.bottom().add( *i );
-}
-
-void
-Midi_track::add_event( Moment mom, Midi_event* midi_event_p )
-{
- if ( ! midi_event_p )
- return;
- tcol_l( mom - midi_event_p->mom() )->add_event( midi_event_p );
-}
-
-// too much red tape?
-String
-Midi_track::name_str()
-{
- return name_str_;
-}
-
-Moment
-Midi_track::end_mom()
-{
- // heu..
- Moment mom = 0.0;
- for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
- mom = i->end_mom() >? mom;
- return mom;
-}
-
-Midi_voice*
-Midi_track::get_free_midi_voice_l( Moment mom )
-{
- for ( PCursor<Midi_voice*> midi_voice_l_pcur( midi_voice_p_list_.top() ); midi_voice_l_pcur.ok(); midi_voice_l_pcur++ )
- if ( midi_voice_l_pcur->end_mom() == mom )
- return *midi_voice_l_pcur;
-
- Midi_voice* midi_voice_p = new Midi_voice( mom );
- Midi_voice* midi_voice_l = midi_voice_p;
- midi_voice_p_list_.bottom().add( midi_voice_p );
- return midi_voice_l;
-}
-
-Moment
-Midi_track::next_begin_mom( Moment now_mom )
-{
-// Moment begin_mom = Midi_track::end_mom() + 1;
- Moment begin_mom = Midi_track::end_mom();
- for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
-// if ( i->begin_mom() >= now_mom )
- if ( i->begin_mom() > now_mom )
- begin_mom = begin_mom <? i->begin_mom();
- return begin_mom;
-}
-
-Moment
-Midi_track::next_end_mom( Moment now_mom )
-{
- Moment end_mom = Midi_track::end_mom();
- for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
- if ( i->end_mom() > now_mom )
- end_mom = end_mom <? i->end_mom();
- return end_mom;
-}
-
-void
-Midi_track::process()
-{
- for ( PCursor<Track_column*> tcol_l_pcur( tcol_p_list_.top() ); tcol_l_pcur.ok(); tcol_l_pcur++ )
- while ( tcol_l_pcur->midi_event_p_list_.size() )
- // shit, where has the T* PCursor::remove() gone??
- // i don-t want to get and delete,
- // i want to (re)move!
- // is it renamed: get vs add/insert ?? (put/remove :-)
- get_free_midi_voice_l( tcol_l_pcur->mom() )->add_event( tcol_l_pcur->midi_event_p_list_.top().remove_p() );
-
- dtor << "ends: " << endl;
- int n = 0;
- for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
- vtor << "voice " << n++ << ": " << i->end_mom() << endl;
- dtor << ":sdne" << endl;
-}
-
-
-void
-Midi_track::output_mudela( Lily_stream& lily_stream_r )
-{
- lily_stream_r << name_str_ << " = music { $";
- lily_stream_r.indent();
- lily_stream_r << "% midi copyright:" << copyright_str_;
- lily_stream_r.newline();
- lily_stream_r << "% instrument:" << instrument_str_;
- lily_stream_r.newline();
-
- PointerList<Midi_voice*> open_voices;
- Moment now_mom = 0.0;
- Moment then_mom = 0.0;
- while ( now_mom < end_mom() ) {
- add_begin_at( open_voices, now_mom );
-
- Moment begin_mom = next_begin_mom( now_mom );
- Moment end_mom = next_end_mom( now_mom );
- if ( ( begin_mom > now_mom ) && ( begin_mom < end_mom ) )
- then_mom = begin_mom;
- else
- then_mom = end_mom;
-
- dtor << "begin: " << begin_mom << " end: " << end_mom << endl;
- dtor << "slice: " << now_mom << ", " << then_mom << endl;
-
- if ( open_voices.size() > 1 )
- lily_stream_r << "{ ";
- for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
- lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
- if ( open_voices.size() > 1 )
- lily_stream_r << "} ";
- now_mom = then_mom;
-
- remove_end_at( open_voices, now_mom );
- }
- lily_stream_r.tnedni();
- lily_stream_r << "$} % " << name_str_;
- lily_stream_r.newline();
-}
-
-void
-Midi_track::remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
-{
- for ( PCursor<Midi_voice*> i( open_voices_r.top() ); i.ok(); i++ )
- if ( i->end_mom() == mom ) {
- i.remove_p(); // remove? // no delete; only a copy
- if ( !i.ok() )
- break;
- }
-// i.del(); // remove? // no delete; only a copy
-// plist is breendet
-// duh, del and get will do a ++, but will fail if they render list empty
-// if ( i->end_mom() == mom ) {
-// if ( i->size() > 1 )
-// i.del();
-// else
-// i.junk(); // what-s in a name? (sic)
-// }
-}
-
-Track_column*
-Midi_track::tcol_l( Moment mom )
-{
- for ( PCursor<Track_column*> tcol_l_pcur( tcol_p_list_.top() ); tcol_l_pcur.ok(); tcol_l_pcur++ ) {
- if ( tcol_l_pcur->mom() == mom )
- return *tcol_l_pcur;
- if ( tcol_l_pcur->mom() > mom ) {
- Track_column* tcol_p = new Track_column( mom );
- tcol_l_pcur.insert( tcol_p );
- return tcol_p;
- }
- }
-
- Track_column* tcol_p = new Track_column( mom );
- tcol_p_list_.bottom().add( tcol_p );
- return tcol_p;
-}
-
+++ /dev/null
-//
-// midi-voice.cc -- implement midi_voice
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-Midi_voice::Midi_voice( Moment begin_mom )
-{
- begin_mom_ = begin_mom;
-}
-
-void
-Midi_voice::add_event( Midi_event* midi_event_p )
-{
- midi_event_p_list_.bottom().add( midi_event_p );
-}
-
-Moment
-Midi_voice::begin_mom()
-{
- return begin_mom_;
-}
-
-Moment
-Midi_voice::end_mom()
-{
- Moment now_mom = begin_mom_;
- dtor << now_mom << ", ";
- for ( PCursor<Midi_event*> i( midi_event_p_list_.top() ); i.ok(); i++ ) {
- dtor << now_mom << ", ";
- now_mom += i->mom();
- }
- dtor << endl;
- return now_mom;
-}
-
-String
-Midi_voice::mudela_str( Moment from_mom, Moment to_mom, bool multiple_bo )
-{
- String str;
-
- if ( begin_mom() >= to_mom )
- return "";
- if ( end_mom() <= from_mom )
- return "";
-
- Moment now_mom = begin_mom();
- PCursor<Midi_event*> i( midi_event_p_list_.top() );
- for ( ; i.ok() && now_mom < from_mom ; i++ )
- now_mom += i->mom();
-
- for ( ; i.ok() && now_mom < to_mom ; i++ ) {
- now_mom += i->mom();
- str += i->mudela_str( false ) + " ";
- }
-
- if ( str.length_i() && multiple_bo )
- str = "\\music{ " + str + "} ";
- return str;
-}
-
+++ /dev/null
-//
-// my-midi-lexer.cc -- implement My_midi_lexer
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-int
-yylex()
-{
- return midi_lexer_l_g->yylex();
-}
-
-My_midi_lexer* midi_lexer_l_g = 0;
-
-My_midi_lexer::My_midi_lexer( String filename_str )
-{
- midi_lexer_l_g = this;
- input_file_p_ = new Input_file( filename_str );
- switch_streams( input_file_p_->is );
- errorlevel_i_ = 0;
-}
-
-My_midi_lexer::~My_midi_lexer()
-{
- delete input_file_p_;
- midi_lexer_l_g = 0;
-}
-
-void
-My_midi_lexer::error( char const* sz_l )
-{
- if ( !input_file_p_ ) {
-// *mlog << "error at EOF" << sz_l << '\n';
- cerr << "error at EOF" << sz_l << '\n';
- } else {
- char const* ch_c_l = here_ch_c_l();
- if ( ch_c_l ) {
- ch_c_l--;
- while ( ( *ch_c_l == ' ' ) || ( *ch_c_l == '\t' ) || ( *ch_c_l == '\n' ) )
- ch_c_l--;
- ch_c_l++;
- }
- errorlevel_i_ |= 1;
-// ::error( sz_l, ch_c_l );
- ::error( sz_l, ch_c_l );
- }
-}
-
-char const*
-My_midi_lexer::here_ch_c_l()
-{
- return input_file_p_->sourcefile_l_->ch_c_l() + yyin->tellg();
-}
-
-int
-My_midi_lexer::varint2_i( String str )
-{
- int var_i = 0;
-
- for ( int i = 0; i < str.length_i(); i++ ) {
- Byte byte = str[ i ];
- var_i <<= 7;
- var_i += byte & 0x7f;
- if ( ! ( byte & 0x80 ) )
- return var_i;
- }
- cout << "\nvarint2_i:" << String_convert::bin2hex_str( str ) << endl;
- assert( 0 ); // illegal varint
- return 0;
-}
-
-int
-My_midi_lexer::close_i()
-{
- return 0;
-}
-
+++ /dev/null
-//
-// my-midi-parser.cc -- implement My_midi_parser
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-void
-yyerror(char const* sz_l )
-{
- midi_parser_l_g->error( sz_l );
-}
-
-
-My_midi_parser* midi_parser_l_g = 0;
-
-My_midi_parser::My_midi_parser( String filename_str )
-{
- midi_parser_l_g = this;
- filename_str_ = filename_str;
- midi_lexer_p_ = new My_midi_lexer( filename_str_ );
- defined_ch_c_l_ = 0;
- fatal_error_i_ = 0;
- midi_key_p_ = 0;
- midi_score_p_ = 0;
- midi_tempo_p_ = 0;
- midi_time_p_ = 0;
- track_i_ = 0;
- reset();
-}
-
-My_midi_parser::~My_midi_parser()
-{
- delete midi_lexer_p_;
- midi_parser_l_g = 0;
- delete midi_key_p_;
- delete midi_tempo_p_;
- delete midi_time_p_;
- delete midi_score_p_;
-}
-
-void
-My_midi_parser::reset()
-{
- delete midi_key_p_;
- midi_key_p_ = new Midi_key( 0, 0 );
- // useconds per 4: 250000 === 60 4 per minute
- delete midi_tempo_p_;
- midi_tempo_p_ = new Midi_tempo( 250000 );
- delete midi_time_p_;
- midi_time_p_ = new Midi_time( 4, 4, 384, 8 );
- now_i64_ = 0;
-
- copyright_str_ = "";
- track_name_str_ = "";
- instrument_str_ = "";
-
- for ( int i = 0; i < CHANNELS_i; i++ )
- for ( int j = 0; j < PITCHES_i; j++ )
-// running_i64_i64_a_[ i ][ j ] = -1;
- running_i64_i64_a_[ i ][ j ] = 0;
-}
-
-void
-My_midi_parser::add_score( Midi_score* midi_score_p )
-{
- assert( !midi_score_p_ );
- midi_score_p_ = midi_score_p;
- track_i_ = 0;
-}
-
-void
-My_midi_parser::error( char const* sz_l )
-{
- midi_lexer_l_g->error( sz_l );
-
- if ( fatal_error_i_ )
- exit( fatal_error_i_ );
-}
-
-void
-My_midi_parser::forward( int i )
-{
- now_i64_ += i;
-}
-
-Moment
-My_midi_parser::mom()
-{
- return Duration_convert::i2_mom( now_i64_, division_1_i_ );
-}
-
-void
-My_midi_parser::note_begin( int channel_i, int pitch_i, int dyn_i )
-{
- // one pitch a channel at time!
- // heu, what about { < c2 > < c4 d4 > }
-// assert( running_i64_i64_a_[ channel_i ][ pitch_i ] == -1 );
- running_i64_i64_a_[ channel_i ][ pitch_i ] = now_i64_;
-}
-
-Midi_event*
-My_midi_parser::note_end_midi_event_p( int channel_i, int pitch_i, int dyn_i )
-{
- Int64 start_i64 = running_i64_i64_a_[ channel_i ][ pitch_i ];
-
-// running_i64_i64_a_[ channel_i ][ pitch_i ] = -1;
-// assert( start_i64 != -1 ); // did we start?
-
- return new Midi_note( midi_key_p_->notename_str( pitch_i ), midi_time_p_->i2_dur( now_i64_ - start_i64, division_1_i_ ) );
-}
-
-int
-My_midi_parser::output_mudela( String filename_str )
-{
- assert( midi_score_p_ );
- midi_score_p_->process();
- return midi_score_p_->output_mudela( filename_str );
-}
-
-int
-My_midi_parser::parse()
-{
- return ::yyparse();
-}
-
-void
-My_midi_parser::set_division_4( int division_4_i )
-{
- division_1_i_ = division_4_i * 4;
- if ( division_4_i < 0 )
- warning( "seconds iso metrical time" , 0 );
-}
-
-void
-My_midi_parser::set_key( int accidentals_i, int minor_i )
-{
- delete midi_key_p_;
- midi_key_p_ = new Midi_key( accidentals_i, minor_i );
-}
-
-void
-My_midi_parser::set_tempo( int useconds_i )
-{
- delete midi_tempo_p_;
- midi_tempo_p_ = new Midi_tempo( useconds_i );
-}
-
-void
-My_midi_parser::set_time( int num_i, int den_i, int clocks_i, int count_32_i )
-{
- delete midi_time_p_;
- midi_time_p_ = new Midi_time( num_i, den_i, clocks_i, count_32_i );
-}
-
+++ /dev/null
-//
-// track-column.cc -- implement Track_column
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "m2m.hh"
-
-Track_column::Track_column( Moment mom )
-{
- mom_ = mom;
-}
-
-void
-Track_column::add_event( Midi_event* midi_event_p )
-{
- midi_event_p_list_.bottom().add( midi_event_p );
-}
-
-Moment
-Track_column::mom()
-{
- return mom_;
-}
--- /dev/null
+//
+// lily-stream.hh -- part of LilyPond
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+// should i be named Mudela_stream?
+
+#ifndef LILY_STREAM_HH
+#define LILY_STREAM_HH
+
+/// Lily output
+struct Lily_stream {
+ ostream* os_p_;
+ String filename_str_;
+ int indent_i_;
+ int column_i_;
+ int wrap_column_i_;
+ bool comment_mode_bo_;
+
+ Lily_stream( String filename_str );
+ ~Lily_stream();
+
+ Lily_stream& operator <<( String str );
+ Lily_stream& operator <<( Midi_event& midi_event_r );
+
+ void check_comment( String str );
+ void header();
+ void indent();
+ void newline();
+ void open();
+ void tnedni();
+};
+
+#endif // LILY_STREAM_HH
+
--- /dev/null
+//
+// mi2mu.hh -- generic mi2mu include file
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef M2M_HH
+#define M2M_HH
+
+// yes, i know this hurts the dependency calc, however,
+// having includes in headers sucks, and long trial and error
+// include lists also suck.
+// if you want less dependecies, break lib/exe down in smaller
+// modules.
+
+#include <assert.h>
+#include <iostream.h>
+#include <fstream.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "proto.hh"
+#include "plist.hh"
+#include "debug.hh"
+#ifdef mtor
+#undef mtor
+#endif
+
+#include "string.hh"
+#include "string-convert.hh"
+
+#include "lgetopt.hh"
+
+#include "moment.hh"
+#include "duration.hh"
+#include "input-file.hh"
+#include "source-file.hh"
+#include "source.hh"
+
+// mustn-t do, these get touched!
+// #include "fversion.hh"
+// #include "version.hh"
+
+#include "midi-global.hh"
+
+#include "lily-stream.hh"
+#include "midi-event.hh"
+#include "midi-score.hh"
+#include "midi-track.hh"
+#include "midi-voice.hh"
+#include "my-midi-lexer.hh"
+#include "my-midi-parser.hh"
+#include "track-column.hh"
+
+#endif // M2M_HH
+
--- /dev/null
+//
+// midi-event.hh -- declare midi_event
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef MIDI_EVENT_HH
+#define MIDI_EVENT_HH
+
+
+// should these:
+// * be Midi_items
+// * be Voice_elements/requests
+// * get a name-change
+// ?
+
+/// (midi_event)
+class Midi_event {
+public:
+ Midi_event();
+
+ virtual String mudela_str( bool command_mode_bo ) = 0;
+ void output_mudela( Lily_stream& lily_stream_r, bool command_mode_bo );
+ virtual Moment mom();
+};
+
+class Midi_key : public Midi_event {
+public:
+ Midi_key( int accidentals_i, int minor_i );
+
+ String notename_str( int pitch_i );
+ virtual String mudela_str( bool command_mode_bo );
+
+private:
+ int accidentals_i_;
+ int minor_i_;
+ int key_i_;
+};
+
+class Midi_note : public Midi_event {
+public:
+ int const c0_pitch_i_c_ = 60;
+
+ Midi_note( String name_str, Duration dur );
+ virtual Moment mom();
+ virtual String mudela_str( bool command_mode_bo );
+
+private:
+ bool const simple_plet_bo_ = false;
+ Duration dur_;
+ String name_str_;
+};
+
+class Midi_tempo : public Midi_event {
+public:
+ Midi_tempo( int useconds_per_4_i );
+
+ int get_tempo_i( Moment moment );
+ virtual String mudela_str( bool command_mode_bo );
+
+private:
+ int useconds_per_4_i_;
+ Real seconds_per_1_f_;
+};
+
+class Midi_text : public Midi_event {
+public:
+ enum Type {
+ TEXT = 1, COPYRIGHT, TRACK_NAME, INSTRUMENT_NAME, LYRIC,
+ MARKER, CUE_POINT
+ };
+ Midi_text( Midi_text::Type type, String str );
+ virtual String mudela_str( bool command_mode_bo );
+private:
+ Type type_;
+ String text_str_;
+};
+
+class Midi_time : public Midi_event {
+public:
+ Midi_time( 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();
+ virtual String mudela_str( bool command_mode_bo );
+ Moment bar_mom();
+
+private:
+ Real sync_f_;
+ Duration sync_dur_;
+ int clocks_1_i_;
+ int num_i_;
+ int den_i_;
+};
+
+#endif // MIDI_EVENT_HH
+
--- /dev/null
+//
+// midi-global.hh -- declare global (sic) stuff for mi2mu
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef MIDI_GLOBAL_HH
+#define MIDI_GLOBAL_HH
+
+#include "string.hh"
+
+#define monitor_p_g &cout
+enum Verbose { QUIET_ver, BRIEF_ver, NORMAL_ver, VERBOSE_ver, DEBUG_ver };
+extern Verbose level_ver;
+#ifdef NPRINT
+#define dtor if ( 0 ) *monitor_p_g
+#define mtor if ( 0 ) *monitor_p_g
+#else
+#define dtor if ( level_ver >= DEBUG_ver ) *monitor_p_g
+#define vtor if ( level_ver >= VERBOSE_ver ) *monitor_p_g
+#define mtor if ( level_ver >= NORMAL_ver ) *monitor_p_g
+#define btor if ( level_ver >= BRIEF_ver ) *monitor_p_g
+#define qtor if ( level_ver >= QUIET_ver ) *monitor_p_g
+#endif
+
+extern Source* source_l_g;
+extern bool no_triplets_bo_g;
+void message( String message_str, char const* context_ch_c_l );
+void warning( String message_str, char const* context_ch_c_l );
+void error( String message_str, char const* context_ch_c_l );
+
+String version_str();
+
+#endif // MIDI_GLOBAL_HH
+
--- /dev/null
+//
+// midi-score.hh -- declare midi_score
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef MIDI_SCORE_HH
+#define MIDI_SCORE_HH
+
+/// (midi_score)
+class Midi_score {
+public:
+ Midi_score( int format_i, int tracks_i, int tempo_i );
+ ~Midi_score();
+
+ void add_track( Midi_track* midi_track_p );
+
+ int output_mudela( String filename_str );
+ void process();
+
+private:
+ IPointerList<Midi_track*> midi_track_p_list_;
+ int format_i_;
+ int tracks_i_;
+ int tempo_i_;
+};
+
+#endif // MIDI_SCORE_HH
+
--- /dev/null
+//
+// midi-track.hh -- declare midi_track
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef MIDI_TRACK_HH
+#define MIDI_TRACK_HH
+
+/// (midi_track)
+class Midi_track {
+public:
+ Midi_track( int number_i, String copyright_str, String track_name_str, String instrument_str );
+
+ void add_event( Moment mom, Midi_event* midi_event_p );
+ Moment end_mom();
+ String name_str();
+ void output_mudela( Lily_stream& lily_stream_r );
+ Moment next_begin_mom( Moment now_mom );
+ Moment next_end_mom( Moment now_mom );
+ void process();
+ Track_column* tcol_l( Moment mom );
+
+ String copyright_str_;
+ String instrument_str_;
+ String name_str_;
+
+private:
+ void add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom );
+ Midi_voice* get_free_midi_voice_l( Moment mom );
+ void remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom );
+ IPointerList<Track_column*> tcol_p_list_;
+ IPointerList<Midi_voice*> midi_voice_p_list_;
+ int number_i_;
+
+};
+
+#endif // MIDI_TRACK_HH
+
--- /dev/null
+//
+// midi-voice.hh -- declare midi_voice
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+/// (midi_voice)
+#ifndef MIDI_VOICE_HH
+#define MIDI_VOICE_HH
+
+class Midi_voice {
+public:
+ Midi_voice( Moment begin_mom );
+
+ void add_event( Midi_event* midi_event_p );
+ Moment begin_mom();
+ Moment end_mom();
+
+ String mudela_str( Moment from_mom, Moment to_mom, bool multiple_bo );
+
+private:
+ Moment begin_mom_;
+ IPointerList<Midi_event*> midi_event_p_list_;
+};
+
+#endif // MIDI_VOICE_HH
+
--- /dev/null
+//
+// my-midi-lexer.hh -- declare My_midi_lexer
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef MY_MIDI_LEXER_HH
+#define MY_MIDI_LEXER_HH
+
+#include <FlexLexer.h>
+#include "proto.hh"
+// #include "fproto.hh"
+#include "varray.hh"
+#include "string.hh"
+
+int yylex();
+void yyerror(const char *s);
+// bool busy_parsing();
+// void kill_lexer();
+// void set_lexer();
+
+/// (midi_lexer)
+class My_midi_lexer : yyFlexLexer {
+public:
+ My_midi_lexer( String filename_str );
+ ~My_midi_lexer();
+
+ int close_i();
+ void error( char const* sz_l );
+ char const* here_ch_c_l();
+ static int varint2_i( String str );
+ int yylex();
+
+private:
+ Input_file* input_file_p_;
+
+public: // ugh
+ int errorlevel_i_;
+};
+
+extern My_midi_lexer* midi_lexer_l_g;
+
+#endif // MY_MIDI_LEXER_HH
+
--- /dev/null
+//
+// my-midi-parser.hh -- declare My_midi_parser
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef MY_MIDI_PARSER_HH
+#define MY_MIDI_PARSER_HH
+
+// #include "proto.hh"
+// #include "string.hh"
+
+int yyparse();
+
+/// (midi_parser)
+class My_midi_parser {
+public:
+ My_midi_parser( String filename_str );
+ ~My_midi_parser();
+
+ void add_score( Midi_score* midi_score_p );
+ void error( char const* sz_l );
+ int parse();
+ void forward( int i );
+ Moment mom();
+ void note_begin( int channel_i, int pitch_i, int dyn_i );
+ Midi_event* note_end_midi_event_p( int channel_i, int pitch_i, int dyn_i );
+ int output_mudela( String filename_str );
+ void reset();
+ void set_division_4( int division_4_i );
+ void set_key( int accidentals_i, int minor_i );
+ void set_tempo( int useconds_i );
+ void set_time( int num_i, int den_i, int clocks_i, int count_32_i );
+
+ int bar_i_;
+ int track_i_;
+ String filename_str_;
+ String copyright_str_;
+ String instrument_str_;
+ String track_name_str_;
+
+ Midi_key* midi_key_p_;
+ Midi_tempo* midi_tempo_p_;
+ Midi_time* midi_time_p_;
+
+private:
+ I64 now_i64_; // 31 bits yields tipically about 1000 bars
+
+ static int const CHANNELS_i = 16;
+ static int const PITCHES_i = 128;
+ I64 running_i64_i64_a_[ CHANNELS_i ][ PITCHES_i ];
+
+ Midi_score* midi_score_p_;
+ int division_1_i_;
+
+ char const* defined_ch_c_l_;
+ int fatal_error_i_;
+ My_midi_lexer* midi_lexer_p_;
+};
+
+extern My_midi_parser* midi_parser_l_g;
+
+#endif // MY_MIDI_PARSER_HH
+
--- /dev/null
+//
+// track-column.hh -- declare Track_column
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#ifndef TRACK_COLUMN_HH
+#define TRACK_COLUMN_HH
+
+/// (tcol)
+class Track_column {
+public:
+ Track_column( Moment mom );
+
+ void add_event( Midi_event* midi_event_p );
+ Moment mom();
+
+//private:
+ IPointerList<Midi_event*> midi_event_p_list_;
+ Moment mom_;
+};
+
+#endif // TRACK_COLUMN_HH
+
--- /dev/null
+//
+// lily-stream.cc
+//
+// source file of the LilyPond music typesetter
+//
+// (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+// should i be named Mudela_stream?
+
+#include "mi2mu.hh"
+
+Lily_stream::Lily_stream( String filename_str )
+{
+ filename_str_ = filename_str;
+ os_p_ = 0;
+ indent_i_ = 0;
+ comment_mode_bo_ = false;
+ column_i_ = 0;
+ wrap_column_i_ = 60;
+ open();
+ header();
+}
+
+Lily_stream::~Lily_stream()
+{
+ delete os_p_;
+ if ( indent_i_ )
+ warning( "lily indent level: " + String( indent_i_ ), 0 );
+}
+
+Lily_stream&
+Lily_stream::operator <<( String str )
+{
+ static String nobreak_str = "\\`'_-.^<>*@";
+ while ( str.length_i() ) {
+ int max_i = wrap_column_i_ - column_i_ - 1;
+ int i = str.length_i() - 1 <? max_i;
+ int nl_i = str.left_str( i + 1 ).index_i( '\n' );
+ if ( nl_i != -1 ) {
+ i = nl_i - 1;
+ str = str.nomid_str( nl_i, 1 );
+ }
+
+ if ( ( i != str.length_i() - 1 ) && ( nl_i == -1 ) )
+ while ( i && ( isalnum( str[ i ] )
+ || ( nobreak_str.index_i( str[ i ] ) != -1 ) ) )
+ i--;
+
+ if ( !i ) { // no room left
+ if ( column_i_ > 8 * indent_i_ ) {
+ newline();
+ if ( comment_mode_bo_ && ( str[ 0 ] != '%' ) )
+ str = '%' + str;
+ continue;
+ }
+ else { // cannot break neatly...
+ i = max_i;
+ }
+ }
+
+ String line = str.left_str( i + 1 );
+ str = str.mid_str( i + 1, INT_MAX );
+ *os_p_ << line;
+ if ( nl_i != -1 )
+ newline();
+ else
+ check_comment( line );
+ column_i_ += line.length_i();
+ if ( str.length_i() || ( column_i_ >= wrap_column_i_ ) ) {
+ //brr.
+ if ( comment_mode_bo_ )
+ str = "%" + str;
+ newline();
+ }
+ }
+ return *this;
+}
+
+Lily_stream&
+Lily_stream::operator <<( Midi_event& midi_event_r )
+{
+ midi_event_r.output_mudela( *this, false );
+ *os_p_ << flush;
+ return *this;
+}
+
+void
+Lily_stream::check_comment( String str )
+{
+ int newline_i = str.index_last_i( '\n' );
+ if ( newline_i != -1 ) {
+ str = str.mid_str( newline_i +1, INT_MAX );
+ comment_mode_bo_ = false;
+ }
+ if ( str.index_i( '%' ) != -1 )
+ comment_mode_bo_ = true;
+}
+
+void
+Lily_stream::header()
+{
+ *os_p_ << "% Creator: " << 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";
+}
+
+void
+Lily_stream::indent()
+{
+ indent_i_++;
+ newline();
+}
+
+void
+Lily_stream::newline()
+{
+ *os_p_ << endl << String( '\t', indent_i_ );
+ column_i_ = indent_i_ * 8;
+ comment_mode_bo_ = false;
+}
+
+void
+Lily_stream::open()
+{
+ os_p_ = new ofstream( filename_str_ );
+ if ( !*os_p_ )
+ error ( "can't open `" + filename_str_ + "\'", 0 );
+}
+
+void
+Lily_stream::tnedni()
+{
+ assert( indent_i_ > 0 );
+ indent_i_--;
+ newline();
+}
+
--- /dev/null
+//
+// main.cc -- implement silly main() entry point
+// should have Root class.
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+Source source;
+Source* source_l_g = &source;
+
+Verbose level_ver = NORMAL_ver;
+
+// ugh
+bool no_triplets_bo_g = false;
+
+//ugh
+char const* defined_ch_c_l = 0;
+
+// ugh, another global
+String
+find_file( String str )
+{
+ return str;
+}
+
+// ugh, copied from warn.cc, cannot use
+void
+message( String message_str, char const* context_ch_c_l )
+{
+ String str = "mi2mu: ";
+ Source_file* sourcefile_l = source_l_g->sourcefile_l( context_ch_c_l );
+ if ( sourcefile_l ) {
+ str += sourcefile_l->file_line_no_str(context_ch_c_l) + String(": ");
+ }
+ str += message_str;
+ if ( sourcefile_l ) {
+ str += ":\n";
+ str += sourcefile_l->error_str( context_ch_c_l );
+ }
+// if ( busy_parsing() )
+ cerr << endl; // until we have fine output manager...
+ cerr << str << endl;
+}
+
+void
+warning( String message_str, char const* context_ch_c_l )
+{
+ message( "warning: " + message_str, context_ch_c_l );
+}
+
+void
+error( String message_str, char const* context_ch_c_l )
+{
+ message( message_str, context_ch_c_l );
+ // since when exits error again?
+ // i-d say: error: errorlevel |= 1; -> no output upon error
+ // warning: recovery -> output (possibly wrong)
+ if ( midi_lexer_l_g )
+ midi_lexer_l_g->errorlevel_i_ |= 1;
+}
+
+void
+help()
+{
+ btor <<
+ "--debug, -d be really verbose\n"
+ "--help, -h this help\n"
+ "--include=DIR, -I DIR add DIR to search path\n"
+ "--no-triplets, -n assume no triplets\n"
+ "--output=FILE, -o FILE set FILE as default output\n"
+ "--quiet, -q be quiet\n"
+ "--verbose, -v be verbose\n"
+ "--warranty, -w show warranty & copyright\n"
+ ;
+}
+
+void
+identify()
+{
+ mtor << version_str() << endl;
+}
+
+void
+notice()
+{
+ mtor <<
+ "\n"
+ "Mi2mu, translate midi to mudela.\n"
+ "Copyright (C) 1997 by\n"
+ " Han-Wen Nienhuys <hanwen@stack.nl>\n"
+// "Contributors\n"
+ " Jan Nieuwenhuizen <jan@digicash.com>\n"
+// " Mats Bengtsson <matsb@s3.kth.se>\n"
+ "\n"
+ " 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[] )
+{
+ Long_option_init long_option_init_a[] = {
+ 0, "debug", 'd',
+ 0, "help", 'h',
+// 1, "include", 'I',
+ 0, "no-triplets", 'n',
+ 1, "output", 'o',
+ 0, "quiet", 'q',
+ 0, "verbose", 'v',
+ 0, "warranty", 'w',
+ 0,0,0
+ };
+ Getopt_long getopt_long( argc_i, argv_sz_a, long_option_init_a );
+ identify();
+
+ String output_str;
+ while ( Long_option_init* long_option_init_p = getopt_long() )
+ switch ( long_option_init_p->shortname ) {
+ case 'd':
+ level_ver = DEBUG_ver;
+ break;
+ case 'h':
+ help();
+ exit( 0 );
+ break;
+// case 'I':
+// path->push( getopt_long.optarg );
+// break;
+ case 'n':
+ no_triplets_bo_g = true;
+ break;
+ case 'o':
+ output_str = getopt_long.optarg;
+ break;
+ case 'q':
+ level_ver = QUIET_ver;
+ break;
+ case 'v':
+ level_ver = VERBOSE_ver;
+ break;
+ case 'w':
+ notice();
+ exit( 0 );
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
+
+ char* arg_sz = 0;
+ while ( ( arg_sz = getopt_long.get_next_arg() ) ) {
+ My_midi_parser midi_parser( arg_sz );
+ int error_i = midi_parser.parse();
+ if ( error_i )
+ return error_i;
+ if ( !output_str.length_i() ) {
+ output_str = String( arg_sz ) + ".ly";
+ // i-m sure there-s already some routine for this
+ int name_i; // too bad we can-t declare local to if
+ if ( ( name_i = output_str.index_last_i( '/' ) ) != -1 )
+ output_str = output_str.mid_str( name_i + 1, INT_MAX );
+ }
+ error_i = midi_parser.output_mudela( output_str );
+ if ( error_i )
+ return error_i;
+ }
+ return 0;
+}
--- /dev/null
+//
+// midi-event.cc -- implement Midi_event
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+Midi_event::Midi_event()
+{
+}
+
+Moment
+Midi_event::mom()
+{
+ return Moment( 0 );
+}
+
+void
+Midi_event::output_mudela( Lily_stream& lily_stream_r, bool command_mode_bo )
+{
+ lily_stream_r << mudela_str( command_mode_bo ) << String( " " );
+}
+
+Midi_key::Midi_key( int accidentals_i, int minor_i )
+{
+ 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
+Midi_key::mudela_str( bool command_mode_bo )
+{
+ 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' ) );
+ if ( !command_mode_bo )
+ str = String( '\\' ) + str;
+ str = String( "%" ) + str + "\n"; // "\key\F" not supported yet...
+ return str;
+}
+
+String
+Midi_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 octave_str;
+
+ octave_str += String( '\'', ( pitch_i - Midi_note::c0_pitch_i_c_ ) / 12 );
+ octave_str += String( '`', ( Midi_note::c0_pitch_i_c_ + 11 - pitch_i ) / 12 );
+ return octave_str + notename_str;
+}
+
+Midi_note::Midi_note( String name_str, Duration dur )
+{
+ // do i want pitch too?
+ dur_ = dur;
+ name_str_ = name_str;
+}
+
+String
+Midi_note::mudela_str( bool command_mode_bo )
+{
+// assert( !command_mode_bo );
+// undefined ref to simple_plet_bo_ ??
+// if ( simple_plet_bo_ )
+// return name_str_ + Duration_convert::dur2_str( dur_ );
+
+ //ugh
+ String str;
+ if ( dur_.plet_p_ )
+ str += String( "\\plet{ " )
+ + String_convert::i2dec_str( dur_.plet_p_->iso_i_, 0, 0 )
+ + "/"
+ + String_convert::i2dec_str( dur_.plet_p_->type_i_, 0, 0 )
+ + " } ";
+
+ str += name_str_;
+
+ Duration dur = dur_;
+ dur.set_plet( 0 );
+ str += Duration_convert::dur2_str( dur );
+
+ if ( dur_.plet_p_ )
+ str += String( " \\plet{ 1/1 }" );
+
+ return str;
+}
+
+Moment
+Midi_note::mom()
+{
+ return Duration_convert::dur2_mom( dur_ );
+}
+
+Midi_tempo::Midi_tempo( int useconds_per_4_i )
+{
+ useconds_per_4_i_ = useconds_per_4_i;
+// huh, is it not per 4?
+// seconds_per_1_f_ = (Real)useconds_per_4_i_ * 4 / 1e6;
+ seconds_per_1_f_ = (Real)useconds_per_4_i_ * 8 / 1e6;
+}
+
+String
+Midi_tempo::mudela_str( bool command_mode_bo )
+{
+// assert( command_mode_bo );
+ if ( !command_mode_bo )
+ return "";
+ String str = "tempo 4:";
+ str += String( get_tempo_i( Moment( 1, 4 ) ) );
+ return str;
+}
+
+int
+Midi_tempo::get_tempo_i( Moment moment )
+{
+ return Moment( 60 ) / moment / Moment( seconds_per_1_f_ );
+}
+
+Midi_text::Midi_text( Midi_text::Type type, String text_str )
+{
+ type_ = type;
+ text_str_ = text_str;
+}
+
+String
+Midi_text::mudela_str( bool command_mode_bo )
+{
+ (void)command_mode_bo;
+ if ( !text_str_.length_i()
+ || ( text_str_.length_i() != (int)strlen( text_str_.ch_c_l() ) ) )
+ return "";
+
+ return "% " + text_str_ + "\n\t";
+}
+
+Midi_time::Midi_time( int num_i, int den_i, int clocks_4_i, int count_32_i )
+ : sync_dur_( 8 )
+{
+ sync_f_ = 1.0;
+ if ( count_32_i != 8 )
+ warning( String( "#32 in quarter: " ) + String( count_32_i ), 0 );
+ num_i_ = num_i;
+ den_i_ = 2 << den_i;
+ clocks_1_i_ = clocks_4_i * 4;
+}
+
+Moment
+Midi_time::bar_mom()
+{
+ return Moment( num_i_ ) * Duration_convert::dur2_mom( Duration( den_i_ ) );
+}
+
+int
+Midi_time::clocks_1_i()
+{
+ return clocks_1_i_;
+}
+
+Duration
+Midi_time::i2_dur( int time_i, int division_1_i )
+{
+ Moment mom = Duration_convert::i2_mom( time_i, division_1_i );
+ mom /= sync_f_;
+
+ dtor << "\n% (" << time_i << ", " << mom << "): "
+ << sync_f_ << endl;
+
+ Duration dur = Duration_convert::mom2_dur( mom );
+ if ( !dur.type_i_ ) {
+ vtor << "\n% resyncing(" << time_i << ", " << mom << "): "
+ << sync_f_ << " -> ";
+ mom *= sync_f_;
+ sync_f_ = Duration_convert::sync_f( sync_dur_, mom );
+ vtor << sync_f_ << endl;
+ mom /= sync_f_;
+ dur = Duration_convert::mom2_dur( mom );
+ }
+
+ return dur;
+}
+
+String
+Midi_time::mudela_str( bool command_mode_bo )
+{
+ String str = "meter { "
+ + String( num_i_ ) + "*" + String( den_i_ )
+ + " }";
+ if ( !command_mode_bo )
+ str = String( '\\' ) + str;
+ return str;
+}
+
--- /dev/null
+//
+// midi-score.cc -- implement Midi_score
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+Midi_score::Midi_score( int format_i, int tracks_i, int tempo_i )
+{
+ format_i_ = format_i;
+ tracks_i_ = tracks_i;
+ tempo_i_ = tempo_i;
+}
+
+Midi_score::~Midi_score()
+{
+}
+
+void
+Midi_score::add_track( Midi_track* midi_track_p )
+{
+ midi_track_p_list_.bottom().add( midi_track_p );
+}
+
+int
+Midi_score::output_mudela( String filename_str )
+{
+ mtor << "Lily output to " << filename_str << " ..." << endl;
+
+ int track_i = 0;
+ Lily_stream lily_stream( filename_str );
+ for ( PCursor<Midi_track*> i( midi_track_p_list_.top() ); i.ok(); i++ ) {
+ mtor << "track " << track_i++ << ": " << flush;
+ i->output_mudela( lily_stream );
+ lily_stream.newline();
+ mtor << endl;
+ }
+
+ lily_stream << "score {";
+ lily_stream.newline();
+
+ for ( PCursor<Midi_track*> i( midi_track_p_list_.top() ); i.ok(); i++ ) {
+ lily_stream << "\tstaff { melodic music { ";
+ lily_stream << i->name_str();
+ lily_stream << " } }";
+ lily_stream.newline();
+ }
+
+ lily_stream.indent();
+ lily_stream << "commands {";
+ lily_stream.indent();
+ midi_parser_l_g->midi_time_p_->output_mudela( lily_stream, true );
+ lily_stream.tnedni();
+ lily_stream << "}";
+ lily_stream.newline();
+ lily_stream << "midi {";
+ lily_stream.indent();
+ midi_parser_l_g->midi_tempo_p_->output_mudela( lily_stream, true );
+ lily_stream.tnedni();
+ lily_stream << "}";
+ lily_stream.tnedni();
+
+ lily_stream << "}";
+ lily_stream.newline();
+
+ return 0;
+}
+
+void
+Midi_score::process()
+{
+ int track_i = 0;
+ for ( PCursor<Midi_track*> i( midi_track_p_list_.top() ); i.ok(); i++ ) {
+ mtor << "track " << track_i++ << ": " << flush;
+ i->process();
+ mtor << endl;
+ }
+}
+
--- /dev/null
+//
+// midi-track.cc -- implement Midi_track
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+Midi_track::Midi_track( 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;
+ if ( track_name_str.length_i() )
+ name_str_ = track_name_str;
+ else
+ name_str_ = String( "track" ) + String( number_i_ );
+ tcol_p_list_.bottom().add( new Track_column( Moment( 0 ) ) );
+}
+
+void
+Midi_track::add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
+{
+ for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
+ if ( i->begin_mom() == mom ) {
+ dtor << "open_voices (" << open_voices_r.size() << "): +1\n";
+ open_voices_r.bottom().add( *i );
+ }
+}
+
+void
+Midi_track::add_event( Moment mom, Midi_event* midi_event_p )
+{
+ if ( ! midi_event_p )
+ return;
+ tcol_l( mom - midi_event_p->mom() )->add_event( midi_event_p );
+}
+
+// too much red tape?
+String
+Midi_track::name_str()
+{
+ return name_str_;
+}
+
+Moment
+Midi_track::end_mom()
+{
+ // heu..
+ Moment mom = 0.0;
+ for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
+ mom = i->end_mom() >? mom;
+ return mom;
+}
+
+Midi_voice*
+Midi_track::get_free_midi_voice_l( Moment mom )
+{
+ for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
+ if ( i->end_mom() == mom )
+ return *i;
+
+ Midi_voice* midi_voice_p = new Midi_voice( mom );
+ Midi_voice* midi_voice_l = midi_voice_p;
+ midi_voice_p_list_.bottom().add( midi_voice_p );
+ return midi_voice_l;
+}
+
+Moment
+Midi_track::next_begin_mom( Moment now_mom )
+{
+// Moment begin_mom = Midi_track::end_mom() + 1;
+ Moment begin_mom = Midi_track::end_mom();
+ for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
+// if ( i->begin_mom() >= now_mom )
+ if ( i->begin_mom() > now_mom )
+ begin_mom = begin_mom <? i->begin_mom();
+ return begin_mom;
+}
+
+Moment
+Midi_track::next_end_mom( Moment now_mom )
+{
+ Moment end_mom = Midi_track::end_mom();
+ for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
+ if ( i->end_mom() > now_mom )
+ end_mom = end_mom <? i->end_mom();
+ return end_mom;
+}
+
+void
+Midi_track::process()
+{
+ int bar_i = 1;
+ Moment bar_mom = midi_parser_l_g->midi_time_p_->bar_mom();
+
+ for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
+ int bars_i = (int)( i->mom() / bar_mom );
+ if ( bars_i > bar_i )
+ mtor << '[' << bar_i << flush;
+ while ( i->midi_event_p_list_.size() )
+ // shit, where has the T* PCursor::remove() gone??
+ // i don-t want to get and delete,
+ // i want to (re)move!
+ // is it renamed: get vs add/insert ?? (put/remove :-)
+ get_free_midi_voice_l( i->mom() )->add_event( i->midi_event_p_list_.top().remove_p() );
+ if ( bars_i > bar_i ) {
+ bar_i++;
+ mtor << ']' << flush;
+ }
+ }
+
+ dtor << "ends: " << endl;
+ int n = 0;
+ for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
+ vtor << "voice " << n++ << ": " << i->end_mom() << endl;
+ dtor << ":sdne" << endl;
+}
+
+
+void
+Midi_track::output_mudela( Lily_stream& lily_stream_r )
+{
+ lily_stream_r << name_str_ << " = music { $";
+ lily_stream_r.indent();
+ lily_stream_r << "% midi copyright:" << copyright_str_;
+ lily_stream_r.newline();
+ lily_stream_r << "% instrument:" << instrument_str_;
+ lily_stream_r.newline();
+
+ int bar_i = 1;
+ Moment bar_mom = midi_parser_l_g->midi_time_p_->bar_mom();
+
+ PointerList<Midi_voice*> open_voices;
+ Moment now_mom = 0.0;
+ Moment then_mom = 0.0;
+ while ( now_mom < end_mom() ) {
+ int bars_i = (int)( now_mom / bar_mom );
+ if ( bars_i > bar_i )
+ mtor << '[' << bar_i << flush;
+ add_begin_at( open_voices, now_mom );
+
+ Moment begin_mom = next_begin_mom( now_mom );
+ Moment end_mom = next_end_mom( now_mom );
+ if ( ( begin_mom > now_mom ) && ( begin_mom < end_mom ) )
+ then_mom = begin_mom;
+ else
+ then_mom = end_mom;
+
+ dtor << "begin: " << begin_mom << " end: " << end_mom << endl;
+ dtor << "slice: " << now_mom << ", " << then_mom << endl;
+
+ if ( open_voices.size() > 1 )
+ lily_stream_r << "{ ";
+ for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
+ lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
+ if ( open_voices.size() > 1 )
+ lily_stream_r << "} ";
+ now_mom = then_mom;
+
+ remove_end_at( open_voices, now_mom );
+ if ( bars_i > bar_i ) {
+ bar_i++;
+ mtor << ']' << flush;
+ }
+ }
+ lily_stream_r.tnedni();
+ lily_stream_r << "$} % " << name_str_;
+ lily_stream_r.newline();
+}
+
+void
+Midi_track::remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
+{
+ for ( PCursor<Midi_voice*> i( open_voices_r.top() ); i.ok(); i++ )
+ if ( i->end_mom() <= mom ) {
+ dtor << "open_voices (" << open_voices_r.size() << "): -1\n";
+ i.remove_p(); // remove? // no delete; only a copy
+ if ( !i.ok() )
+ break;
+ }
+}
+
+Track_column*
+Midi_track::tcol_l( Moment mom )
+{
+ for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
+ if ( i->mom() == mom )
+ return *i;
+ if ( i->mom() > mom ) {
+ Track_column* tcol_p = new Track_column( mom );
+ i.insert( tcol_p );
+ return tcol_p;
+ }
+ }
+
+ Track_column* tcol_p = new Track_column( mom );
+ tcol_p_list_.bottom().add( tcol_p );
+ return tcol_p;
+}
+
--- /dev/null
+//
+// midi-voice.cc -- implement midi_voice
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+Midi_voice::Midi_voice( Moment begin_mom )
+{
+ begin_mom_ = begin_mom;
+}
+
+void
+Midi_voice::add_event( Midi_event* midi_event_p )
+{
+ midi_event_p_list_.bottom().add( midi_event_p );
+}
+
+Moment
+Midi_voice::begin_mom()
+{
+ return begin_mom_;
+}
+
+Moment
+Midi_voice::end_mom()
+{
+ Moment now_mom = begin_mom_;
+ dtor << now_mom << ", ";
+ for ( PCursor<Midi_event*> i( midi_event_p_list_.top() ); i.ok(); i++ ) {
+ dtor << now_mom << ", ";
+ now_mom += i->mom();
+ }
+ dtor << endl;
+ return now_mom;
+}
+
+String
+Midi_voice::mudela_str( Moment from_mom, Moment to_mom, bool multiple_bo )
+{
+ String str;
+
+ if ( begin_mom() >= to_mom )
+ return "";
+ if ( end_mom() <= from_mom )
+ return "";
+
+ Moment now_mom = begin_mom();
+ PCursor<Midi_event*> i( midi_event_p_list_.top() );
+ for ( ; i.ok() && now_mom < from_mom ; i++ )
+ now_mom += i->mom();
+
+ for ( ; i.ok() && now_mom < to_mom ; i++ ) {
+ now_mom += i->mom();
+ str += i->mudela_str( false ) + " ";
+ }
+
+ if ( str.length_i() && multiple_bo )
+ str = "\\music{ " + str + "} ";
+ return str;
+}
+
--- /dev/null
+//
+// my-midi-lexer.cc -- implement My_midi_lexer
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+int
+yylex()
+{
+ return midi_lexer_l_g->yylex();
+}
+
+My_midi_lexer* midi_lexer_l_g = 0;
+
+My_midi_lexer::My_midi_lexer( String filename_str )
+{
+ midi_lexer_l_g = this;
+ input_file_p_ = new Input_file( filename_str );
+ switch_streams( input_file_p_->is );
+ errorlevel_i_ = 0;
+}
+
+My_midi_lexer::~My_midi_lexer()
+{
+ delete input_file_p_;
+ midi_lexer_l_g = 0;
+}
+
+void
+My_midi_lexer::error( char const* sz_l )
+{
+ if ( !input_file_p_ ) {
+// *mlog << "error at EOF" << sz_l << '\n';
+ cerr << "error at EOF" << sz_l << '\n';
+ } else {
+ char const* ch_c_l = here_ch_c_l();
+ if ( ch_c_l ) {
+ ch_c_l--;
+ while ( ( *ch_c_l == ' ' ) || ( *ch_c_l == '\t' ) || ( *ch_c_l == '\n' ) )
+ ch_c_l--;
+ ch_c_l++;
+ }
+ errorlevel_i_ |= 1;
+// ::error( sz_l, ch_c_l );
+ ::error( sz_l, ch_c_l );
+ }
+}
+
+char const*
+My_midi_lexer::here_ch_c_l()
+{
+ return input_file_p_->sourcefile_l_->ch_c_l() + yyin->tellg();
+}
+
+int
+My_midi_lexer::varint2_i( String str )
+{
+ int var_i = 0;
+
+ for ( int i = 0; i < str.length_i(); i++ ) {
+ Byte byte = str[ i ];
+ var_i <<= 7;
+ var_i += byte & 0x7f;
+ if ( ! ( byte & 0x80 ) )
+ return var_i;
+ }
+ cout << "\nvarint2_i:" << String_convert::bin2hex_str( str ) << endl;
+ assert( 0 ); // illegal varint
+ return 0;
+}
+
+int
+My_midi_lexer::close_i()
+{
+ return 0;
+}
+
--- /dev/null
+//
+// my-midi-parser.cc -- implement My_midi_parser
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+void
+yyerror(char const* sz_l )
+{
+ midi_parser_l_g->error( sz_l );
+}
+
+
+My_midi_parser* midi_parser_l_g = 0;
+
+My_midi_parser::My_midi_parser( String filename_str )
+{
+ midi_parser_l_g = this;
+ filename_str_ = filename_str;
+ midi_lexer_p_ = new My_midi_lexer( filename_str_ );
+ defined_ch_c_l_ = 0;
+ fatal_error_i_ = 0;
+ midi_key_p_ = 0;
+ midi_score_p_ = 0;
+ midi_tempo_p_ = 0;
+ midi_time_p_ = 0;
+ track_i_ = 0;
+ bar_i_ = 1;
+ reset();
+}
+
+My_midi_parser::~My_midi_parser()
+{
+ delete midi_lexer_p_;
+ midi_parser_l_g = 0;
+ delete midi_key_p_;
+ delete midi_tempo_p_;
+ delete midi_time_p_;
+ delete midi_score_p_;
+}
+
+void
+My_midi_parser::reset()
+{
+ delete midi_key_p_;
+ midi_key_p_ = new Midi_key( 0, 0 );
+ // useconds per 4: 250000 === 60 4 per minute
+ delete midi_tempo_p_;
+ midi_tempo_p_ = new Midi_tempo( 250000 );
+ delete midi_time_p_;
+ midi_time_p_ = new Midi_time( 4, 4, 384, 8 );
+ now_i64_ = 0;
+ bar_i_ = 1;
+
+ copyright_str_ = "";
+ track_name_str_ = "";
+ instrument_str_ = "";
+
+ for ( int i = 0; i < CHANNELS_i; i++ )
+ for ( int j = 0; j < PITCHES_i; j++ )
+// running_i64_i64_a_[ i ][ j ] = -1;
+ running_i64_i64_a_[ i ][ j ] = 0;
+}
+
+void
+My_midi_parser::add_score( Midi_score* midi_score_p )
+{
+ assert( !midi_score_p_ );
+ midi_score_p_ = midi_score_p;
+ track_i_ = 0;
+ bar_i_ = 1;
+}
+
+void
+My_midi_parser::error( char const* sz_l )
+{
+ midi_lexer_l_g->error( sz_l );
+
+ if ( fatal_error_i_ )
+ exit( fatal_error_i_ );
+}
+
+void
+My_midi_parser::forward( int i )
+{
+ now_i64_ += i;
+}
+
+Moment
+My_midi_parser::mom()
+{
+ return Duration_convert::i2_mom( now_i64_, division_1_i_ );
+}
+
+void
+My_midi_parser::note_begin( int channel_i, int pitch_i, int dyn_i )
+{
+ // one pitch a channel at time!
+ // heu, what about { < c2 > < c4 d4 > }
+// assert( running_i64_i64_a_[ channel_i ][ pitch_i ] == -1 );
+ running_i64_i64_a_[ channel_i ][ pitch_i ] = now_i64_;
+}
+
+Midi_event*
+My_midi_parser::note_end_midi_event_p( int channel_i, int pitch_i, int dyn_i )
+{
+ I64 start_i64 = running_i64_i64_a_[ channel_i ][ pitch_i ];
+
+// running_i64_i64_a_[ channel_i ][ pitch_i ] = -1;
+// assert( start_i64 != -1 ); // did we start?
+
+ return new Midi_note( midi_key_p_->notename_str( pitch_i ), midi_time_p_->i2_dur( now_i64_ - start_i64, division_1_i_ ) );
+}
+
+int
+My_midi_parser::output_mudela( String filename_str )
+{
+ assert( midi_score_p_ );
+ mtor << "\nProcessing..." << endl;
+ midi_score_p_->process();
+ return midi_score_p_->output_mudela( filename_str );
+}
+
+int
+My_midi_parser::parse()
+{
+ mtor << "\nParsing..." << flush;
+ return ::yyparse();
+}
+
+void
+My_midi_parser::set_division_4( int division_4_i )
+{
+ division_1_i_ = division_4_i * 4;
+ if ( division_4_i < 0 )
+ warning( "seconds iso metrical time" , 0 );
+}
+
+void
+My_midi_parser::set_key( int accidentals_i, int minor_i )
+{
+ delete midi_key_p_;
+ midi_key_p_ = new Midi_key( accidentals_i, minor_i );
+}
+
+void
+My_midi_parser::set_tempo( int useconds_i )
+{
+ delete midi_tempo_p_;
+ midi_tempo_p_ = new Midi_tempo( useconds_i );
+}
+
+void
+My_midi_parser::set_time( int num_i, int den_i, int clocks_i, int count_32_i )
+{
+ delete midi_time_p_;
+ midi_time_p_ = new Midi_time( num_i, den_i, clocks_i, count_32_i );
+}
+
--- /dev/null
+//
+// template.cc -- implementemplate
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "proto.hh"
+#include "list.hh"
+#include "list.tcc"
+#include "cursor.tcc"
+
+L_instantiate(void *);
+
+class istream;
+class ostream;
+
+#include "mi2mu.hh"
+#include "plist.hh"
+#include "plist.tcc"
+
+IPL_instantiate(Midi_event);
+IPL_instantiate(Midi_track);
+PL_instantiate(Midi_voice);
+IPL_instantiate(Midi_voice);
+IPL_instantiate(Source_file);
+IPL_instantiate(Track_column);
+
--- /dev/null
+//
+// track-column.cc -- implement Track_column
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+
+Track_column::Track_column( Moment mom )
+{
+ mom_ = mom;
+}
+
+void
+Track_column::add_event( Midi_event* midi_event_p )
+{
+ midi_event_p_list_.bottom().add( midi_event_p );
+}
+
+Moment
+Track_column::mom()
+{
+ return mom_;
+}
--- /dev/null
+//
+// version.cc -- implement inexpensive versioning
+//
+// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+
+#include "mi2mu.hh"
+#include "fversion.hh"
+#include "version.hh"
+
+// should simply have Root class...
+String
+version_str()
+{
+ return String ( "This is mi2mu " ) + VERSIONSTR
+ + "/FlowerLib " + FVERSIONSTR
+ + " of " + __DATE__ + " " + __TIME__;
+}
+