configure
make
-You might want to edit Variables.make to tailor the compilation flags.
-why G++ >= 2.7? LilyPond & FlowerLib uses:
-
-=over 5
-
-=item *
-builtin bool
-
-=item *
-typeof
-
-=item *
-operator <?, operator >?
-
-=item *
-the new for-scope
-
-=item *
-class Rational (libg++)
-
-=item *
-named return values
-
-=back
+You probably want to edit Variables.make to tailor the compilation
+flags. If you're not into debugging C++, then you should go for no
+debugging and C<-O2>
=head1 AUTHORS
A: Yes.
-
Q: Why shouldn't I put all commands (\clef, \meter) inside the music?
A: You should do what you like, but at some time we will enable
finding a cute syntax (such as YYYY) isn't very hard. The complicated
issue how to adapt the internals to do XXXX. The parser is really a
simple front end to the complicated internals.
+
+Q: Why do I need g++ >= 2.7?
+
+A: By using g++ LilyPond is portable to all platforms which support
+g++ (there are quite a few). Not having to support other compilers
+saves us a *lot* of trouble. LilyPond & FlowerLib uses:
+
+=over 5
+
+=item *
+builtin bool
+
+=item *
+typeof
+
+=item *
+operator <?, operator >?
+
+=item *
+the new for-scope
+
+=item *
+class Rational (libg++)
+
+=item *
+named return values
+
+=back
+
+pl 36
+ - Jan's patches:
+ - do MIDI rests cleanly.
+ - lily/m2m: time and tempo fixed for metric timing
+Internal
+ - Midi_tempo
+ - m2m parses more midi stuff (all of bach-wtc); timing??
+ - m2m recognises some commandline options
+Examples
+ - fixed midi.ly
+
+*******
pl 35
- Register_group
Bugfix
- junked Midi_staff, Staff_column children, Midi_walker
- Midi_output
+pl 33-1
+ - m2m parses midi
+Internal
+ - Binary_source_file
+ - Source_file::error_str simplified
*******
pl33
Examples
tstream.hh voice.hh\
voiceregs.hh voicegroupregs.hh walkregs.hh
-mycc=bar.cc barreg.cc beam.cc boxes.cc break.cc calcideal.cc clefreg.cc\
+mycc=bar.cc barreg.cc beam.cc \
+ binary-source-file.cc\
+ boxes.cc break.cc calcideal.cc clefreg.cc\
clefitem.cc colhpos.cc commandrequest.cc\
complexstaff.cc complexwalker.cc \
debug.cc dimen.cc\
# m2m headers
#
mym2mhh=\
+ binary-source-file.hh\
midi-event.hh\
midi-main.hh\
midi-score.hh\
# m2m source
#
mym2mcc=\
+ binary-source-file.cc\
midi-event.cc\
midi-main.cc\
midi-score.cc\
# version info
MAJVER=0
MINVER=0
-PATCHLEVEL=35
+PATCHLEVEL=36
# CXX=g++
# turn off -pipe if linker doesn't support it
-EXTRACXXFLAGS=-pipe -Wall -W -Wmissing-prototypes -DSTRING_UTILS_INLINED
+EXTRACXXFLAGS=-pipe -Wall -W -Wmissing-prototypes -DSTRING_UTILS_INLINED -O
#
# -lefence = ElectricFence.
--- /dev/null
+/*
+ PROJECT: FlowerSoft C++ library
+ FILE : string-convert.cc
+
+--*/
+
+
+#include <assert.h>
+#include "string.hh"
+
+String
+String_convert::bin2hex_str( String bin_str )
+{
+ String str;
+ Byte const* byte_c_l = bin_str.byte_c_l();
+ for ( int i = 0; i < bin_str.length_i(); i++ ) {
+ str += (char)nibble2hex_byte( *byte_c_l >> 4 );
+ str += (char)nibble2hex_byte( *byte_c_l++ );
+ }
+ return str;
+}
+
+int
+String_convert::bin2_i( String bin_str )
+{
+ assert( bin_str.length_i() <= 4 );
+
+ int result_i = 0;
+ for ( int i = 0; i < bin_str.length_i(); i++ ) {
+ result_i <<= 8;
+ result_i += (Byte)bin_str[ i ];
+ }
+ return result_i;
+}
+
+// breendet imp from String
+int
+String_convert::dec2_i( String dec_str )
+{
+ if ( !dec_str.length_i() )
+ return 0;
+
+ long l = 0;
+ int conv = sscanf( dec_str.ch_c_l(), "%ld", &l );
+ assert( conv );
+
+ return (int)l;
+}
+
+// breendet imp from String
+double
+String_convert::dec2_f( String dec_str )
+{
+ if ( !dec_str.length_i() )
+ return 0;
+ double d = 0;
+ int conv = sscanf( dec_str.ch_c_l(), "%lf", &d );
+ assert( conv );
+ return d;
+}
+
+int
+String_convert::hex2bin_i( String hex_str, String& bin_str_r )
+{
+ if ( hex_str.length_i() % 2 )
+ hex_str = "0" + hex_str;
+
+ bin_str_r = "";
+ Byte const* byte_c_l= hex_str.byte_c_l();
+ int i = 0;
+ while ( i < hex_str.length_i() ) {
+ int high_i = hex2nibble_i( *byte_c_l++ );
+ int low_i = hex2nibble_i( *byte_c_l++ );
+ if ( high_i < 0 || low_i < 0 )
+ return 1; // illegal char
+ bin_str_r += String( (char)( high_i << 4 | low_i ), 1 );
+ i += 2;
+ }
+ return 0;
+}
+
+String
+String_convert::hex2bin_str( String hex_str )
+{
+ String str;
+// silly, asserts should alway be "on"!
+// assert( !hex2bin_i( hex_str, str ) );
+ int error_i = hex2bin_i( hex_str, str );
+ assert( !error_i );
+ return str;
+}
+
+int
+String_convert::hex2nibble_i( Byte byte )
+{
+ if ( byte >= '0' && byte <= '9' )
+ return byte - '0';
+ if ( byte >= 'A' && byte <= 'F' )
+ return byte - 'A' + 10;
+ if ( byte >= 'a' && byte <= 'f')
+ return byte - 'a' + 10;
+ return -1;
+}
+
+String
+String_convert::i2dec_str( int i, int length_i, char ch )
+{
+ char fill_ch = ch;
+ if ( fill_ch)
+ fill_ch = '0';
+
+ // ugh
+ String dec_str( i );
+
+ // ugh
+ return String( fill_ch, length_i - dec_str.length_i() ) + dec_str;
+}
+
+String
+String_convert::i2hex_str( int i, int length_i, char ch )
+{
+ String str;
+ if ( !i )
+ str = "0";
+ while ( i ) {
+ str = ( i % 16 )["0123456789abcdef"] + str;
+ i /= 16;
+ }
+ if ( str.length_i() < length_i )
+ str = String( ch, length_i - str.length_i() ) + str;
+ return str;
+}
+
+Byte
+String_convert::nibble2hex_byte( Byte byte )
+{
+ if ( ( byte & 0x0f ) <= 9 )
+ return ( byte & 0x0f ) + '0';
+ else
+ return ( byte & 0x0f ) - 10 + 'a';
+}
--- /dev/null
+/*
+ PROJECT: FlowerSoft C++ library
+ FILE : string-convert.hh
+
+*/
+
+#ifndef STRING_CONVERT_HH
+#define STRING_CONVERT_HH
+
+///
+#define functor class // :-)
+/**
+ The functor String_convert handles all conversions to/from String (some
+ time, anyway).
+ The class is quite empty from data view.
+ */
+functor String_convert {
+ static int hex2bin_i( String hex_str, String& bin_str_r );
+ static int hex2nibble_i( Byte byte );
+ static Byte nibble2hex_byte( Byte byte );
+public:
+ static String bin2dec_str( String dec_str );
+ static String bin2hex_str( String bin_str );
+ static String dec2bin_str( String str );
+ static int bin2_i( String str );
+ static int dec2_i( String dec_str );
+ static double dec2_f( String dec_str );
+ static int hex2int_i( String str );
+ static String hex2bin_str( String str );
+ static String i2hex_str( int i, int length_i, char ch );
+ static String i2dec_str( int i, int length_i, char ch );
+};
+
+#endif // __STRING_CONVERT_HH //
#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();
- ~Midi_event();
+ virtual ~Midi_event();
+
+ String mudela_str();
+
+protected:
+ String mudela_str_;
+
+private:
+};
+
+class Midi_key : public Midi_event {
+public:
+ Midi_key( int accidentals_i, int minor );
+ virtual ~Midi_key();
+
+ String notename_str( int pitch_i );
+
+private:
+ int accidentals_i_;
+ int minor_i_;
+ int key_i_;
+};
+
+class Midi_note : public Midi_event {
+public:
+// Midi_note( Midi_key* midi_key_l, Midi_tempo* midi_tempo_l, Midi_time* midi_time_l, int pitch_i, Real duration_f );
+ Midi_note( Midi_key* midi_key_l, Midi_time* midi_time_l, int clocks_per_whole_i, int pitch_i, Real duration_f );
+ virtual ~Midi_note();
+
+};
+
+class Midi_tempo : public Midi_event {
+public:
+ Midi_tempo( int useconds_per_4_i );
+ virtual ~Midi_tempo();
+
+ int get_tempo_i( Moment moment );
+
+private:
+ int useconds_per_4_i_;
+ Real seconds_per_1_f_;
+};
+
+class Midi_time : public Midi_event {
+public:
+ Midi_time( int num_i, int den_i, int clocks_i, int count_32_i );
+ virtual ~Midi_time();
+
+ String duration_str( int usecond24th_per_clock_i, Real delta_time_f );
+ int whole_clocks_i();
private:
+ int whole_clocks_i_;
+ int num_i_;
+ int den_i_;
};
#endif // MIDI_EVENT_HH
// midi-main.hh -- global (sic) m2m stuff
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-
#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;
void message( String message_str, char const* context_ch_c_l );
void warning( String message_str, char const* context_ch_c_l );
/**
Generate a note-event on a channel pitch.
- @param #melreq_l# the pitch. If null, then output a silent C
- #on_b# turn on?
+ @param #melreq_l# is the pitch.
*/
Midi_note( Melodic_req* melreq_l, int channel_i, bool on_b );
-
+
virtual String str();
int channel_i_;
struct Midi_header : Midi_chunk {
/* *************** */
- Midi_header( int format_i, int tracks_i, int tempo_i );
+ Midi_header( int format_i, int tracks_i, int clocks_per_4_i );
+};
+
+struct Midi_tempo : Midi_item {
+ /* *************** */
+ Midi_tempo( int tempo_i );
+
+ virtual String str();
+
+ int tempo_i_;
};
struct Midi_track : Midi_chunk {
Midi_stream* midi_stream_l_;
Midi_output(Score* score_l, Midi_def* );
void do_staff(Staff*st_l, int count);
+
+ Midi_def* midi_l_;
};
#endif // MIDIOUTPUT_HH
struct Midi_stream {
ostream* os_p_;
String filename_str_;
- int tempo_i_;
+ int clocks_per_4_i_;
int tracks_i_;
- Midi_stream( String filename_str, int tracks_i, int tempo_i );
+ Midi_stream( String filename_str, int tracks_i, int clocks_per_4_i_ );
~Midi_stream();
Midi_stream& operator <<( String str );
/* *************** */
void do_stop_notes(Moment);
+
+ void output_event(Midi_item&, Moment);
public:
Midi_walker(Staff*, Midi_track*);
#include "proto.hh"
#include "varray.hh"
#include "string.hh"
-// #include "plist.hh"
int yyparse();
void add_score( Midi_score* midi_score_p );
void error( char const* sz_l );
int parse();
+ void forward( Real f );
+ 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( String filename_str );
+ void set_division( int clocks_per_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 );
private:
+ Real now_f_;
+ Real step_f_;
+
+ static int const CHANNELS_i = 16;
+ static int const PITCHES_i = 128;
+ Real running_f_f_a_[ CHANNELS_i ][ PITCHES_i ];
+
Array<Midi_score*> midi_score_p_array_;
+ int clocks_per_whole_i_;
+ Midi_key* midi_key_p_;
+ Midi_tempo* midi_tempo_p_;
+ Midi_time* midi_time_p_;
+
char const* defined_ch_c_l_;
int fatal_error_i_;
My_midi_lexer* midi_lexer_p_;
struct Meter_register;
struct Midi_def;
struct Midi_duration;
+struct Midi_event;
struct Midi_header;
struct Midi_item;
+struct Midi_key;
+struct Midi_note;
struct Midi_output;
struct Midi_pitch;
struct Midi_staff;
struct Midi_stream;
+struct Midi_tempo;
+struct Midi_time;
struct Midi_track;
struct Midi_walker;
struct Mixed_qp;
/**
@return path to opened file.
*/
- Source_file( String &filename_str );
- ~Source_file();
+ // jcn: ugh! filename gets changed!, why?
+ Source_file( String& filename_str );
+ virtual ~Source_file();
+
char const* ch_c_l();
- String error_str( char const* pos_ch_c_l );
+ virtual String error_str( char const* pos_ch_c_l );
istream* istream_l();
bool in_b( char const* pos_ch_c_l );
- int line_i( char const* pos_ch_c_l );
+ off_t length_off();
+ virtual int line_i( char const* pos_ch_c_l );
String name_str();
- String file_line_no_str(const char *ch_c_l );
+ String file_line_no_str( char const* ch_c_l );
private:
void close();
default: ;
-DISTFILES=Makefile kortjakje.ly pavane.ly maartje.ly\
+DISTFILES=Makefile kortjakje.ly maartje.ly\
cadenza.ly scales.ly standchen.ly twinkle.ly\
wohltemperirt.ly\
error.ly midi.ly plet.ly\
martien.ly mlalt.ly mlvio1.ly mlvio2.ly mlcello.ly\
coriolan-alto.ly rhythm.ly \
- standchen.tex pavane.tex scsii-menuetto.tex scsii-menuetto.ly\
+ standchen.tex scsii-menuetto.tex scsii-menuetto.ly\
martien.tex
score {
staff { mstaf }
staff { bass_staf }
+ commands {
+ meter { 2 * 4}
+ }
midi {
tempo 4:120
}
- commands {
- meter { 2 * 4 }
- }
}
+++ /dev/null
-% Pavane pour une Infante d\'efunte
-% by Maurice Ravel
-%
-% Ravel deceased in 1937, so copyright on the music will pass in 2008.
-%
-% The purpose of this file is to demonstrate features of LilyPond;
-% I hope this citation isn't beyond the bounds of "fairness"
-%
-%
-% (there is an accompanying LaTeX file, pavane.tex)
-%
-
-horn =
-music {
- $
- \octave { ' }
- \key{ fis cis }
- \duration { 8 }
-
-% 1
- d2(( [)d e cis `b] |
- `a4 [`b cis] [cis `b] )`b4 |
- fis2(( [)fis g e d] |
- cis4 [d e(] [)e fis d cis] |
- `b4 [cis d(] [)d e cis `b] |
- )cis2 r2^"c\'edez" |
- r4 fis2 fis4 |
- fis2^"en mesure" (()[fis e a fis]|
- fis4-- e4-- d4-- )e4-- |
- `b2()[`b^"un peu retenu" `a( d cis]|
-% 11
- )`b [`fis^"en \'elargissant"-- `a-- `b--] cis4-- `b4--|
- `fis2 r2 |
- cis4^"1er mouvement"( d4^"tr\`es lontain" ()[d cis d e]
- \octave { }
- | a4 )gis2. |
- a4 (b4()[b a b 'cis] |
- fis4 e4 )cis2 |
- e4( fis4 () [fis e fis gis] |
- cis4 `b4())`b8 r8 r4^"tr\`es soutenu" |
-
- \meter {2 *4} r4 r4 |
- \meter {4 *4}
- 'cis4_"\dyn ppp"( 'd4 () ['d 'cis 'd 'e] |
- a4 )gis2. |
- a4 (b4()[b a b 'cis] |
- fis4 e4 )cis2 |
- e4_"\dyn pp"( fis4()[fis e fis gis] |
- cis4_"\dyn mf" `b4())`b8 r8 r4^"un peu plus lent" |
- r1 |
- r2 r4 r4 %^\fermata
-%% cut 'n paste.
- \octave { ' }
- | d2^"Reprenez le mouvement"( ([)d e cis `b] |
- `a4 [`b cis] [cis `b] )`b4 |
- fis2(( [)fis g e d] |
- cis4 [d e(] [)e fis d cis] |
- `b4 [cis d(] [)d e cis `b] |
- )cis2 r2^"c\'edez" |
- r4 fis2 fis4 |
- fis2(^"en mesure"()[fis e a fis] |
- fis4-- e4-- d4-- e4-- |
- `b2() [`b `a-. d-. cis-.] |
- )`b-. [`fis^"large" `a `b] cis4 `b4 `fis2 r2 |
-
- %% mark B
- r1^"1er mouvement"
- \duration {8}
- | r2 [c-.( e-. c-. )`a-. ]
- \octave{} |
- | [c e a ]2/3 b4-> () [b c-- e-- a--] |
- b4. b8()g2 |
- r1 |
- r2 [f a f d]
- | [f a 'c]2/3 'e4-^ () ['e f-> a-> 'c->] |
- 'e4._"sf" 'e8()'c4 r4 |
- r1 |
- \meter {2 *4}
- r4 r4-\fermata
- \meter {4 *4}
-
- \octave { ' }
- |d2(( [)d e cis `b] |
- `a4 [`b cis] [cis `b] )`b4 |
- fis2( ([)fis g e d] |
- cis4 [d e(] [)e fis d cis] |
- `b4 [cis d(] [)d e cis `b] |
- )cis2 r2^"c\'edez" |
- r4 fis2 fis4 |
- fis2(()[fis e a fis] |
- fis4-- e4-- d4-- e4--
- \octave{ }
- | b2()[b a 'd 'cis] |
- )b [fis a b ] 'cis4 b4 |
- fis2 r2 |
- r1-\fermata
- $
-}
-score {
- staff { melodic music { horn }
- }
- paper {
- output "pavane.out"
- unitspace 1.5 cm
- geometric 1.4
- width 12cm
- }
- commands {
- meter {4 *4}
- skip {39*1}
- bar "|:"
- skip {10*1}
- bar ":|"
- skip {13*1}
- bar "||"
- }
- midi { tempo 4:70 }
-}
+++ /dev/null
-\documentclass{article} %UGH
-\usepackage{a4}
-\begin{document}
-\input lilyponddefs
-\input titledefs
-\def\interscoreline{\vskip12pt}
-\title{Pavane pour une Infante d\'efunte}
-\composer{Maurice Ravel}
-\instrument{Cor en Fa}
-\maketit
-\input pavane.out
-\end{document}
output "standchen.out"
}
midi {
- tempo 4:50
+ tempo 4:80
}
}
}
paper {}
midi {
- tempo 4:80
+ tempo 4:90
}
}
--- /dev/null
+//
+// binary-source-file.cc
+//
+
+#include <limits.h> // INT_MAX
+#include <assert.h>
+
+#include "proto.hh"
+#include "plist.hh"
+#include "string.hh"
+#include "debug.hh"
+#include "sourcefile.hh"
+#include "binary-source-file.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 <? ch_c_l() + length_off();
+
+ String pre_str( (Byte const*)begin_ch_c_l, pos_ch_c_l - begin_ch_c_l );
+ pre_str = StringConversion::bin2hex_str( pre_str );
+ for ( int i = 2; i < pre_str.length_i(); i += 3 )
+ pre_str = pre_str.left( i ) + " " + pre_str.mid( i + 1, INT_MAX );
+ String post_str( (Byte const*)pos_ch_c_l, end_ch_c_l - pos_ch_c_l );
+ post_str = StringConversion::bin2hex_str( post_str );
+ for ( int i = 2; i < post_str.length_i(); i += 3 )
+ post_str = post_str.left( i ) + " " + post_str.mid( i + 1, INT_MAX );
+
+ String str = pre_str
+ + String( '\n' )
+ + String( ' ', pre_str.length_i() + 1 )
+ + post_str;
+ return str;
+}
+
+int
+Binary_source_file::line_i( char const* pos_ch_c_l )
+{
+ if ( !in_b( pos_ch_c_l ) )
+ return 0;
+
+ return pos_ch_c_l - ch_c_l();
+}
+
#include "inputfile.hh"
#include "debug.hh"
#include "sourcefile.hh"
+#include "binary-source-file.hh"
#include "source.hh"
Input_file::Input_file(String s)
sourcefile_l_ = 0;
}
else {
- Source_file* sourcefile_p = new Source_file( pf );
+ Source_file* sourcefile_p = 0;
+ // ugh, very dirty, need to go away
+ if ( ( pf.right( 3 ).lower() == "mid" ) || ( pf.right( 4 ).lower() == "midi" ) )
+ sourcefile_p = new Binary_source_file( pf );
+ else
+ sourcefile_p = new Source_file( pf );
source_l_g->add( sourcefile_p );
sourcefile_l_ = sourcefile_p;
is = sourcefile_l_->istream_l();
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include <assert.h>
#include "proto.hh"
+
+#include "plist.hh" // all for midi-main.hh
+#include "string.hh"
+#include "source.hh"
+#include "sourcefile.hh"
+#include "midi-main.hh" // *tors
+
+#include "moment.hh"
#include "midi-event.hh"
Midi_event::Midi_event()
{
}
+String
+Midi_event::mudela_str()
+{
+ return mudela_str_;
+}
+
+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;
+ mudela_str_ = String( "\\key\\" );
+ if ( !minor_i_ )
+ mudela_str_ += String( (char)( key_i_ - 2 + 'A' ) );
+ else
+ mudela_str_ += String( (char)( key_i_ - 2 + 'a' ) );
+}
+
+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--;
+ return notename_str;
+}
+
+Midi_key::~Midi_key()
+{
+}
+
+Midi_note::Midi_note( Midi_key* midi_key_l, Midi_time* midi_time_l, int clocks_per_whole_i, int pitch_i, Real delta_time_f )
+{
+ mudela_str_ = midi_key_l->notename_str( pitch_i );
+ mudela_str_ += midi_time_l->duration_str( clocks_per_whole_i, delta_time_f );
+}
+
+Midi_note::~Midi_note()
+{
+}
+
+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;
+ mudela_str_ = "\\Tempo: ";
+ mudela_str_ += String( useconds_per_4_i_ );
+ mudela_str_ += String( ": " )
+ + String( get_tempo_i( Moment( 1, 4 ) ) )
+ + String( " 4 per minute" );
+}
+
+Midi_tempo::~Midi_tempo()
+{
+}
+
+int
+Midi_tempo::get_tempo_i( Moment moment )
+{
+ return Moment( 60 ) / moment / Moment( seconds_per_1_f_ );
+}
+
+Midi_time::Midi_time( int num_i, int den_i, int clocks_i, int count_32_i )
+{
+// we should warn, at least!
+// assert( count_32_i == 8 );
+ if ( count_32_i != 8 )
+ warning( String( "#32 in quarter: " ) + String( count_32_i ), 0 );
+ num_i_ = num_i;
+ den_i_ = 2 << den_i;
+ // huh?, see midiitem.cc; reasonably for fugue1.midi
+// whole_clocks_i_ = clocks_i * 4 * 10;
+ whole_clocks_i_ = clocks_i * 4;
+// whole_clocks_i_ = clocks_i;
+ mudela_str_ = "\\Time: ";
+ mudela_str_ += String( num_i_ ) + "/" + String( den_i_ )
+ + ", " + String( whole_clocks_i_ )
+ + ": " + String( count_32_i );
+}
+
+Midi_time::~Midi_time()
+{
+}
+
+String
+Midi_time::duration_str( int clocks_per_whole_i, Real delta_time_f )
+{
+ dtor << "(" << delta_time_f;
+ String str;
+
+ Moment delta_time_moment = 1.0;
+ if ( delta_time_f ) {
+ // 288/96*.25 = .75
+ // 96/96*.25 = .25
+ // 24/96*.25 = 0.0625
+// delta_time_moment = Moment( delta_time_f ) / Moment( whole_clocks_i() );
+ if ( clocks_per_whole_i > 0 )
+ delta_time_moment = Moment( delta_time_f ) / Moment( clocks_per_whole_i );
+ else
+ delta_time_moment = Moment( -clocks_per_whole_i ) / Moment( delta_time_f );
+ }
+
+ dtor << ", " << (Real)delta_time_moment << "): ";
+
+ static Real sync_f = 1;
+ delta_time_moment = delta_time_moment / sync_f;
+
+ double dummy_f;
+ if ( ( sync_f == 1 )
+ && ( abs( modf( (Real)delta_time_moment / ( (Real)1 / 64 / 3 ), &dummy_f ) ) ) > 1e-6 ) {
+ sync_f = (Real)delta_time_moment / 0.125;
+ delta_time_moment = (Real)delta_time_moment / sync_f;
+ mtor << "\nsyncing: " << sync_f << ", "
+// << (Real)sync_f / usecond24th_per_clock_i << endl;
+ << (Real)whole_clocks_i() << endl;
+ }
+
+ static bool must_resync_bo = false;
+ if ( ( (Real)delta_time_moment / 0.125 > 16 )
+ || ( (Real)delta_time_moment / 0.125 < ( (Real)1 / 16 ) ) )
+ must_resync_bo = true;
+
+ if ( must_resync_bo ) {
+ must_resync_bo = false;
+ delta_time_moment = delta_time_moment * sync_f;
+ sync_f = (Real)delta_time_moment / 0.125;
+ delta_time_moment = (Real)delta_time_moment / sync_f;
+ mtor << "\nresyncing: " << sync_f << ", "
+// << (Real)sync_f / usecond24th_per_clock_i << endl;
+ << (Real)whole_clocks_i() << endl;
+ }
+
+ if ( !delta_time_moment )
+ return "0";
+
+ // output of modf: double
+ double duration_f = 0;
+ Real rest_f = modf( ( Moment( 1 ) / delta_time_moment ), &duration_f );
+ int dots_i = 0;
+ int plet_type_i = 0;
+ if ( rest_f ) {
+ // output of modf: double
+ double dots_f = 0;
+ Real dots_rest_f = modf( rest_f * 3, &dots_f );
+ if ( !dots_rest_f )
+ dots_i = (int)rint( dots_f );
+ else if ( abs( dots_rest_f - rint( dots_rest_f ) ) < 1e-8 )
+ dots_i = (int)rint( dots_rest_f );
+ // try 3plet
+ else if ( !modf( (Real)3 * delta_time_moment / 2, &duration_f ) )
+ plet_type_i = 3;
+ // try 6plet
+ else if ( !modf( (Real)6 * delta_time_moment / 2, &duration_f ) )
+ plet_type_i = 6;
+ else {
+// str += String( "\n*" ) + String( (int)( 1 / rest_f ) );
+ str += String( "\n*" ) + String( rest_f );
+ must_resync_bo = true;
+ }
+ }
+
+ if ( dots_i ) {
+ for ( int i = dots_i; i ; i-- )
+ delta_time_moment *= (Real)2 / 3;
+ modf( ( Moment( 1 ) / delta_time_moment ), &duration_f );
+ }
+
+ str += String( (int)( duration_f ) );
+ if ( dots_i )
+ str += String( '.', dots_i );
+ if ( plet_type_i )
+ str += String( "/" ) + String( plet_type_i );
+
+ return str;
+}
+
+int
+Midi_time::whole_clocks_i()
+{
+ return whole_clocks_i_;
+}
+
%{
// midi-lexer.l
-#include <stdio.h>
+//#include <stdio.h>
#include "string.hh"
#include "proto.hh"
+#include "midi-main.hh"
#include "my-midi-lexer.hh"
#include "midi-parser.hh"
-#ifndef MIDI_LEX_DEBUG
-#define puts( x )
-#endif
-
%}
%option c++
HEADER MThd
TRACK MTrk
-RUNNING_STATUS [\x30-\x4f]
+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]
%%
{HEADER}/{INT32} { // using /{INT32}; longer match than {INT32}
- puts( "lex: header" );
+ dtor << "lex: header" << endl;
yy_push_state( int16 );
yy_push_state( int16 );
yy_push_state( int16 );
}
{TRACK}/{INT32} { // using /{INT32}; longer match than {INT32}
- puts( "lex: track" );
+ dtor << "lex: track" << endl;
yy_push_state( track );
yy_push_state( int32 );
return TRACK;
}
-
+{INT8} {
+ error( String( "top level: illegal byte: " )
+ + StringConversion::bin2hex_str( String( *YYText() ) ) );
+ exit( 1 );
+}
<int32>{INT32} {
- puts( "lex: int32" );
+ dtor << "lex: int32" << endl;
assert( YYLeng() == 4 );
String str( (Byte const*)YYText(), YYLeng() );
yylval.i = StringConversion::bin2int_i( str );
return INT32;
}
<int16>{INT16} {
- puts( "lex: int16" );
+ dtor << "lex: int16" << endl;
assert( YYLeng() == 2 );
String str( (Byte const*)YYText(), YYLeng() );
yylval.i = StringConversion::bin2int_i( str );
return INT16;
}
<int8>{INT8} {
- puts( "lex: int8" );
+ dtor << "lex: int8" << endl;
assert( YYLeng() == 1 );
// yylval.byte = *(Byte*)YYText();
yylval.i = *(Byte*)YYText();
}
<track>{VARINT} {
- puts( "lex: track: varint" );
String str( (Byte const*)YYText(), YYLeng() );
yylval.i = My_midi_lexer::varint2int_i( str );
+ dtor << String( "lex: track: varint(" )
+ + String( yylval.i ) + "): "
+ + StringConversion::bin2hex_str( str ) << endl;
yy_push_state( event );
return VARINT;
}
-
+<track>{INT8} {
+ error( String( "track: illegal byte: " )
+ + StringConversion::bin2hex_str( String( *YYText() ) ) );
+ exit( 1 );
+}
<event>{RUNNING_STATUS} {
- yylval.byte = *(Byte*)YYText();
+// 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;
}
+<event>{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;
+}
+<event>{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;
+}
<event>{NOTE_OFF} {
- puts( "lex: note off" );
- yylval.byte = *(Byte*)YYText();
+ 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;
}
<event>{NOTE_ON} {
- puts( "lex: note on" );
- yylval.byte = *(Byte*)YYText();
+ 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;
}
+<event>{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;
+}
+<event>{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;
+}
<event>{PROGRAM_CHANGE} {
- yylval.byte = *(Byte*)YYText();
+ dtor << "lex: program change" << endl;
+// yylval.byte = *(Byte*)YYText();
+ yylval.i = *(Byte*)YYText();
yy_pop_state();
yy_push_state( int8 );
return PROGRAM_CHANGE;
}
+<event>{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;
+}
+<event>{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;
+}
+<event>{SYSEX_EVENT1} { // len data
+ dtor << "lex: sysex1" << endl;
+ yy_pop_state();
+ yy_push_state( data );
+ return SYSEX_EVENT1;
+}
+<event>{SYSEX_EVENT2} { // len data
+ dtor << "lex: sysex2" << endl;
+ yy_pop_state();
+// yy_push_state( int8 ); //?
+ yy_push_state( data );
+ return SYSEX_EVENT2;
+}
<event>{META_EVENT} {
+ dtor << "lex: meta" << endl;
yy_push_state( meta_event );
return META_EVENT;
}
-
+<event>{INT8} {
+ error( String( "event: illegal byte: " )
+ + StringConversion::bin2hex_str( String( *YYText() ) ) );
+ exit( 1 );
+}
<meta_event>{SEQUENCE} { // ssss sequence number
+ dtor << "lex: sequence" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( int16 );
return SEQUENCE;
}
<meta_event>{TEXT} { // len data
+ dtor << "lex: text" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return TEXT;
}
<meta_event>{COPYRIGHT} {
+ dtor << "lex: copyright" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return COPYRIGHT;
}
<meta_event>{TRACK_NAME} {
+ dtor << "lex: track name" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return TRACK_NAME;
}
<meta_event>{INSTRUMENT_NAME} {
+ dtor << "lex: instrument name" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return INSTRUMENT_NAME;
}
<meta_event>{LYRIC} {
+ dtor << "lex: lyric" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return LYRIC;
}
<meta_event>{MARKER} {
+ dtor << "lex: marker" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return MARKER;
}
<meta_event>{CUE_POINT} {
+ dtor << "lex: cue point" << endl;
+ yy_pop_state();
+ yy_pop_state();
yy_push_state( data );
return CUE_POINT;
}
<meta_event>{TEMPO} { // tttttt usec
- puts( "lex: tempo" );
+ dtor << "lex: tempo" << endl;
yy_pop_state();
yy_pop_state();
yy_push_state( int8 );
return TEMPO;
}
<meta_event>{SMPTE_OFFSET} { // hr mn se fr ff
+ dtor << "lex: smpte offset" << endl;
yy_pop_state();
yy_pop_state();
yy_push_state( int8 );
return SMPTE_OFFSET;
}
<meta_event>{TIME} { // nn dd cc bb
- puts( "lex: time" );
+ dtor << "lex: time" << endl;
yy_pop_state();
yy_pop_state();
yy_push_state( int8 );
return TIME;
}
<meta_event>{KEY} { // sf mi
- puts( "lex: key" );
+ dtor << "lex: key" << endl;
yy_pop_state();
yy_pop_state();
yy_push_state( int8 );
return KEY;
}
<meta_event>{SSME} { // len data
+ dtor << "lex: smme" << endl;
yy_pop_state();
yy_pop_state();
yy_push_state( data );
return SSME;
}
<meta_event>{END_OF_TRACK} {
- puts( "lex: end of track" );
+ dtor << "lex: end of track" << endl;
yy_pop_state();
yy_pop_state();
yy_pop_state();
return END_OF_TRACK;
}
<meta_event>{INT8} {
- yylval.byte = *(Byte*)YYText();
+ warning( String( "meta_event: unimplemented event: " )
+ + StringConversion::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;
}
<data>{VARINT} {
+ dtor << "lex: data" << endl;
String str( (Byte const*)YYText(), YYLeng() );
int i = My_midi_lexer::varint2int_i( str );
String* str_p = new String;
*str_p += (char)yyinput();
yylval.str_p = str_p;
yy_pop_state();
- yy_pop_state();
return DATA;
}
-
+<data>{INT8} {
+ error( String( "data: illegal byte: " )
+ + StringConversion::bin2hex_str( String( *YYText() ) ) );
+ exit( 1 );
+}
<<EOF>> {
// mtor << "<<EOF>>";
#include <iostream.h>
#include "proto.hh"
#include "plist.hh"
+#include "version.hh"
+#include "fversion.hh"
#include "string.hh"
+#include "lgetopt.hh"
#include "source.hh"
#include "sourcefile.hh"
#include "midi-main.hh"
+#include "moment.hh"
#include "midi-event.hh"
#include "midi-track.hh"
#include "my-midi-lexer.hh"
Source source;
Source* source_l_g = &source;
+Verbose level_ver = NORMAL_ver;
+
//ugh
char const* defined_ch_c_l = 0;
+// ugh, another global
String
find_file( String str )
{
void
message( String message_str, char const* context_ch_c_l )
{
- String str = "lilypond: ";
+ 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(": ");
midi_lexer_l_g->errorlevel_i_ |= 1;
}
+void
+help()
+{
+ btor <<
+ "--debug, -d be really verbose\n"
+ "--help, -h This help\n"
+ "--include, -I add to file search path.\n"
+ "--output, -o set default output\n"
+ "--quiet, -q be quiet\n"
+ "--verbose, -v be verbose\n"
+ "--warranty, -w show warranty & copyright\n"
+ ;
+}
+
+void
+identify()
+{
+ mtor << "This is m2m " << VERSIONSTR << "/FlowerLib " << FVERSIONSTR
+ << " of " << __DATE__ << " " << __TIME__ << endl;
+}
+
+void
+notice()
+{
+ mtor <<
+ "\n"
+ "M2m, translate midi to mudela.\n"
+ "Copyright (C) 1997 by\n"
+ " Han-Wen Nienhuys <hanwen@stack.nl>\n"
+// "Contributors\n"
+ " Jan Nieuwenhuizen <jan@digicash.com>\n"
+// " Mats Bengtsson <matsb@s3.kth.se>\n"
+ "\n"
+ " This program is free software; you can redistribute it and/or\n"
+ "modify it under the terms of the GNU General Public License version 2\n"
+ "as published by the Free Software Foundation.\n"
+ "\n"
+ " This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ "General Public License for more details.\n"
+ "\n"
+ " You should have received a copy (refer to the file COPYING) of the\n"
+ "GNU General Public License along with this program; if not, write to\n"
+ "the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,\n"
+ "USA.\n";
+}
+
int
main( int argc_i, char* argv_sz_a[] )
{
- if ( !argc_i )
- return 2;
- My_midi_parser midi_parser( argv_sz_a[ 1 ] );
- return midi_parser.parse();
+ long_option_init long_option_init_a[] = {
+ 0, "debug", 'd',
+ 0, "help", 'h',
+// 1, "include", 'I',
+ 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 '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;
+ error_i = midi_parser.output( output_str );
+ if ( error_i )
+ return error_i;
+ }
+ return 0;
}
#include <iostream.h>
+#include "proto.hh" // ugh, these all for midi-main.hh
+#include "plist.hh"
+#include "string.hh"
+#include "sourcefile.hh"
+#include "source.hh"
+#include "midi-main.hh" // *tors
+
#include "my-midi-lexer.hh"
#include "my-midi-parser.hh"
+#include "moment.hh"
#include "midi-event.hh"
#include "midi-track.hh"
#include "midi-score.hh"
%token END_OF_TRACK TEMPO SMPTE_OFFSET TIME KEY SSME
%token<i> INT8 INT16 INT32 INT7_8UNSET INT7_8SET VARINT
-%token<i> RUNNING_STATUS NOTE_OFF NOTE_ON PROGRAM_CHANGE
+%token<i> RUNNING_STATUS DATA_ENTRY ALL_NOTES_OFF
+%token<i> NOTE_OFF NOTE_ON
+%token<i> POLYPHONIC_AFTERTOUCH CONTROLMODE_CHANGE PROGRAM_CHANGE
+%token<i> CHANNEL_AFTERTOUCH PITCHWHEEL_RANGE
%token<str_p> DATA
+%type <i> varint
%type <midi_score_p> header midi_score
%type <midi_track_p> track
%type <midi_event_p> event
-%type <midi_event_p> the_event meta_event text_event midi_event sysex_event
-%type <midi_event_p> running_status note_off note_on program_change
+%type <midi_event_p> the_event meta_event the_meta_event text_event midi_event sysex_event
+%type <midi_event_p> running_status data_entry all_notes_off
+%type <midi_event_p> note_off note_on
+%type <midi_event_p> polyphonic_aftertouch controlmode_change program_change
+%type <midi_event_p> channel_aftertouch pitchwheel_range
%%
header:
HEADER INT32 INT16 INT16 INT16 {
$$ = new Midi_score( $3, $4, $5 );
+ midi_parser_l_g->set_division( $5 );
}
;
;
event:
- VARINT the_event {
+ varint the_event {
+ if ( $2 && $2->mudela_str().length_i() ) {
+ if ( ( $2->mudela_str()[ 0 ] >= 'a' )
+ && $2->mudela_str()[ 0 ] <= 'g' )
+ qtor << $2->mudela_str() << " ";
+ else
+ vtor << $2->mudela_str() << " ";
+ }
}
;
+varint:
+ VARINT {
+ midi_parser_l_g->forward( $1 );
+ }
+ ;
+
the_event:
- meta_event {
+ meta_event {
}
| midi_event {
}
meta_event:
META_EVENT the_meta_event {
- };
+ $$ = $2;
+ }
+ |
+ META_EVENT INT8 INT8 INT8 {
+ $$ = 0;
+ }
+ ;
the_meta_event:
SEQUENCE INT16 {
}
| text_event DATA {
+ $$ = 0;
+ vtor << *$2 << endl;
+ delete $2;
}
| END_OF_TRACK {
+ $$ = 0;
}
| TEMPO INT8 INT8 INT8 {
+ $$ = new Midi_tempo( ( $2 << 16 ) + ( $3 << 8 ) + $4 );
+ vtor << $$->mudela_str() << endl; // ?? waai not at event:
+ 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 );
+ vtor << $$->mudela_str() << endl; // ?? waai not at event:
+ 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 {
+ $$ = 0;
+ delete $2;
}
;
text_event:
TEXT {
+ vtor << endl << "Text: ";
}
| COPYRIGHT {
+ vtor << endl << "Copyright: ";
}
| TRACK_NAME {
+ vtor << endl << "Track name: ";
}
| INSTRUMENT_NAME {
+ vtor << endl << "Instrument name: ";
}
| LYRIC {
+ vtor << endl << "Lyric: ";
}
| MARKER {
+ vtor << endl << "Marker: ";
}
| CUE_POINT {
+ vtor << endl << "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 {
+ 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 pitch_i = $2;
- // assuming key of C
- String notename_str = ( pitch_i % 12 )[ "ccddeffggaab" ];
- static int accidental_i_a[ 12 ] = { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 };
- int accidental_i = accidental_i_a[ pitch_i % 12 ];
- if ( accidental_i == 1 )
- notename_str += "is";
- cout << "note(" << pitch_i << "): " << notename_str << endl;
+ 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 {
+ PROGRAM_CHANGE INT8 {
+ $$ = 0;
+ }
+ ;
+
+channel_aftertouch:
+ CHANNEL_AFTERTOUCH INT8 INT8 {
+ $$ = 0;
+ }
+ ;
+
+pitchwheel_range:
+ PITCHWHEEL_RANGE INT8 INT8 {
+ $$ = 0;
}
;
sysex_event:
- SYSEX_EVENT1 {
+ SYSEX_EVENT1 DATA {
+ $$ = 0;
}
- | SYSEX_EVENT2 {
+ | SYSEX_EVENT2 DATA { // INT8 ?
+ $$ = 0;
}
;
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
#include "proto.hh"
+#include "string.hh"
+#include "moment.hh"
#include "midi-event.hh"
#include "midi-track.hh"
return String( "<duration: " ) + String( seconds_f_ ) + ">";
}
-Midi_header::Midi_header( int format_i, int tracks_i, int tempo_i )
+Midi_header::Midi_header( int format_i, int tracks_i, int clocks_per_4_i )
{
String str;
String tracks_str = StringConversion::int2hex_str( tracks_i, 4, '0' );
str += StringConversion::hex2bin_str( tracks_str );
- String tempo_str = StringConversion::int2hex_str( tempo_i, 4, '0' );
+ String tempo_str = StringConversion::int2hex_str( clocks_per_4_i, 4, '0' );
str += StringConversion::hex2bin_str( tempo_str );
set( "MThd", str, "" );
Midi_note::Midi_note( Melodic_req* melreq_l, int channel_i, bool on_bo )
{
-
- if (!melreq_l )
- pitch_i_ = INT_MAX-1; // any pitch.
- else
- pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;
-
+ assert(melreq_l);
+ pitch_i_ = melreq_l->pitch() + c0_pitch_i_c_;
channel_i_ = channel_i;
// poor man-s staff dynamics:
return String( "" );
}
+Midi_tempo::Midi_tempo( int tempo_i )
+{
+ tempo_i_ = tempo_i;
+}
+
+String
+Midi_tempo::str()
+{
+ int useconds_per_4_i = 60 * (int)1e6 / tempo_i_;
+ String str = "ff5103";
+ str += StringConversion::int2hex_str( useconds_per_4_i, 6, '0' );
+ return StringConversion::hex2bin_str( str );
+}
+
Midi_track::Midi_track( int number_i )
{
// 4D 54 72 6B MTrk
number_i_ = number_i;
char const* data_ch_c_l = "00" "ff58" "0404" "0218" "08"
- "00" "ff51" "0307" "a120"
+// "00" "ff51" "0307" "a120"
// why a key at all, in midi?
// key: C
"00" "ff59" "02" "00" "00"
void
Midi_track::add( Moment delta_time_moment, Midi_item* mitem_l )
{
- // silly guess: 24 midi clocks per 4 note
- // huh?
-// int delta_time_i = delta_time_moment / Moment( 1, 4 ) * Moment( 24 );
- int delta_time_i = delta_time_moment / Moment( 1, 4 ) * Moment( 96 );
+ // use convention of 384 clocks per 4
+ int delta_time_i = delta_time_moment * Moment( 384 ) / Moment( 1, 4 );
add( delta_time_i, mitem_l->str() );
}
Midi_output:: Midi_output(Score* score_l, Midi_def* midi_l )
{
+ midi_l_ = midi_l;
+
Midi_stream midi_stream(midi_l->outfile_str_,
score_l->staffs_.size(),
- midi_l->get_tempo_i(Moment(1, 4)));
+ 384 );
+// oeps, not tempo, but clocks per 4 (384 convention)
+// must set tempo in tempo request
+// midi_l->get_tempo_i(Moment(1, 4)));
midi_stream_l_ = &midi_stream;
int track_i=0;
Midi_output::do_staff(Staff*st_l,int track_i)
{
Midi_track midi_track( track_i );
+ Midi_tempo midi_tempo( midi_l_->get_tempo_i( Moment( 1, 4 ) ) );
+ midi_track.add( Moment( 0.0 ), &midi_tempo );
for (Midi_walker w (st_l, &midi_track); w.ok(); w++)
w.process_requests();
#include "midistream.hh"
#include "debug.hh"
-Midi_stream::Midi_stream( String filename_str, int tracks_i, int tempo_i )
+Midi_stream::Midi_stream( String filename_str, int tracks_i, int clocks_per_4_i )
{
filename_str_ = filename_str;
tracks_i_ = tracks_i;
- tempo_i_ = tempo_i;
+ clocks_per_4_i_ = clocks_per_4_i;
open();
header();
}
// *os_p_ << str;
// *this << Midi_header( 1, 1, tempo_i_ );
- *this << Midi_header( 1, tracks_i_, tempo_i_ );
+ *this << Midi_header( 1, tracks_i_, clocks_per_4_i_ );
}
void
track_l_ = track_l;
last_moment_= 0;
}
+
/**
output notestop events for all notes which end before #max_moment#
*/
Melodic_req * req_l = stop_notes.get();
Midi_note note(req_l, track_l_->number_i_, false);
-
- Moment delta_t = stop_moment-last_moment_ ;
- last_moment_ += delta_t;
- track_l_->add(delta_t, ¬e );
+ output_event(note, stop_moment);
}
}
+/** advance the track to #now#, output the item, and adjust current
+ "moment". */
+void
+Midi_walker::output_event(Midi_item &i, Moment now)
+{
+ Moment delta_t = now - last_moment_ ;
+ last_moment_ += delta_t;
+ track_l_->add(delta_t, &i );
+}
void
Midi_walker::process_requests()
for ( int i = 0; i < ptr()->musicalreq_l_arr_.size(); i++ ) {
Rhythmic_req *n = ptr()->musicalreq_l_arr_[i]->rhythmic();
- if ( !n || !(n->note() || n->rest()) )
+ if ( !n)
+ continue;
+ Note_req * note_l = n->note();
+ if (!note_l)
continue;
- Midi_note note(n->melodic(), track_l_->number_i_, true);
- stop_notes.enter(n->melodic(), n->duration() + ptr()->when() );
- Moment dt = 0;
- track_l_->add(dt, ¬e);
+ Midi_note note(note_l, track_l_->number_i_, true);
+ stop_notes.enter(note_l, n->duration() + ptr()->when() );
+ output_event(note, ptr()->when());
}
}
My_midi_lexer::My_midi_lexer( String filename_str )
{
input_file_p_ = new Input_file( filename_str );
- switch_streams( input_file_p_->is );
+ switch_streams( input_file_p_->is );
midi_lexer_l_g = this;
errorlevel_i_ = 0;
}
return input_file_p_->sourcefile_l_->ch_c_l() + yyin->tellg();
}
-#if 0 // ?? huh
-int
-My_midi_lexer::yylex()
-{
- return 0;
-}
-#endif
-
int
My_midi_lexer::varint2int_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 << "\nvarint2int:" << StringConversion::bin2hex_str( str ) << endl;
+ assert( 0 ); // illegal varint
return 0;
}
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
+#include "proto.hh"
+
+#include "plist.hh" // ugh
+#include "string.hh"
+#include "sourcefile.hh"
+#include "source.hh"
+#include "midi-main.hh" // *tors
+
+#include "my-midi-lexer.hh"
+#include "my-midi-parser.hh"
+#include "midi-event.hh"
#include "my-midi-lexer.hh"
#include "my-midi-parser.hh"
{
midi_lexer_p_ = new My_midi_lexer( filename_str );
midi_parser_l_g = this;
+
+ midi_key_p_ = new Midi_key( 0, 0 );
+// midi_tempo_p_ = new Midi_tempo( 384 ); // wiellie dunno!
+ // 07A120 == 500000
+ midi_tempo_p_ = new Midi_tempo( 0x07a120 ); // wiellie dunno!
+ midi_time_p_ = new Midi_time( 4, 4, 0x24, 8 );
+
defined_ch_c_l_ = 0;
fatal_error_i_ = 0;
+ now_f_ = 0;
+ step_f_ = 0;
+
+ for ( int i = 0; i < CHANNELS_i; i++ )
+ for ( int j = 0; j < PITCHES_i; j++ )
+ running_f_f_a_[ i ][ j ] = 0;
}
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_;
+}
+
+void
+My_midi_parser::add_score( Midi_score* midi_score_p )
+{
+ midi_score_p_array_.push( midi_score_p );
+ cout << endl;
}
void
exit( fatal_error_i_ );
}
+void
+My_midi_parser::forward( Real f )
+{
+ // ugh
+ if ( f )
+ step_f_ = f;
+ now_f_ += step_f_;
+}
+
+void
+My_midi_parser::note_begin( int channel_i, int pitch_i, int dyn_i )
+{
+ // one pitch a channel at time!
+ // heu, what if start at t = 0?
+// assert( !running_f_f_a_[ channel_i ][ pitch_i ] );
+ running_f_f_a_[ channel_i ][ pitch_i ] = now_f_;
+}
+
+Midi_event*
+My_midi_parser::note_end_midi_event_p( int channel_i, int pitch_i, int dyn_i )
+{
+ Real start_f = running_f_f_a_[ channel_i ] [ pitch_i ];
+ // did we start? -> heu, don-t know: what if start at t = 0?
+// assert( start_f );
+ return new Midi_note( midi_key_p_, midi_time_p_, clocks_per_whole_i_, pitch_i, now_f_ - start_f );
+}
+
+int
+My_midi_parser::output( String filename_str )
+{
+ return 0;
+}
+
int
My_midi_parser::parse()
{
}
void
-My_midi_parser::add_score( Midi_score* midi_score_p )
+My_midi_parser::set_division( int clocks_per_4_i )
{
- midi_score_p_array_.push( midi_score_p );
+ clocks_per_whole_i_ = clocks_per_4_i * 4;
+ if ( clocks_per_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 );
}
open();
map();
+ // ugh!?, should call name_str() !
filename_str = name_str_;
}
}
end_ch_c_l--;
-// String( char const* p, int length ) is missing!?
-// String line_str( begin_ch_c_l, end_ch_c_l - begin_ch_c_l );
-
+#if 1
+// String( char const* p, int length ) is missing!?
+ String line_str( (Byte const*)begin_ch_c_l, end_ch_c_l - begin_ch_c_l );
+#else
int length_i = end_ch_c_l - begin_ch_c_l;
char* ch_p = new char[ length_i + 1 ];
strncpy( ch_p, begin_ch_c_l, length_i );
ch_p[ length_i ] = 0;
String line_str( ch_p );
delete ch_p;
+#endif
int error_col_i = 0;
char const* scan_ch_c_l = begin_ch_c_l;
return istream_p_;
}
+off_t
+Source_file::length_off()
+{
+ return size_off_;
+}
+
int
Source_file::line_i( char const* pos_ch_c_l )
{
}
}
String
-Source_file::file_line_no_str(const char *cch_c_l )
+Source_file::file_line_no_str(char const *ch_c_l )
{
return name_str() + ": "
- + String( line_i( cch_c_l ) );
+ + String( line_i( ch_c_l ) );
}