+pl 9.jcn2
+ - redo of mi2mu frontend (midi-parser)
+ - bf: String_convert::bin2_i; added bin2_u
+ - bf's: Binary_source_file
+ - bf: constr. Tempo/Timing_req
+
pl 9
- declare rhythic_request
- preliminary support for real \mudelaheaders
TOPLEVEL_PATCH_LEVEL = 9
# use to send patches, always empty for released version:
-TOPLEVEL_MY_PATCH_LEVEL = .jcn1
+TOPLEVEL_MY_PATCH_LEVEL = .jcn2
sub
do_init
{
- $MAILADRESS=$ENV{MAILADRESS};
+ $MAILADDRESS=$ENV{MAILADDRESS};
@pw=(getpwuid($<));
$username=$pw[6];
source file of $PROJECT
- (c) 1997 $username <$MAILADRESS>
+ (c) 1997 $username <$MAILADDRESS>
*/\n";
print $headstr;
}
static String bin2dec_str (String bin_str);
static String bin2hex_str (String bin_str);
static String dec2bin_str (String str);
- static int bin2_i (String str);
+ static int bin2_i (String bin_str);
+ static unsigned bin2_u (String bin_str);
static String char_str (char c, int n);
static int dec2_i (String dec_str);
static double dec2_f (String dec_str);
int
String_convert::bin2_i (String bin_str)
{
- assert (bin_str.length_i() <= 4);
+ return bin2_u (bin_str);
+}
+
+unsigned
+String_convert::bin2_u (String bin_str)
+{
+ assert (bin_str.length_i() <= (int)sizeof(unsigned));
- int result_i = 0;
+ unsigned result_u = 0;
for ( int i = 0; i < bin_str.length_i(); i++)
{
- result_i <<= 8;
- result_i += (Byte)bin_str[ i ];
+ result_u <<= 8;
+ result_u += (Byte)bin_str[ i ];
}
- return result_i;
+ return result_u;
}
// breendet imp from String
}
String
-Binary_source_file::error_str( char const* pos_ch_c_l )
+Binary_source_file::error_str( char const* pos_ch_c_l ) const
{
assert( this );
if ( !in_b( pos_ch_c_l ) )
}
int
-Binary_source_file::line_i( char const* pos_ch_c_l )
+Binary_source_file::line_i( char const* pos_ch_c_l ) const
{
if ( !in_b( pos_ch_c_l ) )
return 0;
Binary_source_file( String& filename_str );
virtual ~Binary_source_file();
- virtual String error_str( char const* pos_ch_c_l );
- virtual int line_i( char const* pos_ch_c_l );
+ virtual String error_str( char const* pos_ch_c_l ) const;
+ virtual int line_i( char const* pos_ch_c_l ) const;
};
#endif // BINARY_SOURCE_FILE_HH //
class Sources
{
public:
+ Sources();
+
Source_file * get_file_l( String &filename );
Source_file* sourcefile_l( char const* ch_C );
void set_path(File_path*p_C);
- Sources();
void set_binary(bool);
- ~Sources();
+
private:
const File_path * path_C_;
void add( Source_file* sourcefile_p );
{
return name_str_;
}
+
Source_file::~Source_file()
{
delete istream_p_;
istream_p_ = 0;
delete storage_p_;
}
+
String
Source_file::error_str( char const* pos_ch_C )const
{
#include "source.hh"
#include "path.hh"
+Sources::Sources()
+{
+ path_C_= 0;
+ binary_b_ = false;
+}
+
+void
+Sources::set_binary(bool bo)
+{
+ binary_b_ = bo;
+}
+
void
Sources::set_path(File_path *f_C)
{
return f_p;
}
-Sources::Sources()
-{
- path_C_= 0;
- binary_b_ = false;
-}
-
void
Sources::add( Source_file* sourcefile_p )
{
return 0;
}
-Sources::~Sources()
-{}
public:
REQUESTMETHODS(Timing_req, timing);
virtual Tempo_req * tempo(){return 0; }
- Tempo_req();
};
Score::Score()
{
- header_p_ =0;
- pscore_p_=0;
+ header_p_ = 0;
+ music_p_ = 0;
+ pscore_p_ = 0;
audio_score_p_ = 0;
paper_p_ = 0;
midi_p_ = 0;
music_p_ = s.music_p_->clone();
midi_p_ = new Midi_def (*s.midi_p_);
paper_p_ = new Paper_def (*s.paper_p_);
- header_p_ = new Header(*s.header_p_);
+ header_p_ = new Header (*s.header_p_);
}
Score::~Score()
-include /dev/null $(DEPFILES)
#
localclean:
- rm -f $(outdir)/{midi-parser,midi-lexer}.*
+# obsoliet
+# rm -f $(outdir)/{midi-parser,midi-lexer}.*
localinstall: installexe
IMPORTANT
- * fix parser: either
- - parse into midi-items (merge with lily/midi-*) and pass
- these nealy up, same for track and score. look at all
- tracks a time (vertically through score), creating columns
- and mudela items in time-order (no searching for columns).
- or
- - junk lex/yacc altogether, parse on byte level, straight
- from memore, vertically through score. there might be no
- need for midi-items, here.
-
* get rid of (last few?) midi-specifics in mudela-*
* find / remove trend (tempo) of mudela columns
BUGS
- * mi2mu nonexist.midi ?
-
* output of 0 duration c'0
- * no output on certain midis
-
- * silly progress indicator upon mudela output
-
- * check for illegal track names, e.g. "Piano________ = \melodic"
-
* array memleaks(?): use Link_array / create Pointer_array?
* fix "#undef MEVENT_LIST" source tree: Array<Midi_event*>
MAJOR_VERSION = 0
MINOR_VERSION = 0
-PATCH_LEVEL = 19
+PATCH_LEVEL = 20
# use to send patches, always empty for released version:
MY_PATCH_LEVEL =
#
#ifndef MI2MU_PROTO_HH
#define MI2MU_PROTO_HH
-
+class Midi_parser;
+struct Midi_parser_info;
+class Midi_score_parser;
+class Midi_track_parser;
class Mudela_stream;
class Mudela_item;
class Mudela_key;
class Mudela_score;
class Mudela_staff;
class Mudela_voice;
-class My_midi_lexer;
-class My_midi_parser;
class Mudela_column;
#endif // MI2MU_PROTO_HH
--- /dev/null
+/*
+ midi-parser.hh -- declare Midi_parser
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+
+#ifndef MIDI_PARSER_HH
+#define MIDI_PARSER_HH
+
+// must, gcc 2.7.2{,.1} hits ico on midi-track-parser.cc:134 (@Midi_note)
+#define INLINES
+
+#ifdef INLINES
+
+#define next_byte() (inline_next_byte (__FUNCTION__))
+#define peek_byte() (inline_peek_byte (__FUNCTION__))
+#define forward_byte_L(n) (inline_forward_byte_L (__FUNCTION__, n))
+
+#else
+
+#define next_byte()\
+ ((info_l_->byte_L_ < info_l_->end_byte_L_ ?\
+ *info_l_->byte_L_++\
+ : (Byte const)exit (__FUNCTION__": unexpected EOF")));
+
+#define peek_byte()\
+ ((info_l_->byte_L_ < info_l_->end_byte_L_ ?\
+ *info_l_->byte_L_\
+ : (Byte const)exit (__FUNCTION__": unexpected EOF")));
+
+#define forward_byte_L(n) (inline_forward_byte_L (__FUNCTION__, n))
+
+#endif
+
+#include "proto.hh"
+#include "moment.hh"
+
+struct Midi_parser_info
+{
+ Midi_parser_info();
+ int division_1_i_;
+ int format_i_;
+ int tracks_i_;
+ int errorlevel_i_;
+ Byte const* byte_L_;
+ Byte const* end_byte_L_;
+ Source_file* source_l_;
+ Moment bar_mom_;
+};
+
+#include "string.hh"
+
+class Midi_parser
+{
+public:
+ Midi_parser ();
+
+ Midi_parser_info* info_l_;
+
+protected:
+// Byte const* inline_forward_byte_L (int n)
+ Byte const* inline_forward_byte_L (char const* fun, int n)
+ {
+ if (info_l_->byte_L_ + n < info_l_->end_byte_L_ )
+ {
+ Byte const* p = info_l_->byte_L_;
+ info_l_->byte_L_ += n;
+ return p;
+ }
+// exit (__FUNCTION__": unexpected EOF");
+ exit (String (fun) + ": unexpected EOF");
+ return 0;
+ }
+
+#ifdef INLINES
+// Byte inline_next_byte ()
+ Byte inline_next_byte (char const* fun)
+ {
+ if (info_l_->byte_L_ < info_l_->end_byte_L_)
+ return *info_l_->byte_L_++;
+// exit (__FUNCTION__": unexpected EOF");
+ exit (String (fun) + ": unexpected EOF");
+ return 0;
+ }
+
+// Byte inline_peek_byte ()
+ Byte inline_peek_byte (char const* fun)
+ {
+ if (info_l_->byte_L_ < info_l_->end_byte_L_)
+ return *info_l_->byte_L_;
+// exit (__FUNCTION__": unexpected EOF");
+ exit (String (fun) + ": unexpected EOF");
+ return 0;
+ }
+#endif
+
+ int get_i (int);
+ String get_str (int);
+ unsigned get_u (int);
+ int get_var_i ();
+ int exit (String);
+ void error (String);
+ String message (String);
+ void warning (String);
+};
+
+#endif // MIDI_PARSER_HH
--- /dev/null
+/*
+ midi-score-parser.hh -- declare
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+
+#ifndef MIDI_SCORE_PARSER_HH
+#define MIDI_SCORE_PARSER_HH
+
+#include "midi-parser.hh"
+#include "proto.hh"
+#include "mi2mu-proto.hh"
+#include "parray.hh"
+
+class Midi_score_parser : public Midi_parser
+{
+public:
+ Mudela_score* parse (String filename_str, Sources*);
+
+private:
+ void open (String filename_str, Sources*);
+
+ void parse_header ();
+ // why the #*&$#{%) has Link_array another behaviour than Link_list??
+ // int find_earliest_i (Link_array<Midi_track_parser*>& tracks);
+ int find_earliest_i (Link_array<Midi_track_parser>& tracks);
+ Mudela_score* parse_score ();
+};
+
+#endif // MIDI_SCORE_PARSER_HH
--- /dev/null
+/*
+ midi-track-parser.hh -- declare
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+
+#ifndef MIDI_TRACK_PARSER_HH
+#define MIDI_TRACK_PARSER_HH
+
+#include "proto.hh"
+#include "plist.hh"
+#include "moment.hh"
+#include "mi2mu-proto.hh"
+#include "midi-parser.hh"
+
+class Midi_track_parser : public Midi_parser
+{
+public:
+
+ Midi_track_parser (Midi_parser_info* info_l);
+ ~Midi_track_parser ();
+
+ Moment at_mom ();
+ Mudela_staff* parse (Mudela_column* col_l);
+
+private:
+ bool eot ();
+ void note_end (Mudela_column* col_l, int channel_i, int pitch_i, int aftertouch_i );
+ void note_end_all (Mudela_column* col_l) ;
+ void parse_delta_time ();
+ Mudela_item* parse_event (Mudela_column* col_l);
+ void parse_header ();
+
+ Moment at_mom_;
+ Byte running_byte_;
+ Link_list<Mudela_note*> open_note_l_list_;
+ Mudela_staff* mudela_staff_p_;
+ Midi_parser_info* track_info_p_;
+};
+
+#endif // MIDI_TRACK_PARSER_HH
void add_item (Mudela_item* mudela_item_p);
void add_staff (Mudela_staff* mudela_staff_p);
- Mudela_column* mudela_column_l (Moment mom);
+ Mudela_column* find_column_l (Moment mom);
+ Mudela_column* get_column_l (Moment mom);
void output (String filename_str);
void process();
void quantify_durations();
void settle_columns();
- Pointer_list<Mudela_column*> mudela_column_p_list_;
Pointer_list<Mudela_staff*> mudela_staff_p_list_;
-// Link_array<Mudela_column*> column_l_array_;
- // huh?
+ // wants Pointer_array!
+// Pointer_list<Mudela_column*> mudela_column_p_list_;
Link_array<Mudela_column> column_l_array_;
// ugh, ugh, ugh
-//
-// 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 "varray.hh"
-#include "string.hh"
-
-int yylex();
-void yyerror(const char *s);
-
-/// (midi_lexer)
-class My_midi_lexer : yyFlexLexer {
-public:
- My_midi_lexer (String& filename_str, Sources*);
- ~My_midi_lexer();
-
- int close_i();
- void error (char const* sz_l);
- char const* here_ch_C();
- static int varint2_i (String str);
- int yylex();
- Source_file* source_file_l_ ;
-
-private:
- int char_count_;
- int running_status_i_;
-
-public: // ugh
- int errorlevel_i_;
-};
-
-extern My_midi_lexer* midi_lexer_l_g;
-
-#endif // MY_MIDI_LEXER_HH
-
-//
-// 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 "mi2mu-proto.hh"
-#include "proto.hh"
-#include "plist.hh"
-#include "string.hh"
-#include "moment.hh"
-
-#include "string.hh"
-#include "moment.hh"
-
-int yyparse();
-
-/**
- An interface to the YACC midi parser.
- (midi_parser)
- */
-class My_midi_parser {
-public:
- My_midi_parser (String filename_str,Sources *);
- ~My_midi_parser();
-
- void add_score (Mudela_score* mudela_score_p);
- void error (char const* sz_l);
- int parse();
- void forward (int i);
- Moment at_mom();
- void note_begin (int channel_i, int pitch_i, int dyn_i);
- void note_end (int channel_i, int pitch_i, int aftertouch_i);
- void note_end_all();
-
- void reset();
- void set_division_4 (int division_4_i);
- void set_key (int accidentals_i, int minor_i);
- void set_meter (int num_i, int den_i, int clocks_i, int count_32_i);
- void set_tempo (int useconds_per_4_i);
-
- int bar_i_;
-
- // ugh
- int track_i_;
- String filename_str_;
- String copyright_str_;
- String instrument_str_;
- String track_name_str_;
-
- // ugh
- Mudela_key* mudela_key_p_;
- Mudela_meter* mudela_meter_p_;
- Mudela_tempo* mudela_tempo_p_;
-
- Mudela_staff* mudela_staff_l_;
- Mudela_score* mudela_score_p_;
- Mudela_column* mudela_column_l_;
-
-private:
- Link_list<Mudela_note*> open_mudela_note_l_list_;
-
- int division_1_i_;
-
- char const* defined_ch_C_;
- int fatal_error_i_;
- My_midi_lexer* midi_lexer_p_;
-};
-
-extern My_midi_parser* midi_parser_l_g;
-
-#endif // MY_MIDI_PARSER_HH
-
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include <assert.h>
#include "string-convert.hh"
#include "lgetopt.hh"
#include "path.hh"
#include "source.hh"
#include "mi2mu-global.hh"
-#include "my-midi-parser.hh"
+#include "midi-score-parser.hh"
#include "mudela-score.hh"
#include "version.hh"
+// ugh
+String filename_str_g;
+
+// ugh
+Mudela_score* mudela_score_l_g = 0;
+
Sources source;
-Sources* source_l_g = &source;
static File_path path;
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)
+ 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;
case 's':
{
int i = String_convert::dec2_i (getopt_long.optional_argument_ch_C_);
- if (!i)
+ if (!i)
{
identify();
usage();
identify();
path.add ("");
- source_l_g->set_path (&path);
+ source.set_binary (true);
+ source.set_path (&path);
char const* arg_sz = 0;
- while ( (arg_sz = getopt_long.get_next_arg()))
+ while ( (arg_sz = getopt_long.get_next_arg ()))
{
- My_midi_parser midi_parser (arg_sz, & source);
- midi_parser_l_g = &midi_parser;
+ 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;
- int error_i = midi_parser.parse();
- if (error_i)
- return error_i;
+ mudela_score_l_g = score_p;
+ score_p->process();
- if (!output_str.length_i())
+ if (!output_str.length_i ())
{
String d, dir, base, ext;
-
split_path (arg_sz, d, dir, base, ext);
-
output_str = base + ext + ".ly";
}
- assert (midi_parser.mudela_score_p_);
- midi_parser.mudela_score_p_->process();
- midi_parser.mudela_score_p_->output (output_str);
-
- midi_parser_l_g = 0;
+ score_p->output (output_str);
+ delete score_p;
}
return 0;
}
-%{//-*-Fundamental-*-
-// midi-lexer.l
-
-/*
- yes, i know that midi is not really a (n evolving?) language,
- and that using lex/yacc to parse midi is overkill, as well as
- a grand example of misuse and asking for performance loss.
-
- it is, however, quite robust, simple, and very easy to extend
- incrementally.
- */
-
-/*
- backup rules
-
- after making a change to the lexer rules, run
- flex -b <this lexer file>
- and make sure that
- lex.backup
- contains no backup states, but only the reminder
- Compressed tables always back up.
- (don-t forget to rm lex.yy.cc :-)
- */
-
-#include "string-convert.hh"
-#include "mi2mu-global.hh"
-#include "mi2mu-proto.hh"
-#include "my-midi-lexer.hh"
-#include "midi-parser.hh"
-
-#define YY_USER_ACTION char_count_ += YYLeng(); // ugh
-
-%}
-
-%option c++
-%option noyywrap
-%option nodefault
-%option debug
-%option yyclass="My_midi_lexer"
-%option stack
-
-%x data
-%x event
-%x i8
-%x u8
-%x int16
-%x int32
-%x meta_event
-%x track
-
-U8 [\x00-\xff]
-I8 {U8}
-INT16 {U8}{U8}
-BACKUP_INT16_0 {U8}
-INT32 {INT16}{INT16}
-BACKUP_INT32_0 {U8}
-BACKUP_INT32_1 {U8}{U8}
-BACKUP_INT32_2 {INT16}{U8}
-INT7_8UNSET [\x00-\x7f]
-INT7_8SET [\x80-\xff]
-VARINT {INT7_8SET}{0,3}{INT7_8UNSET}
-BACKUP_VARINT_0 {INT7_8SET}
-BACKUP_VARINT_1 {INT7_8SET}{INT7_8SET}
-BACKUP_VARINT_2 {INT7_8SET}{INT7_8SET}{INT7_8SET}
-
-HEADER MThd
-TRACK MTrk
-BACKUP_TOP_0 MT
-BACKUP_TOP_1 MTh
-BACKUP_TOP_2 MTr
-
-RUNNING_STATUS [\x00-\x5f]
-DATA_ENTRY [\x60-\x79]
-ALL_NOTES_OFF [\x7a-\x7f]
-NOTE_OFF [\x80-\x8f]
-NOTE_ON [\x90-\x9f]
-POLYPHONIC_AFTERTOUCH [\xa0-\xaf]
-CONTROLMODE_CHANGE [\xb0-\xbf]
-PROGRAM_CHANGE [\xc0-\xcf]
-CHANNEL_AFTERTOUCH [\xd0-\xdf]
-PITCHWHEEL_RANGE [\xe0-\xef]
-
-SYSEX_EVENT1 [\xf0]
-SYSEX_EVENT2 [\xf7]
-
-META_EVENT [\xff]
-
-SEQUENCE [\x00][\x02]
-YYTEXT [\x01]
-YYCOPYRIGHT [\x02]
-YYTRACK_NAME [\x03]
-YYINSTRUMENT_NAME [\x04]
-YYLYRIC [\x05]
-YYMARKER [\x06]
-YYCUE_POINT [\x07]
-
-END_OF_TRACK [\x2f][\x00]
-TEMPO [\x51][\x03]
-SMPTE_OFFSET [\x54][\x05]
-TIME [\x58][\x04]
-KEY [\x59][\x02]
-SSME [\0x7f][\x03]
-
-%%
-
-{HEADER} {
- LOGOUT(DEBUG_ver) << "lex: header" << endl;
- yy_push_state(int16);
- yy_push_state(int16);
- yy_push_state(int16);
- yy_push_state(int32);
- return HEADER;
-}
-
-{TRACK} {
- LOGOUT(DEBUG_ver) << "lex: track" << endl;
- yy_push_state(track);
- yy_push_state(int32);
- return TRACK;
-}
-{U8} {
- error(String("top level: header expected: ")
- + String_convert::bin2hex_str(String(*YYText())));
- exit(1);
-}
-{BACKUP_TOP_0} {
- error(String("top level: header expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-{BACKUP_TOP_1} {
- error(String("top level: header expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-{BACKUP_TOP_2} {
- error(String("top level: header expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<int32>{INT32} { // really signed?
- LOGOUT(DEBUG_ver) << "lex: int32" << endl;
- assert(YYLeng() == 4);
- String str((Byte const*)YYText(), YYLeng());
- yylval.i = String_convert::bin2_i(str);
- yy_pop_state();
- return INT32;
-}
-<int32>{BACKUP_INT32_0} {
- error(String("int32: int32 expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<int32>{BACKUP_INT32_1} {
- error(String("int32: int32 expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<int32>{BACKUP_INT32_2} {
- error(String("int32: int32 expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<int16>{INT16} { // really signed?
- LOGOUT(DEBUG_ver) << "lex: int16" << endl;
- assert(YYLeng() == 2);
- String str((Byte const*)YYText(), YYLeng());
- yylval.i = (short)String_convert::bin2_i(str);
- yy_pop_state();
- return INT16;
-}
-<int16>{BACKUP_INT16_0} {
- error(String("int16: int16 expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<i8>{I8} {
- LOGOUT(DEBUG_ver) << "lex: i8" << endl;
- assert(YYLeng() == 1);
-// yylval.byte = *(signed char*)YYText();
- yylval.i = *(signed char*)YYText();
- yy_pop_state();
- return I8;
-}
-<u8>{U8} {
- LOGOUT(DEBUG_ver) << "lex: u8" << endl;
- assert(YYLeng() == 1);
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- return U8;
-}
-
-<track>{VARINT} {
- String str((Byte const*)YYText(), YYLeng());
- yylval.i = My_midi_lexer::varint2_i(str);
- LOGOUT(DEBUG_ver) << String("lex: track: varint(")
- + String(yylval.i) + "): "
- + String_convert::bin2hex_str(str) << endl;
- yy_push_state(event);
- return VARINT;
-}
-<track>{U8} {
- error(String("track: illegal byte: ")
- + String_convert::bin2hex_str(String(*YYText())));
- exit(1);
-}
-<track>{BACKUP_VARINT_0}{U8} {
- error(String("track: varint expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<track>{BACKUP_VARINT_1}{U8} {
- error(String("track: varint expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<track>{BACKUP_VARINT_2}{U8} {
- error(String("track: varint expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<event>{RUNNING_STATUS} {
-// yylval.byte = *(Byte*)YYText();
-// yylval.i = *(Byte*)YYText();
- yylval.i = running_status_i_;
- LOGOUT(DEBUG_ver) << String ("lex: running status: ") + String(yylval.i) << endl;
- /*
- 'running status' rather means 'missing status'.
- we'll put the running status data back, prepend (unput)
- the running status, and try again.
- */
- yyless(0);
- unput(running_status_i_);
- return RUNNING_STATUS;
-}
-<event>{DATA_ENTRY} {
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- LOGOUT(DEBUG_ver) << String ("lex: undefined data entry: ") + String(yylval.i) << endl;
- yy_pop_state();
- yy_push_state(u8);
- return DATA_ENTRY;
-}
-<event>{ALL_NOTES_OFF} {
- LOGOUT(DEBUG_ver) << "lex: all note off" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- LOGOUT(DEBUG_ver) << String ("lex: all notes off: ") + String(yylval.i) << endl;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return ALL_NOTES_OFF;
-}
-<event>{NOTE_OFF} {
- LOGOUT(DEBUG_ver) << "lex: note off" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return NOTE_OFF;
-}
-<event>{NOTE_ON} {
- LOGOUT(DEBUG_ver) << "lex: note on" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return NOTE_ON;
-}
-<event>{POLYPHONIC_AFTERTOUCH} {
- LOGOUT(DEBUG_ver) << "lex: polyphonic aftertouch" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return POLYPHONIC_AFTERTOUCH;
-}
-<event>{CONTROLMODE_CHANGE} {
- LOGOUT(DEBUG_ver) << "lex: controlmode change" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return CONTROLMODE_CHANGE;
-}
-<event>{PROGRAM_CHANGE} {
- LOGOUT(DEBUG_ver) << "lex: program change" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- return PROGRAM_CHANGE;
-}
-<event>{CHANNEL_AFTERTOUCH} {
- LOGOUT(DEBUG_ver) << "lex: channel aftertouch" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return CHANNEL_AFTERTOUCH;
-}
-<event>{PITCHWHEEL_RANGE} {
- LOGOUT(DEBUG_ver) << "lex: pitchwheel range" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- running_status_i_ = yylval.i;
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return PITCHWHEEL_RANGE;
-}
-<event>{SYSEX_EVENT1} { // len data
- LOGOUT(DEBUG_ver) << "lex: sysex1" << endl;
- yy_pop_state();
- yy_push_state(data);
- return SYSEX_EVENT1;
-}
-<event>{SYSEX_EVENT2} { // len data
- LOGOUT(DEBUG_ver) << "lex: sysex2" << endl;
- yy_pop_state();
-// yy_push_state(u8); //?
- yy_push_state(data);
- return SYSEX_EVENT2;
-}
-<event>{META_EVENT} {
- LOGOUT(DEBUG_ver) << "lex: meta" << endl;
- yy_push_state(meta_event);
- return META_EVENT;
-}
-<event>{U8} {
- error(String("event: illegal byte: ")
- + String_convert::bin2hex_str(String(*YYText())));
- exit(1);
-}
-<meta_event>{SEQUENCE} { // ssss sequence number
- LOGOUT(DEBUG_ver) << "lex: sequence" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_push_state(int16);
- return SEQUENCE;
-}
-<meta_event>{YYTEXT} { // len data
- LOGOUT(DEBUG_ver) << "lex: text" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYTEXT;
-}
-<meta_event>{YYCOPYRIGHT} {
- LOGOUT(DEBUG_ver) << "lex: copyright" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYCOPYRIGHT;
-}
-<meta_event>{YYTRACK_NAME} {
- LOGOUT(DEBUG_ver) << "lex: track name" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYTRACK_NAME;
-}
-<meta_event>{YYINSTRUMENT_NAME} {
- LOGOUT(DEBUG_ver) << "lex: instrument name" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYINSTRUMENT_NAME;
-}
-<meta_event>{YYLYRIC} {
- LOGOUT(DEBUG_ver) << "lex: lyric" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYLYRIC;
-}
-<meta_event>{YYMARKER} {
- LOGOUT(DEBUG_ver) << "lex: marker" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYMARKER;
-}
-<meta_event>{YYCUE_POINT} {
- LOGOUT(DEBUG_ver) << "lex: cue point" << endl;
-// yylval.byte = *(Byte*)YYText();
- yylval.i = *(Byte*)YYText();
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return YYCUE_POINT;
-}
-<meta_event>{TEMPO} { // tttttt usec
- LOGOUT(DEBUG_ver) << "lex: tempo" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- yy_push_state(u8);
- return TEMPO;
-}
-<meta_event>{SMPTE_OFFSET} { // hr mn se fr ff
- LOGOUT(DEBUG_ver) << "lex: smpte offset" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- yy_push_state(u8);
- yy_push_state(u8);
- yy_push_state(u8);
- return SMPTE_OFFSET;
-}
-<meta_event>{TIME} { // nn dd cc bb
- LOGOUT(DEBUG_ver) << "lex: time" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- yy_push_state(u8);
- yy_push_state(u8);
- return TIME;
-}
-<meta_event>{KEY} { // sf mi
- LOGOUT(DEBUG_ver) << "lex: key" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_push_state(i8);
- yy_push_state(i8);
- return KEY;
-}
-<meta_event>{SSME} { // len data
- LOGOUT(DEBUG_ver) << "lex: smme" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_push_state(data);
- return SSME;
-}
-<meta_event>{END_OF_TRACK} {
- LOGOUT(DEBUG_ver) << "lex: end of track" << endl;
- yy_pop_state();
- yy_pop_state();
- yy_pop_state();
- return END_OF_TRACK;
-}
-<meta_event>{U8} {
- warning(String("meta_event: unimplemented event: ")
- + String_convert::bin2hex_str(String(*YYText()))
-// huh?
-// ,this->here_ch_C()
- );
- yy_pop_state();
- yy_pop_state();
- yy_push_state(u8);
- yy_push_state(u8);
- return U8;
-}
-
-<data>{VARINT} {
- LOGOUT(DEBUG_ver) << "lex: data" << endl;
- String str((Byte const*)YYText(), YYLeng());
- int i = My_midi_lexer::varint2_i(str);
- String* str_p = new String;
- while (i--)
- *str_p += (char)yyinput();
- yylval.str_p = str_p;
- yy_pop_state();
- return DATA;
-}
-<data>{U8} {
- error(String("data: illegal byte: ")
- + String_convert::bin2hex_str(String(*YYText())));
- exit(1);
-}
-<data>{BACKUP_VARINT_0}{U8} {
- error(String("data: varint expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<data>{BACKUP_VARINT_1}{U8} {
- error(String("data: varint expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-<data>{BACKUP_VARINT_2}{U8} {
- error(String("data: varint expected: ")
- + String_convert::bin2hex_str(String(*(YYText()))));
- exit(1);
-}
-
-<<EOF>> {
-// LOGOUT(NORMAL_ver) << "<<EOF>>";
-
- if (!close_i())
- yyterminate(); // can't move this, since it actually rets a YY_NULL
-}
-
-%%
-
--- /dev/null
+/*
+ midi-parser.cc -- implement
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+#include <assert.h>
+#include "string-convert.hh"
+#include "source-file.hh"
+#include "mi2mu-global.hh"
+#include "midi-parser.hh"
+
+Midi_parser_info::Midi_parser_info ()
+{
+ division_1_i_ = 0;
+ format_i_ = 0;
+ tracks_i_ = 0;
+ errorlevel_i_ = 0;
+ byte_L_ = 0;
+ end_byte_L_ = 0;
+}
+
+Midi_parser::Midi_parser ()
+{
+ info_l_ = 0;
+}
+
+int
+Midi_parser::exit (String str)
+{
+ error (str);
+ ::exit (1);
+ return 0;
+}
+
+void
+Midi_parser::error (String str)
+{
+ ::message (message (str));
+}
+
+int
+Midi_parser::get_i (int n)
+{
+ assert (n <= (int)sizeof(int));
+ return String_convert::bin2_i (get_str (n));
+}
+
+unsigned
+Midi_parser::get_u (int n)
+{
+ assert (n <= (int)sizeof(int));
+ return String_convert::bin2_i (get_str (n));
+}
+
+String
+Midi_parser::get_str (int n)
+{
+ assert (n > 0);
+ Byte const* p = forward_byte_L (n);
+ return String (p, n);
+}
+
+int
+Midi_parser::get_var_i ()
+{
+ int var_i = 0;
+
+ while (1)
+ {
+ Byte byte = next_byte ();
+ var_i <<= 7;
+ var_i += byte & 0x7f;
+ if (!(byte & 0x80))
+ return var_i;
+ }
+ exit ("get_var_i:");
+ return 0;
+}
+
+String
+Midi_parser::message (String str)
+{
+ return String ("mi2mu: ")
+ + info_l_->source_l_->name_str () + ": "
+ + String_convert::i2dec_str (info_l_->source_l_->line_i ((char const*)info_l_->byte_L_), 0, 0) + ": "
+ + str + "\n"
+ + info_l_->source_l_->error_str ((char const*)info_l_->byte_L_);
+}
+
+void
+Midi_parser::warning (String str)
+{
+ ::message (message (String ("warning: ") + str));
+}
-%{
-
-#include "mi2mu-proto.hh"
-#include "proto.hh"
-#include "plist.hh"
-#include "warn.hh"
-#include "mi2mu-global.hh"
-//#include "midi-parser.hh"
-#include "my-midi-parser.hh"
-#include "my-midi-lexer.hh"
-#include "duration-convert.hh"
-#include "string-convert.hh"
-#include "mudela-item.hh"
-#include "mudela-score.hh"
-#include "mudela-staff.hh"
-
-#ifndef NDEBUG
-#define YYDEBUG 1
-#endif
-
-%}
-
-%union {
- Byte byte;
- char c;
- int i;
- String* str_p;
- Mudela_item* mudela_item_p; // Voice_element* ? jup, just about :-)
- Mudela_score* mudela_score_p; // Input_score* ?
- Mudela_staff* mudela_staff_p; // Input_music* ?
-}
-
-%token HEADER TRACK
-%token SYSEX_EVENT1 SYSEX_EVENT2
-%token META_EVENT
-%token SEQUENCE
-%token END_OF_TRACK TEMPO SMPTE_OFFSET TIME KEY SSME
-
-%token<i> I8 U8 INT16 INT32 INT7_8UNSET INT7_8SET VARINT
-%token<i> RUNNING_STATUS DATA_ENTRY ALL_NOTES_OFF
-%token<i> NOTE_OFF NOTE_ON
-%token<i> POLYPHONIC_AFTERTOUCH CONTROLMODE_CHANGE PROGRAM_CHANGE
-%token<i> CHANNEL_AFTERTOUCH PITCHWHEEL_RANGE
-%token<i> YYTEXT YYCOPYRIGHT YYTRACK_NAME YYINSTRUMENT_NAME YYLYRIC YYMARKER YYCUE_POINT
-%token<str_p> DATA
-
-%type <i> varint
-%type <mudela_score_p> header mudela_score
-%type <mudela_staff_p> track
-%type <mudela_item_p> item
-%type <mudela_item_p> the_item meta_item the_meta_item text_item mudela_item sysex_item
-%type <mudela_item_p> running_status data_entry all_notes_off
-%type <mudela_item_p> note_off note_on
-%type <mudela_item_p> polyphonic_aftertouch controlmode_change program_change
-%type <mudela_item_p> channel_aftertouch pitchwheel_range
-
-%%
-
-midi: /* empty */
- | midi mudela_score {
- midi_parser_l_g->add_score ($2);
- }
- ;
-
-mudela_score:
- header {
- }
- | mudela_score track {
- $$->add_staff ($2);
- // ugh
- $2->set_tempo (midi_parser_l_g->mudela_tempo_p_->useconds_per_4_i());
- $2->set_meter (midi_parser_l_g->mudela_meter_p_->num_i(),
- midi_parser_l_g->mudela_meter_p_->den_i(),
- midi_parser_l_g->mudela_meter_p_->clocks_1_i(),
- 8);
- if (midi_parser_l_g->copyright_str_.length_i())
- $2->copyright_str_ = midi_parser_l_g->copyright_str_;
- if (midi_parser_l_g->track_name_str_.length_i())
- $2->name_str_ = midi_parser_l_g->track_name_str_;
- if (midi_parser_l_g->instrument_str_.length_i())
- $2->instrument_str_ = midi_parser_l_g->instrument_str_;
- midi_parser_l_g->reset();
- }
- ;
-
-header:
- HEADER INT32 INT16 INT16 INT16 {
- // ugh, already constructed;
- // need to have score in My_midi_parser...
-// $$ = new Mudela_score ($3, $4, $5);
- $$ = midi_parser_l_g->mudela_score_p_;
- $$->format_i_ = $3;
- $$->tracks_i_ = $4;
- $$->tempo_i_ = $5;
- midi_parser_l_g->set_division_4 ($5);
- }
- ;
-
-track:
- TRACK INT32 {
- LOGOUT (NORMAL_ver) << "\ntrack " << midi_parser_l_g->track_i_ << ": " << flush;
- $$ = new Mudela_staff (midi_parser_l_g->track_i_++,
- // silly, cause not set yet!
- midi_parser_l_g->copyright_str_,
- midi_parser_l_g->track_name_str_,
- midi_parser_l_g->instrument_str_);
- //ugh, need to know now!
- midi_parser_l_g->mudela_staff_l_ = $$;
- }
- | track item {
- if ($2) {
- $2->mudela_column_l_ = midi_parser_l_g->mudela_column_l_;
- $$->add_item ($2);
- }
- }
- ;
-
-item:
- varint the_item {
- $$ = $2;
- if ($2) {
- String str = $2->str();
- if (str.length_i())
- LOGOUT (DEBUG_ver) << str << " " << flush;
- }
- }
- ;
-
-varint:
- VARINT {
- midi_parser_l_g->forward ($1);
- }
- ;
-
-the_item:
- meta_item {
- }
- | mudela_item {
- }
- | sysex_item {
- }
- ;
-
-meta_item:
- META_EVENT the_meta_item {
- $$ = $2;
- }
- |
- META_EVENT U8 U8 U8 {
- $$ = 0;
- }
- ;
-
-the_meta_item:
- SEQUENCE INT16 {
- }
- | text_item DATA {
- Mudela_text::Type type = (Mudela_text::Type)$1;
- $$ = 0;
- switch (type)
- {
- case Mudela_text::COPYRIGHT:
- midi_parser_l_g->copyright_str_ = *$2;
- break;
- case Mudela_text::TRACK_NAME:
- midi_parser_l_g->track_name_str_ = *$2;
- break;
- case Mudela_text::INSTRUMENT_NAME:
- midi_parser_l_g->instrument_str_ = *$2;
- break;
- default:
- $$ = new Mudela_text (type, *$2);
- break;
- }
- LOGOUT (DEBUG_ver) << *$2 << endl;
- delete $2;
- }
- | END_OF_TRACK {
- $$ = 0;
- }
- | TEMPO U8 U8 U8 {
- $$ = new Mudela_tempo ( ($2 << 16) + ($3 << 8) + $4);
- LOGOUT (DEBUG_ver) << $$->str() << endl;
- midi_parser_l_g->set_tempo ( ($2 << 16) + ($3 << 8) + $4);
- }
- | SMPTE_OFFSET U8 U8 U8 U8 U8 {
- $$ = 0;
- }
- | TIME U8 U8 U8 U8 {
- $$ = new Mudela_meter ($2, $3, $4, $5);
- LOGOUT (DEBUG_ver) << $$->str() << endl;
- midi_parser_l_g->set_meter ($2, $3, $4, $5);
- }
- | KEY I8 I8 {
- $$ = new Mudela_key ($2, $3);
- midi_parser_l_g->set_key ($2, $3 );
- }
- | SSME DATA {
- $$ = new Mudela_text ((Mudela_text::Type)0, *$2);
- delete $2;
- }
- ;
-
-text_item:
- YYTEXT {
- LOGOUT (DEBUG_ver) << "\n% Text: ";
- }
- | YYCOPYRIGHT {
- LOGOUT (DEBUG_ver) << "\n% Copyright: ";
- }
- | YYTRACK_NAME {
- LOGOUT (DEBUG_ver) << "\n% Track name: ";
- }
- | YYINSTRUMENT_NAME {
- LOGOUT (DEBUG_ver) << "\n% Instrument name: ";
- }
- | YYLYRIC {
- LOGOUT (DEBUG_ver) << "\n% Lyric: ";
- }
- | YYMARKER {
- LOGOUT (DEBUG_ver) << "\n% Marker: ";
- }
- | YYCUE_POINT {
- LOGOUT (DEBUG_ver) << "\n% Cue point: ";
- }
- ;
-
-mudela_item:
- running_status {
- }
- | data_entry {
- }
- | all_notes_off {
- }
- | note_off {
- }
- | note_on {
- }
- | polyphonic_aftertouch {
- }
- | controlmode_change {
- }
- | program_change {
- }
- | channel_aftertouch {
- }
- | pitchwheel_range {
- }
- ;
-
-running_status:
- RUNNING_STATUS mudela_item {
- $$ = $2;
- }
- ;
-
-data_entry:
- DATA_ENTRY U8 {
- $$ = 0;
- }
- ;
-
-all_notes_off:
- ALL_NOTES_OFF U8 U8 {
- midi_parser_l_g->note_end_all();
- $$ = 0;
- }
- ;
-
-note_off:
- NOTE_OFF U8 U8 {
- int i = $1;
- i = i & ~0x80;
- midi_parser_l_g->note_end ($1 & ~0x80, $2, $3);
- $$ = 0;
- }
- ;
-
-note_on:
- NOTE_ON U8 U8 {
- int i = $1;
- i = i & ~0x90;
- $$ = 0;
- if ($3)
- midi_parser_l_g->note_begin ($1 & ~0x90, $2, $3);
- /*
- sss: some broken devices encode NOTE_OFF as
- NOTE_ON with zero volume
- */
- else
- midi_parser_l_g->note_end ($1 & ~0x90, $2, $3);
- }
- ;
-
-polyphonic_aftertouch:
- POLYPHONIC_AFTERTOUCH U8 U8 {
- $$ = 0;
- }
- ;
-
-controlmode_change:
- CONTROLMODE_CHANGE U8 U8 {
- $$ = 0;
- }
- ;
-
-program_change:
- PROGRAM_CHANGE U8 {
- $$ = 0;
- }
- ;
-
-channel_aftertouch:
- CHANNEL_AFTERTOUCH U8 U8 {
- $$ = 0;
- }
- ;
-
-pitchwheel_range:
- PITCHWHEEL_RANGE U8 U8 {
- $$ = 0;
- }
- ;
-
-sysex_item:
- SYSEX_EVENT1 DATA {
- $$ = 0;
- }
- | SYSEX_EVENT2 DATA { // U8 ?
- $$ = 0;
- }
- ;
--- /dev/null
+/*
+ midi-score-parser.cc -- implement
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+#include "moment.hh"
+#include "source-file.hh"
+#include "source.hh"
+#include "mi2mu-global.hh"
+#include "midi-score-parser.hh"
+#include "midi-track-parser.hh"
+#include "mudela-item.hh"
+#include "mudela-score.hh"
+
+
+void
+Midi_score_parser::open (String filename_str, Sources* sources_l)
+{
+ info_l_->source_l_ = sources_l->get_file_l (filename_str);
+ if (!info_l_->source_l_)
+ ::error ("can't find: `" + filename_str + "'");
+ info_l_->byte_L_ = (Byte const*)info_l_->source_l_->ch_C ();
+// info_l_->end_byte_L_ = info_l_->byte_L_ + info_l_->source_l_->length_i ();
+ info_l_->end_byte_L_ = info_l_->byte_L_ + info_l_->source_l_->length_i () + 1;
+}
+
+Mudela_score*
+Midi_score_parser::parse (String filename_str, Sources* sources_l)
+{
+ Midi_parser_info info;
+ info_l_ = &info;
+ open (filename_str, sources_l);
+ parse_header ();
+ return parse_score ();
+}
+
+void
+Midi_score_parser::parse_header ()
+{
+ String str = get_str (4);
+ if ( str != "MThd" )
+ exit ("MIDI header expected");
+
+ int length_i = get_i (4);
+ // is this signed?
+ if (length_i < 6)
+ exit ("Invalid header length");
+ info_l_->format_i_ = get_i (2);
+ if (info_l_->format_i_ != 0 && info_l_->format_i_ != 1)
+ exit ("Invalid midi format");
+ info_l_->tracks_i_ = get_i (2);
+ if (info_l_->tracks_i_ < 0 || info_l_->tracks_i_ > 32 )
+ exit ("Invalid number of tracks");
+ info_l_->division_1_i_ = get_i (2) * 4;
+ if (info_l_->division_1_i_ < 0)
+ exit ("Cannot handle non-metrical time");
+ forward_byte_L (length_i - 6);
+}
+
+int
+Midi_score_parser::find_earliest_i (Link_array<Midi_track_parser>& tracks)
+{
+ int earliest_i = 0;
+ Moment earliest_mom = infinity_mom;
+ for (int i = 0; i < tracks.size(); i++)
+ {
+ if ( tracks [i]->at_mom () < earliest_mom )
+ {
+ earliest_mom = tracks [i]->at_mom ();
+ earliest_i = i;
+ }
+ }
+ return earliest_i;
+}
+
+Mudela_score*
+Midi_score_parser::parse_score ()
+{
+ Mudela_meter m4 (1, 4, 0, 0);
+ Moment bar4_mom = m4.bar_mom ();
+
+ Link_array<Midi_track_parser> tracks;
+ for (int i = 0; i < info_l_->tracks_i_; i++)
+ tracks.push (new Midi_track_parser (info_l_));
+
+ int current_bar_i = 0;
+
+ Mudela_score* score_p = new Mudela_score( 1, 1, 1 );
+ while (tracks.size ())
+ {
+ int i = find_earliest_i (tracks);
+ Moment at_mom = tracks [i]->at_mom ();
+ Mudela_column* column_l = score_p->get_column_l (at_mom);
+ Mudela_staff* staff_p = tracks [i]->parse (column_l);
+ if ( staff_p )
+ {
+ score_p->add_staff (staff_p);
+ delete tracks [i];
+ tracks.del (i);
+ }
+
+ // brr, musta have some progress
+ for (int ii = 0; !info_l_->bar_mom_ && ii < tracks.size (); ii++)
+ info_l_->bar_mom_ = tracks [ii]->info_l_->bar_mom_;
+
+ int bar_i = (int) (at_mom
+ / (info_l_->bar_mom_ ? info_l_->bar_mom_ : bar4_mom)) + 1;
+ if (bar_i > current_bar_i)
+ {
+ LOGOUT (NORMAL_ver) << '[' << bar_i << ']' << flush;
+ current_bar_i = bar_i;
+ }
+ }
+ return score_p;
+}
+
--- /dev/null
+/*
+ midi-track-parser.cc -- implement
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+*/
+
+#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-staff.hh"
+
+Midi_track_parser::Midi_track_parser (Midi_parser_info* info_l)
+{
+ info_l_ = info_l;
+ at_mom_ = 0;
+ track_info_p_ = 0;
+ mudela_staff_p_ = new Mudela_staff (0, "", "", "");
+ 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;
+
+ for (PCursor<Mudela_note*> i (open_note_l_list_.top ()); i.ok (); i++)
+ {
+ if ((i->pitch_i_ == pitch_i) && (i->channel_i_ == channel_i))
+ {
+ i->end_column_l_ = col_l;
+ // LOGOUT(DEBUG_ver) << "Note: " << pitch_i;
+ // LOGOUT(DEBUG_ver) << "; " << i->mudela_column_l_->at_mom_;
+ // LOGOUT(DEBUG_ver) << ", " << i->end_column_l_->at_mom_ << "\n";
+ i.remove_p();
+ return;
+ }
+ }
+ warning (String ("junking note-end event: ")
+ + " channel = " + String_convert::i2dec_str (channel_i, 0, ' ')
+ + ", pitch = " + String_convert::i2dec_str (pitch_i, 0, ' '));
+}
+
+void
+Midi_track_parser::note_end_all (Mudela_column* col_l)
+{
+ // find
+ for (PCursor<Mudela_note*> i (open_note_l_list_.top ()); i.ok (); i++)
+ {
+ i->end_column_l_ = col_l;
+ i.remove_p();
+ // ugh
+ if (!i.ok())
+ break;
+ }
+}
+
+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;
+
+ 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_.bottom ().add (p);
+ }
+ 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;
+ item_p = new Mudela_text ((Mudela_text::Type)byte, 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;
+ item_p = new Mudela_tempo ( useconds_per_4_u );
+ }
+ // 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_meter* p = new Mudela_meter ( num_i, den_i, clocks_4_i, count_32_i );
+ item_p = p;
+ info_l_->bar_mom_ = p->bar_mom ();
+ }
+ // KEY [\x59][\x02]
+ else if ((byte == 0x59) && (next == 0x02))
+ {
+ next_byte ();
+ int accidentals_i = (int)next_byte ();
+ int minor_i = (int)next_byte ();
+ item_p = new Mudela_key (accidentals_i, minor_i);
+ }
+ // 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
+ exit ("Invalid 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_;
+}
+
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include <assert.h>
#include "mi2mu-global.hh"
#include "string-convert.hh"
#include "duration-convert.hh"
}
Moment
-Mudela_item::at_mom()
+Mudela_item::at_mom ()
{
- return mudela_column_l_->at_mom();
+ return mudela_column_l_->at_mom ();
}
Moment
-Mudela_item::duration_mom()
+Mudela_item::duration_mom ()
{
return Moment (0);
}
void
Mudela_item::output (Mudela_stream& mudela_stream_r)
{
- mudela_stream_r << str() << String (" ");
+ mudela_stream_r << str () << String (" ");
}
Mudela_key::Mudela_key (int accidentals_i, int minor_i)
{
accidentals_i_ = accidentals_i;
minor_i_ = minor_i;
- if (accidentals_i >= 0)
+ if (accidentals_i >= 0)
key_i_ = ((accidentals_i % 7)[ "cgdaebf" ] - 'a' - 2) % 7;
else
key_i_ = ((-accidentals_i % 7)[ "cfbeadg" ] - 'a' - 2) % 7;
}
String
-Mudela_key::str()
+Mudela_key::str ()
{
String str = "\\key ";
- if (!minor_i_)
+ if (!minor_i_)
str += String ((char) ((key_i_ + 2) % 7 + 'A'));
else // heu, -2: should be - 1 1/2: A -> fis
str += String ((char) ((key_i_ + 2 - 2) % 7 + 'a'));
str = String ("% \"") + str
- + String('"') + "; % not supported yet\n";
+ + String ('"') + "; % not supported yet\n";
return str;
}
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))
+ if (accidental_i && (accidentals_i_ < 0))
{
accidental_i = - accidental_i;
notename_i = (notename_i + 1) % 7;
{
sync_dur_.durlog_i_ = 3 ;
sync_f_ = 1.0;
- if (count_32_i != 8)
+ if (count_32_i != 8)
warning (String ("#32 in quarter: ") + String (count_32_i));
num_i_ = num_i;
den_i_ = den_i;
}
Moment
-Mudela_meter::bar_mom()
+Mudela_meter::bar_mom ()
{
Duration d;
d.durlog_i_ = den_i_;
}
int
-Mudela_meter::clocks_1_i()
+Mudela_meter::clocks_1_i ()
{
return clocks_1_i_;
}
int
-Mudela_meter::den_i()
+Mudela_meter::den_i ()
{
return den_i_;
}
int
-Mudela_meter::num_i()
+Mudela_meter::num_i ()
{
return num_i_;
}
String
-Mudela_meter::str()
+Mudela_meter::str ()
{
String str = "\\meter "
+ String (num_i_) + "/" + String (1 << den_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 ()
+{
+// ugh
+// return Duration_convert::dur2_mom (duration ());
+ return end_column_l_->at_mom () - at_mom ();
+}
+
String
-Mudela_note::str()
+Mudela_note::str ()
{
- Duration dur = duration();
- if (dur.durlog_i_ < -10)
+ 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)
+ if (simple_plet_b_s)
return name_str + Duration_convert::dur2_str (dur) + " ";
//ugh
String str;
- if (dur.plet_b())
+ if (dur.plet_b ())
str += String ("\\plet ")
+ String_convert::i2dec_str (dur.plet_.iso_i_, 0, 0)
+ "/"
tmp.set_plet (1,1);
str += Duration_convert::dur2_str (tmp);
- if (dur.plet_b())
+ if (dur.plet_b ())
str += String (" \\plet 1/1;");
return str + " ";
}
-Duration
-Mudela_note::duration()
-{
- assert (end_column_l_);
- Moment mom = end_column_l_->at_mom() - at_mom();
- return Duration_convert::mom2_dur (mom);
-}
-
-Moment
-Mudela_note::duration_mom()
-{
-// ugh
-// return Duration_convert::dur2_mom (duration());
- return end_column_l_->at_mom() - at_mom();
-}
-
Mudela_skip::Mudela_skip (Mudela_column* mudela_column_l, Moment skip_mom)
: Mudela_item (mudela_column_l)
{
}
Duration
-Mudela_skip::duration()
+Mudela_skip::duration ()
{
return Duration_convert::mom2_dur (mom_);
}
Moment
-Mudela_skip::duration_mom()
+Mudela_skip::duration_mom ()
{
- return Duration_convert::dur2_mom (duration());
+ return Duration_convert::dur2_mom (duration ());
}
String
-Mudela_skip::str()
+Mudela_skip::str ()
{
- if (!mom_)
+ if (!mom_)
return String ("");
- Duration dur = duration();
- if (dur.durlog_i_<-10)
+ Duration dur = duration ();
+ if (dur.durlog_i_<-10)
return "";
String str = "\\skip ";
}
String
-Mudela_tempo::str()
+Mudela_tempo::str ()
{
String str = "\\tempo 4=";
str += String (get_tempo_i (Moment (1, 4)));
}
int
-Mudela_tempo::useconds_per_4_i()
+Mudela_tempo::useconds_per_4_i ()
{
return useconds_per_4_i_;
}
}
String
-Mudela_text::str()
+Mudela_text::str ()
{
- if (!text_str_.length_i()
- || (text_str_.length_i() != (int)strlen (text_str_.ch_C())))
+ if (!text_str_.length_i ()
+ || (text_str_.length_i () != (int)strlen (text_str_.ch_C ())))
return "";
return "% " + text_str_ + "\n";
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include <assert.h>
#include "moment.hh"
#include "duration.hh"
#include "duration-convert.hh"
#include "mudela-staff.hh"
#include "mudela-stream.hh"
+static Mudela_key key_c (0, 0);
+static Mudela_meter meter_4 (4, 2, 24, 8);
+// useconds per 4: 250000 === 60 4 per minute
+static Mudela_tempo tempo_60 (1000000);
+
Mudela_score::Mudela_score (int format_i, int tracks_i, int tempo_i)
{
format_i_ = format_i;
tracks_i_ = tracks_i;
tempo_i_ = tempo_i;
- mudela_column_p_list_.bottom().add (new Mudela_column (this, Moment (0)));
+ column_l_array_.push (new Mudela_column (this, Moment (0)));
+ mudela_key_l_ = &key_c;
+ mudela_meter_l_ = &meter_4;
+ mudela_tempo_l_ = &tempo_60;
}
Mudela_score::~Mudela_score()
}
Mudela_column*
-Mudela_score::mudela_column_l (Moment mom)
+Mudela_score::find_column_l (Moment mom)
+{
+ // should do binary search
+ for (int i = 0; i < column_l_array_.size (); i++ )
+ if ( column_l_array_[i]->at_mom () == mom )
+ return column_l_array_[i];
+ return 0;
+}
+
+Mudela_column*
+Mudela_score::get_column_l (Moment mom)
{
- for (PCursor<Mudela_column*> i (mudela_column_p_list_); i.ok(); i++)
+ if ( column_l_array_ [column_l_array_.size() - 1]->at_mom () > mom )
{
- if (i->at_mom() > mom)
- {
- Mudela_column* p = new Mudela_column (this, mom);
- i.insert (p);
- return p;
- }
- if (i->at_mom() == mom)
- return *i;
+ error ("ugh");
+ exit (1);
}
+ if ( column_l_array_[column_l_array_.size() - 1]->at_mom () < mom )
+ column_l_array_.push (new Mudela_column (this, mom));
- Mudela_column* p = new Mudela_column (this, mom);
- mudela_column_p_list_.bottom().add (p);
- return p;
+ return column_l_array_ [column_l_array_.size() - 1];
}
void
mudela_stream << "\\paper{}\n";
- mudela_stream << "\\midi{ ";
+ mudela_stream << "\\midi{\n";
// let's not use silly 0 track
mudela_staff_p_list_.bottom()->mudela_tempo_p_->output (mudela_stream);
mudela_stream << "}\n";
LOGOUT(NORMAL_ver) << "\nProcessing..." << endl;
LOGOUT(DEBUG_ver) << "columns\n";
- for (PCursor<Mudela_column*> i (mudela_column_p_list_); i.ok(); i++)
- LOGOUT(DEBUG_ver) << "At: " << i->at_mom() << "\n";
+// for (PCursor<Mudela_column*> i (mudela_column_p_list_); i.ok(); i++)
+// LOGOUT(DEBUG_ver) << "At: " << i->at_mom() << "\n";
settle_columns();
filter_tempo();
// return;
LOGOUT(NORMAL_ver) << "\nSettling columns..." << endl;
+#if 0
assert (!column_l_array_.size());
int n = mudela_column_p_list_.size();
// huh?
// column_l_array_.set_size (n);
for (PCursor<Mudela_column*> i (mudela_column_p_list_); i.ok(); i++)
column_l_array_.push (*i);
+#endif
+
+ int n = column_l_array_.size();
int start_i = 0;
int end_i = 0;
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include <assert.h>
#include <ctype.h>
#include "moment.hh"
#include "duration-convert.hh"
#include "mudela-staff.hh"
#include "mudela-stream.hh"
#include "mudela-voice.hh"
-#include "my-midi-parser.hh"
#include "mudela-score.hh"
+extern Mudela_score* mudela_score_l_g;
Mudela_staff::Mudela_staff (int number_i, String copyright_str, String track_name_str, String instrument_str)
{
{
Moment dur = i->at_mom() - mom;
// ugh, need score
- Mudela_column* start = midi_parser_l_g->mudela_score_p_->mudela_column_l (mom);
+ Mudela_column* start = mudela_score_l_g->find_column_l (mom);
voice_p->add_item (new Mudela_skip (start, dur));
mom = i->at_mom();
}
//
// (c) 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include <assert.h>
#include <time.h>
#include <fstream.h>
#include "mi2mu-global.hh"
-#include "my-midi-parser.hh"
#include "mudela-item.hh"
#include "mudela-stream.hh"
+extern String filename_str_g;
+
static int const INDENT_i = 8;
Mudela_stream::Mudela_stream (String filename_str)
time_t t (time (0));
*os_p_ << ctime (&t);
*os_p_ << "% from input file: ";
- *os_p_ << midi_parser_l_g->filename_str_;
+ // *os_p_ << midi_parser_l_g->filename_str_;
+ // ugh
+ *os_p_ << filename_str_g;
*os_p_ << "\n\n";
// ugh
*os_p_ << "\\version \"0.1.1\";\n";
-//
-// my-midi-lexer.cc -- implement My_midi_lexer
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "string-convert.hh"
-#include "mi2mu-global.hh"
-#include "my-midi-lexer.hh"
-#include "source.hh"
-#include "source-file.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, Sources * sources)
-{
- source_file_l_ = sources->get_file_l(filename_str);
- if (!source_file_l_)
- ::error ("can't find: `" + filename_str + "'");
- switch_streams (source_file_l_->istream_l(), 0);
- errorlevel_i_ = 0;
- char_count_ = 0;
- running_status_i_ = 0;
-}
-
-My_midi_lexer::~My_midi_lexer()
-{
-// delete source_file_p_;
-}
-
-void
-My_midi_lexer::error (char const* sz_l)
-{
- if (1|| !source_file_l_)
- {
- cerr << "error at EOF: `" << sz_l << "'\n";
- }
- else
- {
-
- // FIXME
- #if 0
- char const* ch_C = here_ch_C();
- if (ch_C)
- {
- ch_C--;
- while ( (*ch_C == ' ') || (*ch_C == '\t') || (*ch_C == '\n'))
- ch_C--;
- ch_C++;
- }
- errorlevel_i_ |= 1;
- error (sz_l);
- #endif
- }
-}
-
-char const*
-My_midi_lexer::here_ch_C()
-{
- return source_file_l_->ch_C() + char_count_ ;
-}
-
-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;
-}
-
-//
-// my-midi-parser.cc -- implement My_midi_parser
-//
-// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
-#include "string-convert.hh"
-#include "duration-convert.hh"
-#include "mi2mu-global.hh"
-#include "my-midi-lexer.hh"
-#include "my-midi-parser.hh"
-#include "mudela-column.hh"
-#include "mudela-item.hh"
-#include "mudela-score.hh"
-#include "mudela-staff.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, Sources *sources_l)
-{
- filename_str_ = filename_str;
- midi_lexer_p_ = new My_midi_lexer (filename_str_,sources_l);
- midi_lexer_l_g = midi_lexer_p_; // ugh
-
- bar_i_ = 1;
-
- defined_ch_C_ = 0;
- fatal_error_i_ = 0;
-
- mudela_column_l_ = 0;
- mudela_score_p_ = new Mudela_score (1, 1, 1);
-
-
- // ugh, belong to Mudela_{score,staff}
- track_i_ = 0;
- mudela_staff_l_ = 0;
- mudela_key_p_ = 0;
- mudela_tempo_p_ = 0;
- mudela_meter_p_ = 0;
-
- reset();
-}
-
-My_midi_parser::~My_midi_parser()
-{
- midi_lexer_l_g = 0; // ugh
-
- delete midi_lexer_p_;
- delete mudela_key_p_;
- delete mudela_tempo_p_;
- delete mudela_meter_p_;
- delete mudela_score_p_;
-}
-
-void
-My_midi_parser::reset()
-{
-// open_mudela_note_l_list_.clear();
- open_mudela_note_l_list_.junk_links();
-
- // ugh
- delete mudela_key_p_;
- mudela_key_p_ = new Mudela_key (0, 0);
- // useconds per 4: 250000 === 60 4 per minute
- delete mudela_tempo_p_;
- mudela_tempo_p_ = new Mudela_tempo (1000000);
- delete mudela_meter_p_;
- mudela_meter_p_ = new Mudela_meter (4, 2, 24, 8);
-
- bar_i_ = 1;
- mudela_column_l_ = mudela_score_p_->mudela_column_l (0);
-
- // ugh
- copyright_str_ = "";
- track_name_str_ = "";
- instrument_str_ = "";
-}
-
-void
-My_midi_parser::add_score (Mudela_score* mudela_score_p)
-{
- assert (mudela_score_p_);
-
-#if 0 // ugh, already constructed
- mudela_score_p_ = mudela_score_p;
- if (!mudela_column_l_)
- mudela_column_l_ = mudela_score_p_->mudela_column_l (0);
-#endif
-
- mudela_score_p_->mudela_key_l_ = mudela_key_p_;
- mudela_score_p_->mudela_meter_l_ = mudela_meter_p_;
- mudela_score_p_->mudela_tempo_l_ = mudela_tempo_p_;
- 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)
-{
- if (!i)
- return;
-
- Duration dur;
- dur.durlog_i_ = -100;
- dur.set_ticks (i);
- Moment mom = at_mom() + Duration_convert::dur2_mom (dur);
-
- mudela_column_l_ = mudela_score_p_->mudela_column_l (mom);
-
- if (i)
- {
- int bars_i = (int) (mom / mudela_meter_p_->bar_mom());
- if (bars_i > bar_i_)
- LOGOUT(NORMAL_ver) << '[' << bar_i_ << ']' << flush;
- bar_i_ = bars_i;
- }
-}
-
-Moment
-My_midi_parser::at_mom()
-{
- assert (mudela_column_l_);
-// return mudela_column_l_ ? mudela_column_l_->at_mom() : 0;
- return mudela_column_l_->at_mom();
-}
-
-void
-My_midi_parser::note_begin (int channel_i, int pitch_i, int dyn_i)
-{
- // junk dynamics
- (void)dyn_i;
-
- Mudela_note* p = new Mudela_note (mudela_column_l_, channel_i, pitch_i, dyn_i);
-// ugh, score doesn't know about last staff yet...
-// mudela_score_p_->add_item (p);
- mudela_staff_l_->add_item (p);
- open_mudela_note_l_list_.bottom().add (p);
-}
-
-void
-My_midi_parser::note_end (int channel_i, int pitch_i, int aftertouch_i)
-{
- // junk dynamics
- (void)aftertouch_i;
-
- // find
- for (PCursor<Mudela_note*> i (open_mudela_note_l_list_); i.ok(); i++)
- {
- if ( (i->pitch_i_ == pitch_i) && (i->channel_i_ == channel_i))
- {
- i->end_column_l_ = mudela_column_l_;
- LOGOUT(DEBUG_ver) << "Note: " << pitch_i;
- LOGOUT(DEBUG_ver) << "; " << i->mudela_column_l_->at_mom_;
- LOGOUT(DEBUG_ver) << ", " << i->end_column_l_->at_mom_ << "\n";
- i.remove_p();
- return;
- }
- }
- warning (String ("junking note-end event: ")
- + " channel = " + String_convert::i2dec_str (channel_i, 0, ' ')
- + ", pitch = " + String_convert::i2dec_str (pitch_i, 0, ' '));
-}
-
-void
-My_midi_parser::note_end_all()
-{
- // find
- for (PCursor<Mudela_note*> i (open_mudela_note_l_list_); i.ok(); i++)
- {
- i->end_column_l_ = mudela_column_l_;
- i.remove_p();
- // ugh
- if (!i.ok())
- break;
- }
-}
-
-int
-My_midi_parser::parse()
-{
- LOGOUT(NORMAL_ver) << "\nParsing..." << flush;
- int i = ::yyparse();
- if (!i)
- note_end_all();
- return i;
-}
-
-void
-My_midi_parser::set_division_4 (int division_4_i)
-{
- division_1_i_ = division_4_i * 4;
- // ugh
- Duration::division_1_i_s = division_1_i_;
- if (division_4_i < 0)
- warning ("seconds iso metrical time");
-}
-
-void
-My_midi_parser::set_key (int accidentals_i, int minor_i)
-{
- delete mudela_key_p_;
- mudela_key_p_ = new Mudela_key (accidentals_i, minor_i);
-}
-
-void
-My_midi_parser::set_meter (int num_i, int den_i, int clocks_i, int count_32_i)
-{
- delete mudela_meter_p_;
- mudela_meter_p_ = new Mudela_meter (num_i, den_i, clocks_i, count_32_i);
-}
-
-void
-My_midi_parser::set_tempo (int useconds_per_4_i)
-{
- delete mudela_tempo_p_;
- mudela_tempo_p_ = new Mudela_tempo (useconds_per_4_i);
-}
-