From 32ad364ded4ad9c0fcbf59996644620d14d07473 Mon Sep 17 00:00:00 2001 From: fred Date: Wed, 5 Mar 1997 09:14:02 +0000 Subject: [PATCH] lilypond-0.0.39 --- m2m/midi-lexer.l | 400 ++++++++++++++++++++++++++++++++++++++++++ m2m/midi-parser.y | 296 +++++++++++++++++++++++++++++++ m2m/midi-score.cc | 72 ++++++++ m2m/midi-track.cc | 185 +++++++++++++++++++ m2m/midi-voice.cc | 62 +++++++ m2m/my-midi-lexer.cc | 78 ++++++++ m2m/my-midi-parser.cc | 155 ++++++++++++++++ m2m/track-column.cc | 23 +++ 8 files changed, 1271 insertions(+) create mode 100644 m2m/midi-lexer.l create mode 100644 m2m/midi-parser.y create mode 100644 m2m/midi-score.cc create mode 100644 m2m/midi-track.cc create mode 100644 m2m/midi-voice.cc create mode 100644 m2m/my-midi-lexer.cc create mode 100644 m2m/my-midi-parser.cc create mode 100644 m2m/track-column.cc diff --git a/m2m/midi-lexer.l b/m2m/midi-lexer.l new file mode 100644 index 0000000000..b5ae41046c --- /dev/null +++ b/m2m/midi-lexer.l @@ -0,0 +1,400 @@ +%{ +// midi-lexer.l + + +#include "m2m.hh" +#include "midi-parser.hh" + +%} + +%option c++ +%option noyywrap +%option nodefault +%option yylineno +%option debug +%option yyclass="My_midi_lexer" +%option stack + +%x data +%x event +%x int8 +%x int16 +%x int32 +%x meta_event +%x track + +INT8 [\x00-\xff] +INT16 {INT8}{INT8} +INT32 {INT16}{INT16} +INT7_8UNSET [\x00-\x7f] +INT7_8SET [\x80-\xff] +VARINT {INT7_8SET}{0,3}{INT7_8UNSET} + +HEADER MThd +TRACK MTrk + +XRUNNING_STATUS [\x30-\x4f] +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}/{INT32} { // using /{INT32}; longer match than {INT32} + dtor << "lex: header" << endl; + yy_push_state( int16 ); + yy_push_state( int16 ); + yy_push_state( int16 ); + yy_push_state( int32 ); + return HEADER; +} + +{TRACK}/{INT32} { // using /{INT32}; longer match than {INT32} + dtor << "lex: track" << endl; + yy_push_state( track ); + yy_push_state( int32 ); + return TRACK; +} +{INT8} { + error( String( "top level: illegal byte: " ) + + String_convert::bin2hex_str( String( *YYText() ) ) ); + exit( 1 ); +} +{INT32} { + dtor << "lex: int32" << endl; + assert( YYLeng() == 4 ); + String str( (Byte const*)YYText(), YYLeng() ); + yylval.i = String_convert::bin2_i( str ); + yy_pop_state(); + return INT32; +} +{INT16} { + dtor << "lex: int16" << endl; + assert( YYLeng() == 2 ); + String str( (Byte const*)YYText(), YYLeng() ); + yylval.i = String_convert::bin2_i( str ); + yy_pop_state(); + return INT16; +} +{INT8} { + dtor << "lex: int8" << endl; + assert( YYLeng() == 1 ); +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + return INT8; +} + +{VARINT} { + String str( (Byte const*)YYText(), YYLeng() ); + yylval.i = My_midi_lexer::varint2_i( str ); + dtor << String( "lex: track: varint(" ) + + String( yylval.i ) + "): " + + String_convert::bin2hex_str( str ) << endl; + yy_push_state( event ); + return VARINT; +} +{INT8} { + error( String( "track: illegal byte: " ) + + String_convert::bin2hex_str( String( *YYText() ) ) ); + exit( 1 ); +} +{RUNNING_STATUS} { +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + dtor << String ( "lex: running status: " ) + String( yylval.i ) << endl; + yy_pop_state(); +// yy_push_state( int8 ); + yy_push_state( int8 ); + return RUNNING_STATUS; +} +{DATA_ENTRY} { +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + dtor << String ( "lex: undefined data entry: " ) + String( yylval.i ) << endl; + yy_pop_state(); + yy_push_state( int8 ); + return DATA_ENTRY; +} +{ALL_NOTES_OFF} { + dtor << "lex: all note off" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + dtor << String ( "lex: all notes off: " ) + String( yylval.i ) << endl; + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return ALL_NOTES_OFF; +} +{NOTE_OFF} { + dtor << "lex: note off" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return NOTE_OFF; +} +{NOTE_ON} { + dtor << "lex: note on" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return NOTE_ON; +} +{POLYPHONIC_AFTERTOUCH} { + dtor << "lex: polyphonic aftertouch" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return POLYPHONIC_AFTERTOUCH; +} +{CONTROLMODE_CHANGE} { + dtor << "lex: controlmode change" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return CONTROLMODE_CHANGE; +} +{PROGRAM_CHANGE} { + dtor << "lex: program change" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + return PROGRAM_CHANGE; +} +{CHANNEL_AFTERTOUCH} { + dtor << "lex: channel aftertouch" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return CHANNEL_AFTERTOUCH; +} +{PITCHWHEEL_RANGE} { + dtor << "lex: pitchwheel range" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return PITCHWHEEL_RANGE; +} +{SYSEX_EVENT1} { // len data + dtor << "lex: sysex1" << endl; + yy_pop_state(); + yy_push_state( data ); + return SYSEX_EVENT1; +} +{SYSEX_EVENT2} { // len data + dtor << "lex: sysex2" << endl; + yy_pop_state(); +// yy_push_state( int8 ); //? + yy_push_state( data ); + return SYSEX_EVENT2; +} +{META_EVENT} { + dtor << "lex: meta" << endl; + yy_push_state( meta_event ); + return META_EVENT; +} +{INT8} { + error( String( "event: illegal byte: " ) + + String_convert::bin2hex_str( String( *YYText() ) ) ); + exit( 1 ); +} +{SEQUENCE} { // ssss sequence number + dtor << "lex: sequence" << endl; + yy_pop_state(); + yy_pop_state(); + yy_push_state( int16 ); + return SEQUENCE; +} +{YYTEXT} { // len data + dtor << "lex: text" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_pop_state(); + yy_push_state( data ); + return YYTEXT; +} +{YYCOPYRIGHT} { + dtor << "lex: copyright" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_pop_state(); + yy_push_state( data ); + return YYCOPYRIGHT; +} +{YYTRACK_NAME} { + dtor << "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; +} +{YYINSTRUMENT_NAME} { + dtor << "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; +} +{YYLYRIC} { + dtor << "lex: lyric" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_pop_state(); + yy_push_state( data ); + return YYLYRIC; +} +{YYMARKER} { + dtor << "lex: marker" << endl; +// yylval.byte = *(Byte*)YYText(); + yylval.i = *(Byte*)YYText(); + yy_pop_state(); + yy_pop_state(); + yy_push_state( data ); + return YYMARKER; +} +{YYCUE_POINT} { + dtor << "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; +} +{TEMPO} { // tttttt usec + dtor << "lex: tempo" << endl; + yy_pop_state(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + yy_push_state( int8 ); + return TEMPO; +} +{SMPTE_OFFSET} { // hr mn se fr ff + dtor << "lex: smpte offset" << endl; + yy_pop_state(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + yy_push_state( int8 ); + yy_push_state( int8 ); + yy_push_state( int8 ); + return SMPTE_OFFSET; +} +{TIME} { // nn dd cc bb + dtor << "lex: time" << endl; + yy_pop_state(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + yy_push_state( int8 ); + yy_push_state( int8 ); + return TIME; +} +{KEY} { // sf mi + dtor << "lex: key" << endl; + yy_pop_state(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return KEY; +} +{SSME} { // len data + dtor << "lex: smme" << endl; + yy_pop_state(); + yy_pop_state(); + yy_push_state( data ); + return SSME; +} +{END_OF_TRACK} { + dtor << "lex: end of track" << endl; + yy_pop_state(); + yy_pop_state(); + yy_pop_state(); + return END_OF_TRACK; +} +{INT8} { + warning( String( "meta_event: unimplemented event: " ) + + String_convert::bin2hex_str( String( *YYText() ) ), + this->here_ch_c_l() ); + yy_pop_state(); + yy_pop_state(); + yy_push_state( int8 ); + yy_push_state( int8 ); + return INT8; +} + +{VARINT} { + dtor << "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; +} +{INT8} { + error( String( "data: illegal byte: " ) + + String_convert::bin2hex_str( String( *YYText() ) ) ); + exit( 1 ); +} + +<> { +// mtor << "<>"; + + if ( !close_i() ) + yyterminate(); // can't move this, since it actually rets a YY_NULL +} + +%% + diff --git a/m2m/midi-parser.y b/m2m/midi-parser.y new file mode 100644 index 0000000000..297b9facd8 --- /dev/null +++ b/m2m/midi-parser.y @@ -0,0 +1,296 @@ +%{ + +#include "m2m.hh" + +#ifndef NDEBUG +#define YYDEBUG 1 +#endif + +%} + +%union { + Byte byte; + char c; + int i; + String* str_p; + Request* request_p; + Midi_event* midi_event_p; // Voice_element* ? + Midi_score* midi_score_p; // Input_score* ? + Midi_track* midi_track_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 INT8 INT16 INT32 INT7_8UNSET INT7_8SET VARINT +%token RUNNING_STATUS DATA_ENTRY ALL_NOTES_OFF +%token NOTE_OFF NOTE_ON +%token POLYPHONIC_AFTERTOUCH CONTROLMODE_CHANGE PROGRAM_CHANGE +%token CHANNEL_AFTERTOUCH PITCHWHEEL_RANGE +%token YYTEXT YYCOPYRIGHT YYTRACK_NAME YYINSTRUMENT_NAME YYLYRIC YYMARKER YYCUE_POINT +%token DATA + +%type varint +%type header midi_score +%type track +%type event +%type the_event meta_event the_meta_event text_event midi_event sysex_event +%type running_status data_entry all_notes_off +%type note_off note_on +%type polyphonic_aftertouch controlmode_change program_change +%type channel_aftertouch pitchwheel_range + +%% + +midi: /* empty */ + | midi midi_score { + midi_parser_l_g->add_score( $2 ); + } + ; + +midi_score: + header { + } + | midi_score track { + $$->add_track( $2 ); + 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 { + $$ = new Midi_score( $3, $4, $5 ); + midi_parser_l_g->set_division_4( $5 ); + } + ; + +track: + TRACK INT32 { + $$ = new Midi_track( 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_ ); + } + | track event { + $$->add_event( midi_parser_l_g->mom(), $2 ); + } + ; + +event: + varint the_event { + $$ = $2; + if ( $2 ) { + String str = $2->mudela_str( false ); + if ( str.length_i() ) + dtor << str << " " << flush; + } + } + ; + +varint: + VARINT { + midi_parser_l_g->forward( $1 ); + } + ; + +the_event: + meta_event { + } + | midi_event { + } + | sysex_event { + } + ; + +meta_event: + META_EVENT the_meta_event { + $$ = $2; + } + | + META_EVENT INT8 INT8 INT8 { + $$ = 0; + } + ; + +the_meta_event: + SEQUENCE INT16 { + } + | text_event DATA { + Midi_text::Type type = (Midi_text::Type)$1; + $$ = 0; + switch ( type ) + { + case Midi_text::COPYRIGHT: + midi_parser_l_g->copyright_str_ = *$2; + break; + case Midi_text::TRACK_NAME: + midi_parser_l_g->track_name_str_ = *$2; + while ( midi_parser_l_g->track_name_str_.index_i( ' ' ) != -1 ) + *(midi_parser_l_g->track_name_str_.ch_l() + midi_parser_l_g->track_name_str_.index_i( ' ' ) ) = '_'; + break; + case Midi_text::INSTRUMENT_NAME: + midi_parser_l_g->instrument_str_ = *$2; + break; + default: + $$ = new Midi_text( type, *$2 ); + break; + } + dtor << *$2 << endl; + delete $2; + } + | END_OF_TRACK { + $$ = 0; + } + | TEMPO INT8 INT8 INT8 { + $$ = new Midi_tempo( ( $2 << 16 ) + ( $3 << 8 ) + $4 ); + dtor << $$->mudela_str( false ) << endl; + midi_parser_l_g->set_tempo( ( $2 << 16 ) + ( $3 << 8 ) + $4 ); + } + | SMPTE_OFFSET INT8 INT8 INT8 INT8 INT8 { + $$ = 0; + } + | TIME INT8 INT8 INT8 INT8 { + $$ = new Midi_time( $2, $3, $4, $5 ); + dtor << $$->mudela_str( true ) << endl; + midi_parser_l_g->set_time( $2, $3, $4, $5 ); + } + | KEY INT8 INT8 { + $$ = new Midi_key( $2, $3 ); + midi_parser_l_g->set_key( $2, $3 ); + } + | SSME DATA { + $$ = new Midi_text( (Midi_text::Type)0, *$2 ); + delete $2; + } + ; + +text_event: + YYTEXT { + dtor << "\n% Text: "; + } + | YYCOPYRIGHT { + dtor << "\n% Copyright: "; + } + | YYTRACK_NAME { + dtor << "\n% Track name: "; + } + | YYINSTRUMENT_NAME { + dtor << "\n% Instrument name: "; + } + | YYLYRIC { + dtor << "\n% Lyric: "; + } + | YYMARKER { + dtor << "\n% Marker: "; + } + | YYCUE_POINT { + dtor << "\n% Cue point: "; + } + ; + +midi_event: + 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 INT8 { //INT8 { + $$ = 0; + } + ; + +data_entry: + DATA_ENTRY INT8 { + $$ = 0; + } + ; + +all_notes_off: + ALL_NOTES_OFF INT8 INT8 { + $$ = 0; + } + ; + +note_off: + NOTE_OFF INT8 INT8 { + int i = $1; + i = i & ~0x80; + $$ = midi_parser_l_g->note_end_midi_event_p( $1 & ~0x80, $2, $3 ); + } + ; + +note_on: + NOTE_ON INT8 INT8 { + int i = $1; + i = i & ~0x90; + $$ = 0; + midi_parser_l_g->note_begin( $1 & ~0x90, $2, $3 ); + } + ; + +polyphonic_aftertouch: + POLYPHONIC_AFTERTOUCH INT8 INT8 { + $$ = 0; + } + ; + +controlmode_change: + CONTROLMODE_CHANGE INT8 INT8 { + $$ = 0; + } + ; + +program_change: + PROGRAM_CHANGE INT8 { + $$ = 0; + } + ; + +channel_aftertouch: + CHANNEL_AFTERTOUCH INT8 INT8 { + $$ = 0; + } + ; + +pitchwheel_range: + PITCHWHEEL_RANGE INT8 INT8 { + $$ = 0; + } + ; + +sysex_event: + SYSEX_EVENT1 DATA { + $$ = 0; + } + | SYSEX_EVENT2 DATA { // INT8 ? + $$ = 0; + } + ; diff --git a/m2m/midi-score.cc b/m2m/midi-score.cc new file mode 100644 index 0000000000..541cb8f0f3 --- /dev/null +++ b/m2m/midi-score.cc @@ -0,0 +1,72 @@ +// +// midi-score.cc -- implement Midi_score +// +// copyright 1997 Jan Nieuwenhuizen + +#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_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_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 i( midi_track_p_list_.top() ); i.ok(); i++ ) + i->process(); +} + diff --git a/m2m/midi-track.cc b/m2m/midi-track.cc new file mode 100644 index 0000000000..6c18f7a150 --- /dev/null +++ b/m2m/midi-track.cc @@ -0,0 +1,185 @@ +// +// midi-track.cc -- implement Midi_track +// +// copyright 1997 Jan Nieuwenhuizen + +#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& open_voices_r, Moment mom ) +{ + for ( PCursor 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 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_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 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 begin_mom(); + return begin_mom; +} + +Moment +Midi_track::next_end_mom( Moment now_mom ) +{ + Moment end_mom = Midi_track::end_mom(); + for ( PCursor i( midi_voice_p_list_.top() ); i.ok(); i++ ) + if ( i->end_mom() > now_mom ) + end_mom = end_mom end_mom(); + return end_mom; +} + +void +Midi_track::process() +{ + for ( PCursor 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 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 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 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& open_voices_r, Moment mom ) +{ + for ( PCursor 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 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; +} + diff --git a/m2m/midi-voice.cc b/m2m/midi-voice.cc new file mode 100644 index 0000000000..0d5b4b446c --- /dev/null +++ b/m2m/midi-voice.cc @@ -0,0 +1,62 @@ +// +// midi-voice.cc -- implement midi_voice +// +// copyright 1997 Jan Nieuwenhuizen + +#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 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 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; +} + diff --git a/m2m/my-midi-lexer.cc b/m2m/my-midi-lexer.cc new file mode 100644 index 0000000000..22ebe75372 --- /dev/null +++ b/m2m/my-midi-lexer.cc @@ -0,0 +1,78 @@ +// +// my-midi-lexer.cc -- implement My_midi_lexer +// +// copyright 1997 Jan Nieuwenhuizen + +#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; +} + diff --git a/m2m/my-midi-parser.cc b/m2m/my-midi-parser.cc new file mode 100644 index 0000000000..ff0f44935e --- /dev/null +++ b/m2m/my-midi-parser.cc @@ -0,0 +1,155 @@ +// +// my-midi-parser.cc -- implement My_midi_parser +// +// copyright 1997 Jan Nieuwenhuizen + +#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 ); +} + diff --git a/m2m/track-column.cc b/m2m/track-column.cc new file mode 100644 index 0000000000..783206fb93 --- /dev/null +++ b/m2m/track-column.cc @@ -0,0 +1,23 @@ +// +// track-column.cc -- implement Track_column +// +// copyright 1997 Jan Nieuwenhuizen + +#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_; +} -- 2.39.5