From 5d9f9a9c6ef58ed7c6ed2311f2bc4d75b8722469 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Thu, 6 Mar 1997 19:16:55 +0100 Subject: [PATCH] partial: 0.0.39-1.jcn --- lib/binary-source-file.cc | 64 +++++ lib/duration.cc | 247 ++++++++++++++++++ {hdr => lib/include}/binary-source-file.hh | 0 lib/include/duration.hh | 114 ++++++++ {hdr => lib/include}/source-file.hh | 0 {hdr => lib/include}/source.hh | 0 lily/include/lyric-item.hh | 19 ++ .../include/lyric-staff.hh | 0 {hdr => lily/include}/midi-def.hh | 0 lily/include/midi-item.hh | 108 ++++++++ lily/include/midi-stream.hh | 32 +++ lily/lyric-walker.cc | 39 +++ lily/midi-def.cc | 64 +++++ lily/midi-item.cc | 228 ++++++++++++++++ lily/midi-stream.cc | 90 +++++++ m2m/include/lily-stream.hh | 35 +++ m2m/include/m2m.hh | 57 ++++ m2m/include/midi-event.hh | 95 +++++++ m2m/include/midi-global.hh | 34 +++ m2m/include/midi-main.hh | 12 + m2m/include/midi-score.hh | 28 ++ m2m/include/midi-track.hh | 38 +++ m2m/include/midi-voice.hh | 26 ++ {hdr => m2m/include}/my-midi-lexer.hh | 0 m2m/include/my-midi-parser.hh | 62 +++++ m2m/include/track-column.hh | 23 ++ m2m/lily-stream.cc | 122 +++++++++ m2m/midi-event.cc | 214 +++++++++++++++ m2m/midi-main.cc | 191 ++++++++++++++ m2m/midi-score.cc | 72 +++++ m2m/midi-template.cc | 26 ++ 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 ++ 36 files changed, 2543 insertions(+) create mode 100644 lib/binary-source-file.cc create mode 100644 lib/duration.cc rename {hdr => lib/include}/binary-source-file.hh (100%) create mode 100644 lib/include/duration.hh rename {hdr => lib/include}/source-file.hh (100%) rename {hdr => lib/include}/source.hh (100%) create mode 100644 lily/include/lyric-item.hh rename hdr/lyricstaff.hh => lily/include/lyric-staff.hh (100%) rename {hdr => lily/include}/midi-def.hh (100%) create mode 100644 lily/include/midi-item.hh create mode 100644 lily/include/midi-stream.hh create mode 100644 lily/lyric-walker.cc create mode 100644 lily/midi-def.cc create mode 100644 lily/midi-item.cc create mode 100644 lily/midi-stream.cc create mode 100644 m2m/include/lily-stream.hh create mode 100644 m2m/include/m2m.hh create mode 100644 m2m/include/midi-event.hh create mode 100644 m2m/include/midi-global.hh create mode 100644 m2m/include/midi-main.hh create mode 100644 m2m/include/midi-score.hh create mode 100644 m2m/include/midi-track.hh create mode 100644 m2m/include/midi-voice.hh rename {hdr => m2m/include}/my-midi-lexer.hh (100%) create mode 100644 m2m/include/my-midi-parser.hh create mode 100644 m2m/include/track-column.hh create mode 100644 m2m/lily-stream.cc create mode 100644 m2m/midi-event.cc create mode 100644 m2m/midi-main.cc create mode 100644 m2m/midi-score.cc create mode 100644 m2m/midi-template.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/lib/binary-source-file.cc b/lib/binary-source-file.cc new file mode 100644 index 0000000000..34f6645de6 --- /dev/null +++ b/lib/binary-source-file.cc @@ -0,0 +1,64 @@ +/* + binary-source-file.cc -- implement Binary_source_file + + source file of the LilyPond music typesetter + + (c) 1997 Jan Nieuwenhuizen +*/ + + +#include // INT_MAX +#include + +#include "proto.hh" +#include "plist.hh" +#include "string.hh" +#include "debug.hh" +#include "source-file.hh" +#include "binary-source-file.hh" +#include "string-convert.hh" + +Binary_source_file::Binary_source_file( String& filename_str ) + : Source_file( filename_str ) +{ +} + +Binary_source_file::~Binary_source_file() +{ +} + +String +Binary_source_file::error_str( char const* pos_ch_c_l ) +{ + assert( this ); + if ( !in_b( pos_ch_c_l ) ) + return ""; + + char const* begin_ch_c_l = pos_ch_c_l - 8 >? ch_c_l(); + char const* end_ch_c_l = pos_ch_c_l + 7 + +// split into 4? + +#include "proto.hh" +#include "plist.hh" +#include "string.hh" +#include "source-file.hh" +#include "source.hh" +#include "moment.hh" +#include "duration.hh" +#include "debug.hh" //ugh + +Duration::Duration( int type_i, int dots_i = 0, Plet* plet_l ) +{ + type_i_ = type_i; + dots_i_ = dots_i; + plet_p_ = 0; + set_plet( plet_l ); +} + +Duration::Duration( Duration const& dur_c_r ) +{ + type_i_ = 0; + dots_i_ = 0; + plet_p_ = 0; + *this = dur_c_r; +} + +Duration::~Duration() +{ + delete plet_p_; +} + +Duration const& +Duration::operator =( Duration const& dur_c_r ) +{ + if ( &dur_c_r == this ) + return *this; + + type_i_ = dur_c_r.type_i_; + dots_i_ = dur_c_r.dots_i_; + set_plet( dur_c_r.plet_p_ ); + + return *this; +} + +void +Duration::set_plet( Plet* plet_l ) +{ + delete plet_p_; + plet_p_ = 0; + if ( plet_l ) + plet_p_ = new Plet( *plet_l ); +} + +Plet::Plet( int iso_i, int type_i ) +{ + iso_i_ = iso_i; + type_i_ = type_i; +} + +Plet::Plet( Plet const& plet_c_r ) +{ + iso_i_ = plet_c_r.iso_i_; + type_i_ = plet_c_r.type_i_; +} + +String +Duration_convert::dur2_str( Duration dur ) +{ + String str( dur.type_i_ ); + str += String( '.', dur.dots_i_ ); + if ( dur.plet_p_ ) + str += String( "*" ) + String( dur.plet_p_->iso_i_ ) + + String( "/" ) + String( dur.plet_p_->type_i_ ); + return str; +} + +int +Duration_convert::dur2_i( Duration dur, int division_1_i ) +{ + return dur2_mom( dur ) * Moment( division_1_i ); +} + +Moment +Duration_convert::dur2_mom( Duration dur ) +{ + if ( !dur.type_i_ ) + return 0; + + Moment mom = Moment( 1 , dur.type_i_ ); + + Moment delta = mom; + while ( dur.dots_i_-- ) { + delta /= 2.0; + mom += delta; + } + + return mom * plet_factor_mom( dur ); +} + +Duration +Duration_convert::mom2_dur( Moment mom ) +{ + /* this is cute, + but filling an array using Duration_iterator + might speed things up, a little + */ + Duration_iterator iter_dur; + assert( iter_dur ); + while ( iter_dur ) { + Duration lower_dur = iter_dur++; + Duration upper_dur( 0 ); + if ( iter_dur ) + upper_dur = iter_dur(); + Moment lower_mom = dur2_mom( lower_dur ); + Moment upper_mom = dur2_mom( upper_dur ); + if ( mom == lower_mom ) + return lower_dur; + if ( mom == upper_mom ) // don-t miss last (sic) + return upper_dur; + if ( ( mom >= lower_mom ) && ( mom <= upper_mom ) ) { + warning( String( "duration not exact: " ) + String( (Real)mom ) , 0 ); + if ( abs( mom - lower_mom ) < abs( mom - upper_mom ) ) + return lower_dur; + else + return upper_dur; + } + lower_dur = upper_dur; + } + return Duration( 0 ); +} + +Moment +Duration_convert::plet_factor_mom( Duration dur ) +{ + if ( !dur.plet_p_ ) + return 1; + return Moment( dur.plet_p_->iso_i_, dur.plet_p_->type_i_ ); +} + +Real +Duration_convert::sync_f( Duration dur, Moment mom ) +{ + return mom / dur2_mom( dur ); +} + +Moment +Duration_convert::i2_mom( int time_i, int division_1_i ) +{ + if ( !time_i ) + return Moment( 0 ); + + if ( division_1_i > 0 ) + return Moment( time_i, division_1_i ); + else + return Moment( -division_1_i, time_i ); +} + +Duration_iterator::Duration_iterator() +{ + cursor_dur_.type_i_ = 128; + cursor_dur_.set_plet( 0 ); +} + +Duration +Duration_iterator::operator ++(int) +{ + return forward_dur(); +} + +Duration +Duration_iterator::operator ()() +{ + return dur(); +} + +Duration_iterator::operator bool() +{ + return ok(); +} + +Duration +Duration_iterator::dur() +{ + return cursor_dur_; +} + +Duration +Duration_iterator::forward_dur() +{ + // should do smart table? guessing: + // duration wholes + // 16 0.0625 + // 32.. 0.0703 + // 8:2/3 0.0833 + // 16. 0.0938 + // 8 0.1250 + // 16.. 0.1406 + // 4:2/3 0.1667 + // 8. 0.1875 + + assert( ok() ); + + Duration dur = cursor_dur_; + + if ( !cursor_dur_.dots_i_ && !cursor_dur_.plet_p_ ) { + cursor_dur_.type_i_ *= 2; + cursor_dur_.dots_i_ = 2; + } + else if ( cursor_dur_.dots_i_ == 2 ) { + assert( !cursor_dur_.plet_p_ ); + cursor_dur_.dots_i_ = 0; + cursor_dur_.type_i_ /= 4; + cursor_dur_.set_plet( &Plet( 2, 3 ) ); + } + else if ( cursor_dur_.plet_p_ + && ( cursor_dur_.plet_p_->iso_i_ == 2 ) + && ( cursor_dur_.plet_p_->type_i_ == 3 ) ) { + assert( !cursor_dur_.dots_i_ ); + cursor_dur_.set_plet( 0 ); + cursor_dur_.type_i_ *= 2; + cursor_dur_.dots_i_ = 1; + } + else if ( cursor_dur_.dots_i_ == 1 ) { + assert( !cursor_dur_.plet_p_ ); + cursor_dur_.dots_i_ = 0; + cursor_dur_.type_i_ /= 2; + } + + // ugh + if ( no_triplets_bo_g && cursor_dur_.plet_p_ && ok() ) + forward_dur(); + + return dur; +} + +bool +Duration_iterator::ok() +{ + return ( cursor_dur_.type_i_ + && !( ( cursor_dur_.type_i_ == 1 ) && ( cursor_dur_.dots_i_ > 2 ) ) ); +} diff --git a/hdr/binary-source-file.hh b/lib/include/binary-source-file.hh similarity index 100% rename from hdr/binary-source-file.hh rename to lib/include/binary-source-file.hh diff --git a/lib/include/duration.hh b/lib/include/duration.hh new file mode 100644 index 0000000000..66bbde1ccd --- /dev/null +++ b/lib/include/duration.hh @@ -0,0 +1,114 @@ +// +// duration.hh -- declare Duration, Plet, Duration_convert Duration_iterator +// +// copyright 1997 Jan Nieuwenhuizen + +// split into 4? + +#ifndef DURATION_HH +#define DURATION_HH + +// ugh, to get me in lily lib +extern bool no_triplets_bo_g; + +/// (dur) +struct Duration { + // actually i hate it when other people use default arguments, + // because it makes you easily loose track of what-s really + // happening; in the routine-s implementation you-re not aware + // of this defaultness (who sets this stupid value?). + Duration( int type_i = 1, int dots_i = 0, Plet* plet_p = 0 ); + Duration( Duration const& dur_c_r ); + ~Duration(); + + Duration const& operator =( Duration const& dur_c_r ); + + void set_plet( Plet* plet_l ); // handiger: newt zelf + +// int i_; // balltype -> type! + int type_i_; + int dots_i_; + Plet* plet_p_; +}; + +/// (plet) +struct Plet { + Plet( int replace_i, int type_i ); + Plet( Plet const& plet_c_r ); + +// int i_; + int iso_i_; // 2/3; 2 is not duration, maar of count! + int type_i_; +}; + +/** + Duration_convert handles all conversions to -n fro Duration (dur). + That is including (integer + division) representation for MIDI, + and conversion from unexact time representation (best guess :-). + + A Moment (mom) is a Rational that holds the time fraction + compared to a whole note (before also called wholes). + + SUGGESTION: currently a moment in time is called moment too; + let-s typedef Rational When too, so that we get + When Staff_column::when(), Moment Voice_element::mom(). +*/ +struct Duration_convert { + /// Most used division in MIDI, all fine with me. + static int const division_1_c_i = 384; + + /// Return (integer, division) representation. + static int dur2_i( Duration dur, int division_1_i = division_1_c_i ); + + /// Return Moment representation (fraction of whole note). + static Moment dur2_mom( Duration dur ); + + /// Return Mudela string representation. + static String dur2_str( Duration dur ); + + /// Return Moment from (integer, division) representation. + static Moment i2_mom( int i, int division_1_i = division_1_c_i ); + + /// Return Moment (fraction of whole) representation, best guess. + static Duration mom2_dur( Moment mom ); + + /// Return plet factor (not a Moment: should use Rational?). + static Moment plet_factor_mom( Duration dur ); + + /** Return synchronisation factor for mom, so that + mom2_dur( mom / sync_f ) will return the duration dur. + */ + static Real sync_f( Duration dur, Moment mom ); +}; + +/// (iter_dur) +struct Duration_iterator { + /// start at shortest: 128:2/3 + Duration_iterator(); + + // **** what about these three here ? + /// return forward_dur(); + Duration operator ++(int); + + /// return ok() + operator bool(); + + /// return dur() + Duration operator ()(); + // **** + + /// return current dur + Duration dur(); + + /// return dur(), step to next + Duration forward_dur(); + + /// durations left? + bool ok(); + +private: + Duration cursor_dur_; +}; + +#endif // DURATION_HH + diff --git a/hdr/source-file.hh b/lib/include/source-file.hh similarity index 100% rename from hdr/source-file.hh rename to lib/include/source-file.hh diff --git a/hdr/source.hh b/lib/include/source.hh similarity index 100% rename from hdr/source.hh rename to lib/include/source.hh diff --git a/lily/include/lyric-item.hh b/lily/include/lyric-item.hh new file mode 100644 index 0000000000..a5dc27b67b --- /dev/null +++ b/lily/include/lyric-item.hh @@ -0,0 +1,19 @@ +// +// lyric-item.hh -- part of LilyPond +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef LYRIC_ITEM_HH +#define LYRIC_ITEM_HH + +#include "text-item.hh" + +struct Lyric_item : Text_item { + /* *************** */ + Lyric_item(Lyric_req* lreq_l, int voice_count_i); + virtual void do_pre_processing(); +}; + + +#endif // LYRIC_ITEM_HH // + diff --git a/hdr/lyricstaff.hh b/lily/include/lyric-staff.hh similarity index 100% rename from hdr/lyricstaff.hh rename to lily/include/lyric-staff.hh diff --git a/hdr/midi-def.hh b/lily/include/midi-def.hh similarity index 100% rename from hdr/midi-def.hh rename to lily/include/midi-def.hh diff --git a/lily/include/midi-item.hh b/lily/include/midi-item.hh new file mode 100644 index 0000000000..6f10572457 --- /dev/null +++ b/lily/include/midi-item.hh @@ -0,0 +1,108 @@ +// +// midiitem.hh -- part of LilyPond +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MIDI_ITEM_HH +#define MIDI_ITEM_HH +#include "string.hh" +#include "proto.hh" + +struct Midi_item { + /* *************** */ + static String i2varint_str( int i ); + virtual void output_midi( Midi_stream& midi_stream_r ) const; + virtual String str() const = 0; +}; + +struct Midi_key : public Midi_item { + Midi_key( int accidentals_i, int minor_i ); + + virtual String str() const; + + int accidentals_i_; + int minor_i_; +}; + +struct Midi_note : public Midi_item { + /* *************** */ + int const c0_pitch_i_c_ = 60; + Byte dynamic_byte_; + + /** + Generate a note-event on a channel pitch. + + @param #melreq_l# is the pitch. + */ + Midi_note( Melodic_req* melreq_l, int channel_i, bool on_b ); + + virtual String str() const; + + int channel_i_; + int on_b_; + int pitch_i_; +}; + +struct Midi_duration : public Midi_item { + /* *************** */ + Midi_duration( Real seconds_f ); + + virtual String str() const; + + Real seconds_f_; +}; + +struct Midi_chunk : Midi_item { + /* *************** */ + Midi_chunk(); + + void add( String str ); + void set( String header_str, String data_str, String footer_str ); + virtual String str() const; + +private: + String data_str_; + String footer_str_; + String header_str_; +}; + +struct Midi_header : Midi_chunk { + /* *************** */ + Midi_header( int format_i, int tracks_i, int clocks_per_4_i ); +}; + +struct Midi_text : Midi_item { + /* *************** */ + enum Type { + TEXT = 1, COPYRIGHT, TRACK_NAME, INSTRUMENT_NAME, LYRIC, + MARKER, CUE_POINT + }; + Midi_text( Midi_text::Type type, String text_str ); + + virtual String str() const; + + Type type_; + String text_str_; +}; + +struct Midi_tempo : Midi_item { + /* *************** */ + Midi_tempo( int per_minute_4_i ); + + virtual String str() const; + + int per_minute_4_i_; +}; + +struct Midi_track : Midi_chunk { + /* *************** */ + int number_i_; + Midi_track( int number_i ); + + void add( int delta_time_i, String event ); +// void add( Moment delta_time_moment, Midi_item& mitem_r ); + void add( Moment delta_time_moment, Midi_item* mitem_l ); +}; + +#endif // MIDI_ITEM_HH // + diff --git a/lily/include/midi-stream.hh b/lily/include/midi-stream.hh new file mode 100644 index 0000000000..2444384838 --- /dev/null +++ b/lily/include/midi-stream.hh @@ -0,0 +1,32 @@ +// +// midistream.hh -- part of LilyPond +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MIDI_STREAM_HH +#define MIDI_STREAM_HH + +#include +#include "string.hh" + +/// Midi output +struct Midi_stream { + ostream* os_p_; + String filename_str_; + int clocks_per_4_i_; + int tracks_i_; + + Midi_stream( String filename_str, int tracks_i, int clocks_per_4_i_ ); + ~Midi_stream(); + + Midi_stream& operator <<( String str ); + Midi_stream& operator <<( Midi_item const& mitem_c_r ); + Midi_stream& operator <<( int i ); + + void header(); + void open(); + +//private: +// Midi_stream(Midi_stream const&); +}; +#endif // MIDI_STREAM_HH // diff --git a/lily/lyric-walker.cc b/lily/lyric-walker.cc new file mode 100644 index 0000000000..614e258be7 --- /dev/null +++ b/lily/lyric-walker.cc @@ -0,0 +1,39 @@ +/* + lyricwalker.cc -- implement Lyric_walker + + source file of the LilyPond music typesetter + + (c) 1997 Jan Nieuwenhuizen +*/ + +#include "musicalrequest.hh" +#include "voice.hh" +#include "pscore.hh" +#include "lyric-staff.hh" +#include "lyric-walker.hh" +#include "debug.hh" +#include "lyric-item.hh" +#include "staff-column.hh" + +void +Lyric_walker::process_requests() +{ + allow_break(); + + int req_count=0; + for (int i = 0; i < ptr()->musicalreq_l_arr_.size(); i++) { + Lyric_req * lreq_l = ptr()->musicalreq_l_arr_[i]->lreq_l(); + if (!lreq_l) + continue; + Item *lp = new Lyric_item(lreq_l,req_count++); + ptr()->typeset_musical_item( lp); + } +} + +Lyric_walker::Lyric_walker(Lyric_staff* lstaff_l) + : Staff_walker(lstaff_l, lstaff_l->pstaff_l_->pscore_l_) +{ + +} + + diff --git a/lily/midi-def.cc b/lily/midi-def.cc new file mode 100644 index 0000000000..5bc6b8fa78 --- /dev/null +++ b/lily/midi-def.cc @@ -0,0 +1,64 @@ +// +// midi-def.cc -- implement midi output +// +// source file of the LilyPond music typesetter +// +// (c) 1997 Jan Nieuwenhuizen + +#include +#include "misc.hh" +#include "midi-def.hh" +#include "debug.hh" + +// classes, alphasorted +// statics +// constructors +// destructor +// routines, alphasorted + +Midi_def::Midi_def() +{ + set_tempo( Moment( 1, 4 ), 60 ); + outfile_str_ = "lelie.midi"; +} + +Midi_def::Midi_def( Midi_def const& midi_c_r ) +{ + whole_seconds_f_ = midi_c_r.whole_seconds_f_; + outfile_str_ = midi_c_r.outfile_str_; +} + +Midi_def::~Midi_def() +{ +} + +Real +Midi_def::duration_to_seconds_f( Moment moment ) +{ + if (!moment) + return 0; + + return Moment( whole_seconds_f_ ) * moment; +} + +int +Midi_def::get_tempo_i( Moment moment ) +{ + return Moment( whole_seconds_f_ ) * Moment( 60 ) * moment; +} + +void +Midi_def::print() const +{ +#ifndef NPRINT + mtor << "Midi {4/min: " << Real( 60 ) / ( whole_seconds_f_ * 4 ); + mtor << "out: " << outfile_str_; + mtor << "}\n"; +#endif +} + +void +Midi_def::set_tempo( Moment moment, int count_per_minute_i ) +{ + whole_seconds_f_ = Moment( count_per_minute_i ) / Moment( 60 ) / moment; +} diff --git a/lily/midi-item.cc b/lily/midi-item.cc new file mode 100644 index 0000000000..51ba40d54c --- /dev/null +++ b/lily/midi-item.cc @@ -0,0 +1,228 @@ +// +// midiitem.cc +// +// source file of the LilyPond music typesetter +// +// (c) 1997 Jan Nieuwenhuizen + +#include +#include "proto.hh" +#include "plist.hh" +#include "pcol.hh" +#include "debug.hh" +#include "misc.hh" +#include "string.hh" +#include "string-convert.hh" +#include "request.hh" +#include "musicalrequest.hh" +#include "voice.hh" +#include "midi-item.hh" +#include "midi-stream.hh" + +Midi_chunk::Midi_chunk() +{ +} + +void +Midi_chunk::add( String str ) +{ + data_str_ += str; +} + +void +Midi_chunk::set( String header_str, String data_str, String footer_str ) +{ + data_str_ = data_str; + footer_str_ = footer_str; + header_str_ = header_str; +} + +String +Midi_chunk::str() const +{ + String str = header_str_; + String length_str = String_convert::i2hex_str( data_str_.length_i() + footer_str_.length_i(), 8, '0' ); + length_str = String_convert::hex2bin_str( length_str ); + str += length_str; + str += data_str_; + str += footer_str_; + return str; +} + +Midi_duration::Midi_duration( Real seconds_f ) +{ + seconds_f_ = seconds_f; +} + +String +Midi_duration::str() const +{ + return String( ""; +} + +Midi_header::Midi_header( int format_i, int tracks_i, int clocks_per_4_i ) +{ + String str; + + String format_str = String_convert::i2hex_str( format_i, 4, '0' ); + str += String_convert::hex2bin_str( format_str ); + + String tracks_str = String_convert::i2hex_str( tracks_i, 4, '0' ); + str += String_convert::hex2bin_str( tracks_str ); + + String tempo_str = String_convert::i2hex_str( clocks_per_4_i, 4, '0' ); + str += String_convert::hex2bin_str( tempo_str ); + + set( "MThd", str, "" ); +} + +String +Midi_item::i2varint_str( int i ) +{ + int buffer_i = i & 0x7f; + while ( (i >>= 7) > 0 ) { + buffer_i <<= 8; + buffer_i |= 0x80; + buffer_i += (i & 0x7f); + } + + String str; + while ( 1 ) { + str += (char)buffer_i; + if ( buffer_i & 0x80 ) + buffer_i >>= 8; + else + break; + } + return str; +} + +void +Midi_item::output_midi( Midi_stream& midi_stream_r ) const +{ + midi_stream_r << str(); +} + +Midi_key::Midi_key( int accidentals_i, int minor_i ) +{ + accidentals_i_ = accidentals_i; + minor_i_ = minor_i; +} + +String +Midi_key::str() const +{ + String str = "ff5902"; + str += String_convert::i2hex_str( accidentals_i_, 2, '0' ); + str += String_convert::i2hex_str( minor_i_, 2, '0' ); + return String_convert::hex2bin_str( str ); +} + +Midi_note::Midi_note( Melodic_req* melreq_l, int channel_i, bool on_bo ) +{ + assert(melreq_l); + pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_; + channel_i_ = channel_i; + + // poor man-s staff dynamics: + dynamic_byte_ = (melreq_l)? 0x64 - 0x10 * channel_i_:0; + on_b_ = on_bo; +} + +String +Midi_note::str() const +{ + if ( pitch_i_ != INT_MAX ) { + Byte status_byte = ( on_b_ ? 0x90 : 0x80 ) + channel_i_; + String str = String( (char)status_byte ); + str += (char)pitch_i_; + // poor man-s staff dynamics: + str += (char)dynamic_byte_; + return str; + } + return String( "" ); +} + +Midi_tempo::Midi_tempo( int per_minute_4_i ) +{ + per_minute_4_i_ = per_minute_4_i; +} + +String +Midi_tempo::str() const +{ + int useconds_per_4_i = 60 * (int)1e6 / per_minute_4_i_; + String str = "ff5103"; + str += String_convert::i2hex_str( useconds_per_4_i, 6, '0' ); + return String_convert::hex2bin_str( str ); +} + +Midi_text::Midi_text( Midi_text::Type type, String text_str ) +{ + type_ = type; + text_str_ = text_str; +} + +String +Midi_text::str() const +{ + String str = "ff" + String_convert::i2hex_str( type_, 2, '0' ); + str = String_convert::hex2bin_str( str ); + str += i2varint_str( text_str_.length_i() ); + str += text_str_; + return str; +} + +Midi_track::Midi_track( int number_i ) +{ +// 4D 54 72 6B MTrk +// 00 00 00 3B chunk length (59) +// 00 FF 58 04 04 02 18 08 time signature +// 00 FF 51 03 07 A1 20 tempo + +// FF 59 02 sf mi Key Signature +// sf = -7: 7 flats +// sf = -1: 1 flat +// sf = 0: key of C +// sf = 1: 1 sharp +// sf = 7: 7 sharps +// mi = 0: major key +// mi = 1: minor key + + number_i_ = number_i; + + char const* data_ch_c_l = "00" "ff58" "0404" "0218" "08" +// "00" "ff51" "0307" "a120" +// why a key at all, in midi? +// key: C +// "00" "ff59" "02" "00" "00" +// key: F (scsii-menuetto) +// "00" "ff59" "02" "ff" "00" + ; + + String data_str; + // only for format 0 (currently using format 1)? + data_str += String_convert::hex2bin_str( data_ch_c_l ); + + char const* footer_ch_c_l = "00" "ff2f" "00"; + String footer_str = String_convert::hex2bin_str( footer_ch_c_l ); + + set( "MTrk", data_str, footer_str ); +} + +void +Midi_track::add( int delta_time_i, String event_str ) +{ + assert(delta_time_i >= 0); + Midi_chunk::add( i2varint_str( delta_time_i ) + event_str ); +} + +void +Midi_track::add( Moment delta_time_moment, Midi_item* mitem_l ) +{ + // use convention of 384 clocks per 4 + // use Duration_convert + int delta_time_i = delta_time_moment * Moment( 384 ) / Moment( 1, 4 ); + add( delta_time_i, mitem_l->str() ); +} + diff --git a/lily/midi-stream.cc b/lily/midi-stream.cc new file mode 100644 index 0000000000..88e5eb2dc6 --- /dev/null +++ b/lily/midi-stream.cc @@ -0,0 +1,90 @@ +// +// midistream.cc +// +// source file of the LilyPond music typesetter +// +// (c) 1997 Jan Nieuwenhuizen + +#include +#include +#include "string.hh" +#include "string-convert.hh" +#include "main.hh" +#include "misc.hh" +#include "midi-item.hh" +#include "midi-stream.hh" +#include "debug.hh" + +Midi_stream::Midi_stream( String filename_str, int tracks_i, int clocks_per_4_i ) +{ + filename_str_ = filename_str; + tracks_i_ = tracks_i; + clocks_per_4_i_ = clocks_per_4_i; + os_p_ = 0; + open(); + header(); +} + +Midi_stream::~Midi_stream() +{ + delete os_p_; +} + +Midi_stream& +Midi_stream::operator <<( String str ) +{ + // still debugging... + if ( check_debug ) + str = String_convert::bin2hex_str( str ); + // string now 1.0.26-2 handles binary streaming + *os_p_ << str; + return *this; +} + +Midi_stream& +Midi_stream::operator <<( Midi_item const& mitem_c_r ) +{ + mitem_c_r.output_midi( *this ); + if ( check_debug ) + *os_p_ << "\n"; + return *this; +} + +Midi_stream& +Midi_stream::operator <<( int i ) +{ + // output binary string ourselves + *this << Midi_item::i2varint_str( i ); + return *this; +} + +void +Midi_stream::header() +{ +// *os_p_ << "% Creator: " << get_version(); +// *os_p_ << "% Automatically generated, at "; +// time_t t(time(0)); +// *os_p_ << ctime(&t); + +// 4D 54 68 64 MThd +// String str = "MThd"; +// 00 00 00 06 chunk length +// 00 01 format 1 +// 00 01 one track +// 00 60 96 per quarter-note + +// char const ch_c_l = "0000" "0006" "0001" "0001" "0060"; +// str += String_convert::hex2bin_str( ch_c_l ); +// *os_p_ << str; + +// *this << Midi_header( 1, 1, tempo_i_ ); + *this << Midi_header( 1, tracks_i_, clocks_per_4_i_ ); +} + +void +Midi_stream::open() +{ + os_p_ = new ofstream( filename_str_ ); + if ( !*os_p_ ) + error ("can't open `" + filename_str_ + "\'" ); +} diff --git a/m2m/include/lily-stream.hh b/m2m/include/lily-stream.hh new file mode 100644 index 0000000000..8c6622d324 --- /dev/null +++ b/m2m/include/lily-stream.hh @@ -0,0 +1,35 @@ +// +// lily-stream.hh -- part of LilyPond +// +// copyright 1997 Jan Nieuwenhuizen + +// 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 + diff --git a/m2m/include/m2m.hh b/m2m/include/m2m.hh new file mode 100644 index 0000000000..fd404e4349 --- /dev/null +++ b/m2m/include/m2m.hh @@ -0,0 +1,57 @@ +// +// m2m.hh -- generic m2m include file +// +// copyright 1997 Jan Nieuwenhuizen + +#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 +#include +#include +#include +#include +#include + +#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 + diff --git a/m2m/include/midi-event.hh b/m2m/include/midi-event.hh new file mode 100644 index 0000000000..faaf60e5cd --- /dev/null +++ b/m2m/include/midi-event.hh @@ -0,0 +1,95 @@ +// +// midi-event.hh -- declare midi_event +// +// copyright 1997 Jan Nieuwenhuizen + +#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 + diff --git a/m2m/include/midi-global.hh b/m2m/include/midi-global.hh new file mode 100644 index 0000000000..4d499daf0a --- /dev/null +++ b/m2m/include/midi-global.hh @@ -0,0 +1,34 @@ +// +// midi-global.hh -- declare global (sic) stuff for m2m +// +// copyright 1997 Jan Nieuwenhuizen + +#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 + diff --git a/m2m/include/midi-main.hh b/m2m/include/midi-main.hh new file mode 100644 index 0000000000..7392aec3a7 --- /dev/null +++ b/m2m/include/midi-main.hh @@ -0,0 +1,12 @@ +// +// midi-main.hh -- global (sic) m2m stuff +// +// copyright 1997 Jan Nieuwenhuizen + +#ifndef MIDI_MAIN_HH +#define MIDI_MAIN_HH + +#include "midi-global.hh" + +#endif // MIDI_MAIN_HH + diff --git a/m2m/include/midi-score.hh b/m2m/include/midi-score.hh new file mode 100644 index 0000000000..08cd69b845 --- /dev/null +++ b/m2m/include/midi-score.hh @@ -0,0 +1,28 @@ +// +// midi-score.hh -- declare midi_score +// +// copyright 1997 Jan Nieuwenhuizen + +#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_p_list_; + int format_i_; + int tracks_i_; + int tempo_i_; +}; + +#endif // MIDI_SCORE_HH + diff --git a/m2m/include/midi-track.hh b/m2m/include/midi-track.hh new file mode 100644 index 0000000000..22e110b2e5 --- /dev/null +++ b/m2m/include/midi-track.hh @@ -0,0 +1,38 @@ +// +// midi-track.hh -- declare midi_track +// +// copyright 1997 Jan Nieuwenhuizen + +#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& open_voices_r, Moment mom ); + Midi_voice* get_free_midi_voice_l( Moment mom ); + void remove_end_at( PointerList& open_voices_r, Moment mom ); + IPointerList tcol_p_list_; + IPointerList midi_voice_p_list_; + int number_i_; + +}; + +#endif // MIDI_TRACK_HH + diff --git a/m2m/include/midi-voice.hh b/m2m/include/midi-voice.hh new file mode 100644 index 0000000000..cf3df84171 --- /dev/null +++ b/m2m/include/midi-voice.hh @@ -0,0 +1,26 @@ +// +// midi-voice.hh -- declare midi_voice +// +// copyright 1997 Jan Nieuwenhuizen + +/// (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_p_list_; +}; + +#endif // MIDI_VOICE_HH + diff --git a/hdr/my-midi-lexer.hh b/m2m/include/my-midi-lexer.hh similarity index 100% rename from hdr/my-midi-lexer.hh rename to m2m/include/my-midi-lexer.hh diff --git a/m2m/include/my-midi-parser.hh b/m2m/include/my-midi-parser.hh new file mode 100644 index 0000000000..6faf128a89 --- /dev/null +++ b/m2m/include/my-midi-parser.hh @@ -0,0 +1,62 @@ +// +// my-midi-parser.hh -- declare My_midi_parser +// +// copyright 1997 Jan Nieuwenhuizen + +#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 + diff --git a/m2m/include/track-column.hh b/m2m/include/track-column.hh new file mode 100644 index 0000000000..0ed0323a97 --- /dev/null +++ b/m2m/include/track-column.hh @@ -0,0 +1,23 @@ +// +// track-column.hh -- declare Track_column +// +// copyright 1997 Jan Nieuwenhuizen + +#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_p_list_; + Moment mom_; +}; + +#endif // TRACK_COLUMN_HH + diff --git a/m2m/lily-stream.cc b/m2m/lily-stream.cc new file mode 100644 index 0000000000..71385ab5e7 --- /dev/null +++ b/m2m/lily-stream.cc @@ -0,0 +1,122 @@ +// +// lily-stream.cc +// +// source file of the LilyPond music typesetter +// +// (c) 1997 Jan Nieuwenhuizen + +// 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(); +} + diff --git a/m2m/midi-event.cc b/m2m/midi-event.cc new file mode 100644 index 0000000000..8ec23f9f95 --- /dev/null +++ b/m2m/midi-event.cc @@ -0,0 +1,214 @@ +// +// midi-event.cc -- implement Midi_event +// +// copyright 1997 Jan Nieuwenhuizen + +#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; +} + diff --git a/m2m/midi-main.cc b/m2m/midi-main.cc new file mode 100644 index 0000000000..488afc0a10 --- /dev/null +++ b/m2m/midi-main.cc @@ -0,0 +1,191 @@ +// +// midi-main.cc -- implement silly main() entry point +// should have Root class. +// +// copyright 1997 Jan Nieuwenhuizen + +#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 \n" +// "Contributors\n" + " Jan Nieuwenhuizen \n" +// " Mats Bengtsson \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; +} 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-template.cc b/m2m/midi-template.cc new file mode 100644 index 0000000000..1ffe8d2a1b --- /dev/null +++ b/m2m/midi-template.cc @@ -0,0 +1,26 @@ +// +// midi-template.cc -- implementemplate +// +// copyright 1997 Jan Nieuwenhuizen + +#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); + 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.2