TOPLEVEL_MAJOR_VERSION = 0
TOPLEVEL_MINOR_VERSION = 0
-TOPLEVEL_PATCH_LEVEL = 61
+TOPLEVEL_PATCH_LEVEL = 62
# use to send patches, always empty for released version:
# include separator: ".postfix", "-pl" makes rpm barf
-6/May/97 LilyPond 0.0.60 1
+6/May/97 LilyPond 0.0.62 1
=over 4
+=item *
+
Describing a well-defined language for defining music. We call
this language (rather arrogantly) The Musical Definition Language
(mudela for short). GNU LilyPond reads a mudela sourcefile and outputs a
Q: I get all kinds of errors while compiling parser.cc
A: LilyPond uses features of bison version 1.25. Please confirm that
-you are using a version 1.25 or better. If the problem persists, then
-please mail me.
+you are using a version 1.25 or better. Don't forget to do "make
+clean" after installing it
+
+If the problem persists, then please mail me.
=head2 Language: mudela
=head2 Miscellaneous
+Q: How do I change the staff-dividers?
+
+A: See lilyponddefs.tex
+
+
Q: Why GPL?
A: Yes.
</a
>
-=item *
-<a href=examples.html
->
-info on examples
-</a
->
=item *
<a href=TODO.txt
Herbert Chlapik, Die Praxis des Notengraphikers. Doblinger, 1987.
+Helene Wanske, ?, Schott-Verlag Mainz.
+
Maxwell Weaner and Walter Boelke, Standard Music Notation Practice,
revised edition by Arnold Broido and Daniel Dorff. Music Publisher's
Association of the United States Inc., 1993.
set init file to F<FILE> (default: F<symbol.ini>)
=item B<--include, -I>=F<DIRECTORY>
+
add F<DIRECTORY> to the search path for input files.
=back
=head1 PROBLEMS
-If GNU LilyPond bombs out, then please recompile using with debugging info
-turned on, and send a copy of the input which causes the error and a
-gdb stacktrace of the crash. It also helps if you can print the values
-of the objects. So if your trace is
+
+There is an extensive list of todoes and bugs. See F<TODO>. In
+general, try to find out
+
+=over 4
+
+=item *
+
+if the bug has been fixed in a newer release.
+
+=item *
+
+if the bug has been found earlier, consult F<TODO>
+
+=item *
+
+where the bug comes from: if GNU LilyPond bombs out, then please
+recompile using with debugging info turned on, and send a copy of the
+input which causes the error and a gdb stacktrace of the crash. It
+also helps if you can print the values of the objects. So if your
+trace is
(gdb) backtrace 12
#0 Interval::operator+= (this=0x11fffec60..)
Than it would help if you send a dump of the Interval and the Item
(use: C<print *this> or use GNU LilyPond C<print()> methods).
-This is a beta version of GNU LilyPond. Please send your helpful comments
-and patches to me (see AUTHORS section)
+=back
-GNU LilyPond is updated very frequently, the latest version is always available at:
-ftp://pcnov095.win.tue.nl/pub/lilypond.
+Bug reports should be directed to
+bug-gnu-music@vuse.vanderbilt.edu. In any case, they should contain a
+description of the problem, an small input file which reproduces it
+(if applicable), lilypond version and a description of the platform.
=head1 FILES
B<LILYINCLUDE> an (one) additional directory for finding lilypond data.
+=head1 BUGS
+
=head1 SEE ALSO
=over 4
Goals of the GNU LilyPond project.
-=item The GNU LilyPond FAQ list
+=item FAQ
-=back
+The GNU LilyPond FAQ list
+
+
+
+=item http://?
+
+The GNU Music project. GNU LilyPond is part of the GNU Music
+project. For more information on the GNU Music project,
+
+=item http://www.stack.nl/~hanwen/lilypond/index.html
GNU LilyPond has her own webpage at
-http://www.stack.nl/~hanwen/lilypond/index.html. This webpage contains
+This webpage contains
the MIDI, GIF and PS files for some standard music files. It also has
the complete LilyPond documentation
-A mailing list for GNU LilyPond has been setup, it's at
-lilypond@gnu.ai.mit.edu. To subscribe, send mail to
-lilypond-request@gnu.ai.mit.edu.
-For discussions concerning the GNU Music project,
-gnu-music-discuss@vanderbilt. .edu
+=back
+
+GNU LilyPond is
+updated very frequently, the latest version is always available at:
+ftp://pcnov095.win.tue.nl/pub/lilypond.
+
+For programs which part of the GNU music project, the following mailing list
+have been setup:
+
+
+=over 4
+
+=item info-gnu-music@vuse.vanderbilt.edu
+
+For information on the GNU Music project, to subscribe: send mail with
+subject "subscribe" to info-gnu-music-request@vuse.vanderbilt.edu
+
+=item help-gnu-music@vuse.vanderbilt.edu
+
+For help with programs from the GNU music project. To subscribe: send
+mail with subject "subscribe" to
+help-gnu-music-request@vuse.vanderbilt.edu
+
+=item bug-gnu-music@vuse.vanderbilt.edu
+
+If you have bugreports, you should send them to this list. If you want
+to read all bugreports, you should subscribe to this list. To
+subscribe: send mail with subject "subscribe" to
+bug-gnu-music-request@vuse.vanderbilt.edu
+
+=item gnu-music-discuss@vuse.vanderbilt.edu,
+
+For discussions concerning the GNU Music project, to subscribe: send
+mail with subject "subscribe" to
+gnu-music-discuss-request@vuse.vanderbilt.edu,
+
+=back
=head1 REMARKS
-2/May/97 LilyPond 0.0.60 1
+2/May/97 LilyPond 0.0.62 1
-2/May/97 LilyPond 0.0.60 2
+2/May/97 LilyPond 0.0.62 2
-2/May/97 LilyPond 0.0.60 3
+2/May/97 LilyPond 0.0.62 3
-2/May/97 LilyPond 0.0.60 4
+2/May/97 LilyPond 0.0.62 4
+pl 61.jnc1
+ - smarter + faster duration-convert using Array
+ - bf: mi2mu compilation/duration-conversions
+ - lots faster mi2mu, hopefully does type 1 too...
+pl 60.jnc1
+ - mi2mu handles non-quantified rests, try mi2mu -b wtk-i/fugue2.midi
+
+
+pl 62
+ - make clean bf: remove lex & yacc files too
+ - added kludge in case measure too long
+ - added kludge in case of unconnected columns.
+ - kludged columns get error marker
+ - kludged lines get error marker
+
+**********
+may 14
pl 61
- - scales.ly bugfix: dimensions default to ((0,0),(0,0))
+ - scales.ly bugfix: dimensions default to ((0,0), (0,0))
- naming: PointerList->Pointer_list
- tied notes don't get accidental
- bf: crescendo size
- set_flower_debug: Warning if -d is used when NPRINT is defined.
- Fixed several TeX details. vcenter renamed since it interfered
with LaTeX. Position of accents changed.
- - New example; scriptS.ly
+ - New example; scripts.ly
- table_sixteen: added scriptdefinition (Lilypond breaks if a
script is defined without dimensions).
- bf: ifndef typos in p-score.cc, choleski.cc
- bf: Slur::do_post_processing(), whole notes caused SIGSEGV.
-
+(ascension break :-)
*******
+pl 57.jcn4
+ - mi2mu handles rests (quantified only)
+ - fixed configure buglet
+ - "!date" Fri May 2 02:18:12 MET DST 1997
+
pl 60
- Request_register::get_feature(), tie direction, Slur direction
- lilypond output is now directly texable.
LilyPond is a long way from finished and polished. I do appreciate
criticism, comments, bugreports, patches, etc. Please send e-mail to
-me,
+the mailing lists
- hanwen@stack.nl
+ info-gnu-music-request@vuse.vanderbilt.edu
+ help-gnu-music-request@vuse.vanderbilt.edu
+ bug-gnu-music-request@vuse.vanderbilt.edu
+ gnu-music-discuss-request@vuse.vanderbilt.edu,
+
+(or directly to us: hanwen@stack.nl, jan@digicash.com)
+
+
+
Have fun!
-
This is an assorted collection of stuff that will be done, might be
done, or is an idea that I want to think about
IMPORTANT
+ * faq about mi2mu midi t1.
+
* update 20 pt table
* use Hungarian throughout code
* rename mf fonts to avoid conflicts with musixtex
+ check (c) issues
* decent TeX page layout
PROJECTS
- * Output class, handles
+ * Output class, handles : (smallish)
- help text /(c) notice?
+ - version line
- warning /errors/progress
- abort on error/warning; exit status
- quiet/ignore-version options
- slur start/end
* Output an output format independent (ofi) typeset file; and
- make ofi2 TeX, MusixTex, PostScript, Ascii... interpreters.
+ make ofi2 TeX, MusixTex, PostScript, Ascii... interpreters. (difficult)
- poor man's ascii output possible?
- MusixTeX output possible? (would have to be done before break calc.)
- NIFF ?
- PostScript output (esp. Beams, Slurs, etc)
- * TeX spanners , use texbeam.cc as an example
+ * TeX spanners , use texbeam.cc as an example (smallish)
- Glissando
- trill
- bracket
- * Rewrite Beam and Rhythmic_grouping
+ * Rewrite Beam and Rhythmic_grouping (hairy)
- [c8. c32 c32]
- - interbeam height
+ - interbeam height
- general shaving
- use plet grouping
- abbreviations [c2 c2]1/2
- separate visual from rhythmic info
+ * Redo MIDI output to use Registers: (Difficult)
+ - remember more horizontal info than melodics:
+ - tempo change
+ - repeat
+ - slurs
+ - dynamics etc.
+
PARSER
* Duration -> Musical_duration, typedef Rational Duration?
Hele rusten ook in andere maatsoort dan 4/4 (en centreren in de maat)
-------------------------\
-barcheck failed in lyric mode -> assert (zie barcheck.ly) (0.0.57)
-------------------------/
-
noten staan vaak te dicht aan de rechterkant van de maatstreep.
optie om nummers/markers boven maatstrepen te zetten
implementeren versieringen door duration *0 ofzo? (geeft nu assertion,
zie duration0.ly)
-midi: instrumenten definieren?
-midi: tempo halverwege het stuk wijzigen?
-midi: gebonden noten niet herhalen?
-
Triolen enzo: het zou handig zijn als je het cijfer "3" ook _tussen_
twee noten kon plaatsen. Dat is bijvoorbeeld nodig in
c4*2/3 c8*2/3
BUGS
- * detect -pipe
-
* staccato dot positions.
* stacked scripts.
* standchen triool beam up/down
-
SEVERELY LACKING:
* SPEED!
* \duration 8; e*2/3
-
* configure pitch_byte
* special key.
SMALLISH PROJECTS
+ * --fast/--draft: leave out constraints
+
* write Dynamic_line (to group dynamics horizontally)
* write Rest_collision
* key undo
- * unix style paths for LILYINCLUDE EN
+ * unix style paths for LILYINCLUDE env
* indentable stream as baseclass for TeX stream, lily stream, Dstream.
* qtor, btor, mtor-> tor( QUIET_ver ), tor( DEBUG_ver ), etc.
- - declare notenametab?
+ * declare notenametab?
* use tors feature in lily
* configure idealspacing: arithmetic spacing
- * midi output: eat-up dynamic, key/meter/tempo changes, and
-write them neatly
- * LilyPond .deb
+ * LilyPond .deb. Other packaging methods?
+
+ * detect -pipe
+
DOC
FUTURE
+ * auxilliary file for caching info.
+
* Reg_configure_request
* bring Collision::do_pre_processing to haircutter
* Junk Staff_column, and find the requests while walking the Voices.?
- * MIDI repeat: make lily understand repeats
-
* better beamslope calculation: QLP for beams?
* implement better breaking algorithm
ID '=' EXPR;
- * integrate Register/Midi stuff
-
* create libmudela, or liblily_frontend
* move MIDI stuff (including Quantization) to a ANSI C libmidi library.
- * use an embedded language: Python, Scheme?
+ * use an embedded language: Python
for :
- Items/Spanners
- Registers
- - Complex mudela
+ - Complex mudela?
* y -dims in internote?
* hack up mf sources for decent spacing info (and then
- read TFM directly, for text too)
+ read AFM/TFM directly, for text too)
* merge Atom and Symbol?
RPMS=`find ~/rpms/ -name lilypond-$NEWVER'*'rpm`
rm *.rpm {lilypond,patch}-*.gz
-if [ ! -z $RPMS ]; then
+if [ ! -z "$RPMS" ]; then
ln $RPMS .
fi
ln ../patches/$patch .
-if [ ! -z $RPMS ]; then
- RPMS=lilypond-$LILYVER-1.i386.rpm lilypond-$LILYVER-1.src.rpm
+if [ ! -z "$RPMS" ]; then
+ RPMS="lilypond-$LILYVER-1.i386.rpm lilypond-$LILYVER-1.src.rpm"
fi
tar cf updeet $tarball $patch $RPMS
tar tfv updeet
if test $BISON = "error"
then
- echo "configure: warning: can't find bison. Please install Bison (1.24 or better)" 1>&2
+ echo "configure: warning: can't find bison. Please install Bison (1.25 or better)" 1>&2
+else
+ bison_version=`$BISON --version| sed 's/^.*version 1.//g' `
+ if test $bison_version -lt 25; then
+ echo "configure: warning: Your bison is too old (1.$bison_version). Please install 1.25" 1>&2
+ fi
fi
if test $PODMAN = "error"
fi
echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
-echo "configure:1177: checking how to run the C++ preprocessor" >&5
+echo "configure:1182: checking how to run the C++ preprocessor" >&5
if test -z "$CXXCPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
cross_compiling=$ac_cv_prog_cxx_cross
CXXCPP="${CXX-g++} -E"
cat > conftest.$ac_ext <<EOF
-#line 1190 "configure"
+#line 1195 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1195: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1200: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
:
ac_safe=`echo "FlexLexer.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for FlexLexer.h""... $ac_c" 1>&6
-echo "configure:1215: checking for FlexLexer.h" >&5
+echo "configure:1220: checking for FlexLexer.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1220 "configure"
+#line 1225 "configure"
#include "confdefs.h"
#include <FlexLexer.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1225: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1230: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
eval "DIR_DATADIR=$datadir"
DIR_DATADIR="$DIR_DATADIR/lilypond"
echo $ac_n "checking ""... $ac_c" 1>&6
-echo "configure:1629: checking " >&5
+echo "configure:1634: checking " >&5
cat << EOF > lib/out/config.hh
if test $BISON = "error"
then
- AC_MSG_WARN(can't find bison. Please install Bison (1.24 or better))
+ AC_MSG_WARN(can't find bison. Please install Bison (1.25 or better))
+else
+ bison_version=`$BISON --version| sed 's/^.*version 1.//g' `
+ if test $bison_version -lt 25; then
+ AC_MSG_WARN(Your bison is too old (1.$bison_version). Please install 1.25)
+ fi
fi
if test $PODMAN = "error"
MAJOR_VERSION = 1
MINOR_VERSION = 1
-PATCH_LEVEL = 15
+PATCH_LEVEL = 16
# use to send patches, always empty for released version:
MY_PATCH_LEVEL = # include separator: "-1" or ".a"
#
-pl 1.1.15
+version 1.1:
+
+pl 16
+ - Array::get()
+ - P< > doco.
+
+pl 15
- #ifndef fixes (MB)
- Dstream::clear ()
-pl 1.1.14
+pl 14
- interval methods
-pl 1.1.13
+pl 13
- better test-bed
- Heap PQueue implementation
-pl 1.1.12
+pl 12
- No path search for "" and "-"
-pl 1.1.11
+pl 11
- template<> class P
- assoc elem() methods
-pl 1.1.10
+pl 10
- Matrix_storage naming
- Matrix_storage::try_right_multiply to help speed up
matrix multiply routines.
-pl 1.1.9
+pl 9
- _C iso _c_l
- flower-debug.
-pl 1.1.8
+pl 8
-pl 1.1.7
+pl 7
- PQueue blondification.
- String_convert::i2hex_str fix, unsigned eqvs introduced
- long long depreciated, now named I64
- type I32 introduced. should be used iso int where 32 bits are
needed(or, brr, assumed...)
-pl 1.1.6-2
+pl 6-2
Bugfix
- silly String( int... ) -> String( (char)... ) fix
really should junk ambiguous constructor overload
-pl 1.1.6-1
+pl 6-1
Bugfix
- small but nasty include/fversion.hh fixed
-pl 1.1.6
- - all of 1.1.4-1 and 1.1.5
+pl 6
+ - all of 4-1 and 5
Bugfix
- null_terminated -> is_binary test
-pl 1.1.5
+pl 5
- memmem interface, conditional compilation
- snprintf
-pl 1.1.4-1
+pl 4-1
- included in new make structure, as a library of lilypond;
for compiling you-ll need ../make and ../bin dirs from
lilypond...
-pl 1.1.4
+pl 4
- great file-renaming.
- String cleanup (binary <-> null terminate), several bugfixes
- great renaming of String and String_convert interfaces
- String indexing now all base = 0, not found = -1
- renamed by to byte
-pl 1.1.3
+pl 3
- String::mid
- memmove test code
-pl 1.1.2
+pl 2
- StringConversio::bin2int_i
- dumb prioq
-pl 1.1.1
+pl 1
- separated StringHandle and StringData
- String::compare
-1.1.0:
+0:
------------------
Sorry for the silly naming */
template <class T>
class P {
-
- void copy(T*);
+ /**
+ Set contents to a copy of #t_l#
+ */
+ void copy(T const*t_l);
T* t_p;
+
+ /**
+ junk contents and set to 0
+ */
void junk();
public:
P(P const &src);
+ /**
+ Remove the pointer, and return it.
+ */
T *get_p() { T*p = t_p; t_p=0; return p; }
- T *get_l() { return t_p; }
+ /**
+ return the pointer
+ */
+ T *get_l() { return t_p; }
+
+ T const *get_C() const { return t_p; }
+ /**
+ copy the contents of pointer, and return it
+ */
T *copy_p() const;
+ /**
+ swallow new_p, and set contents t new_p
+ */
void set_p (T *new_p);
- void set_l (T *t_l);
+ /**
+ junk contents, and copy contents of t_l
+ */
+ void set_l (T const *t_C);
P &operator =(P const &);
~P();
T *operator ->() { return t_p; }
operator T * () { return t_p; }
const T *operator ->() const { return t_p ; }
+ T &operator *() { return *t_p; }
+ T const &operator *() const { return *t_p; }
operator const T *() const { return t_p; }
};
#endif // POINTER_HH
template<class T>
inline
void
-P<T>::copy(T *l)
+P<T>::copy(T const *l_C)
{
- t_p = l ? new T(*l) : 0;
+ t_p = l_C ? new T(*l_C) : 0;
}
template<class T>
template<class T>
inline
void
-P<T>::set_l(T * l)
+P<T>::set_l(T const * l_C)
{
- if (t_p == l)
+ if (t_p == l_C)
return;
junk();
- copy(l);
+ copy(l_C);
}
OK();
}
T max() const {
- int first_leaf_i = size();
+ //int first_leaf_i = size();
T max_t;
return max_t;
}
thearray[i] = thearray[i-1];
thearray[j] = k;
}
+ /**
+ remove i-th element, and return it.
+ */
+ T get(int i) {
+ T t = elem(i);
+ del (i);
+ return t;
+ }
void del(int i) {
assert(i >=0&& i < size_);
arrcpy(thearray+i, thearray+i+1, size_-i-1);
"8" "\eighthrest" 0\pt 5\pt 0\pt 8\pt
"16" "\sixteenthrest" 0\pt 6\pt 0\pt 12\pt
"32" "\thirtysecondrest" 0\pt 6\pt 0\pt 16\pt
+ "64" "\sixtyfourthrest" 0\pt 6\pt 0\pt 16\pt
+ "128" "\hundredtwentyeighthrest" 0\pt 6\pt 0\pt 16\pt
}
"meters" = \table {
}
"flags" = \table {
- "8" "\eigthflag" 0\pt 4\pt 0\pt 0\pt
+ "8" "\eighthflag" 0\pt 4\pt 0\pt 0\pt
"16" "\sixteenthflag" 0\pt 4\pt 0\pt 0\pt
"32" "\thirtysecondflag" 0\pt 4\pt 0\pt 0\pt
- "-8" "\deigthflag" 0\pt 4\pt 0\pt 0\pt
+ "64" "\sixtyfourthflag" 0\pt 4\pt 0\pt 0\pt
+ "128" "\hundredtwentyeighthflag" 0\pt 4\pt 0\pt 0\pt
+ "-8" "\deighthflag" 0\pt 4\pt 0\pt 0\pt
"-16" "\dsixteenthflag" 0\pt 4\pt 0\pt 0\pt
"-32" "\dthirtysecondflag" 0\pt 4\pt 0\pt 0\pt
+ "-64" "\dsixtyfourthflag" 0\pt 4\pt 0\pt 0\pt
+ "-128" "\dhundredtwentyeighthflag" 0\pt 4\pt 0\pt 0\pt
}
"beamslopes" = \table {
}
-% Setting up music ...lilypond: ../flower/include/cursor.inl:98: class Cursor<void *> Cursor<void *>::operator ++(int): Assertion 'pointer_' failed.
-%IOT trap/Abort
-% als geen music in staff
-
\include "this-is-hopefully-a-nonexisting-file"
\score{
\staff{ bla }
filename:rhythm.ly
title:
description:
- composers:HWN
+ composers:
entered-by:HWN
copyright:public domain
bool Duration_convert::no_double_dots_b_s = false;
bool Duration_convert::no_triplets_b_s = false;
int Duration_convert::no_smaller_than_i_s = 0;
+Array<Duration> Duration_convert::dur_array_s;
String
Duration_convert::dur2_str( Duration 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 dur = iter_dur++;
- if ( mom == dur2_mom( dur ) )
- return dur;
- }
- if ( midi_as_plet_b_s ) {
- Moment mom_4 = mom / Moment( 4 );
- long num = mom_4.numerator().as_long();
- long den = mom_4.denominator().as_long();
- Duration dur( 4, 0 );
- dur.set_plet( num, den );
+ if (!mom) {
+ Duration dur;
+ dur.set_plet(0,1);
+ return dur;
+ }
+
+
+ Duration dur = mom2standardised_dur( mom );
+// if ( dur.mom() == mom )
+ if ( dur.length() == mom )
return dur;
- }
- assert( 0 );
- // no can do
- Duration dur( 0 );
+ assert( midi_as_plet_b_s );
+
+// dur.set_plet( type_mom, Duration::division_1_i_s / 4 );
+
+// Moment as_plet_mom = mom / dur.mom();
+ Moment as_plet_mom = mom / dur.length();
+ as_plet_mom *= dur.plet_.mom();
+ long num = as_plet_mom.numerator().as_long();
+ long den = as_plet_mom.denominator().as_long();
+ dur.set_plet( num, den );
return dur;
}
Duration
Duration_convert::mom2standardised_dur( Moment mom )
{
- /* this is cute,
- but filling an array using Duration_iterator
- might speed things up, a little
- */
+// if ( !dur_array_s.length_i() )
+ if ( !dur_array_s.size() )
+ set_array();
+// assert( dur_array_s.length_i() );
+ assert( dur_array_s.size() );
+// for ( int i = 0; i < dur_array_s.length_i() - 1; i++ ) {
+ for ( int i = 0; i < dur_array_s.size() - 1; i++ ) {
+ Moment lower_mom = dur2_mom( dur_array_s[ i ] );
+ if ( mom <= lower_mom ) {
+ if ( i || ( mom / lower_mom > Moment( 3, 4 ) ) )
+ return dur_array_s[ i ];
+ else
+ return Duration( 0 );
+ }
+ Moment upper_mom = dur2_mom( dur_array_s[ i + 1 ] );
+ if ( ( mom < upper_mom )
+ && ( ( mom - lower_mom ) / mom
+ < ( upper_mom - mom ) / mom ) )
+ return dur_array_s[ i ];
+ }
+// return dur_array_s[ dur_array_s.length_i() ];
+ return dur_array_s[ dur_array_s.size() - 1 ];
+}
+
+void
+Duration_convert::set_array()
+{
+ dur_array_s.clear();
+
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 == lower_mom )
- return lower_dur;
- }
- return iter_dur();
+ while ( iter_dur )
+ dur_array_s.push( iter_dur++ );
}
Duration
Duration_convert::ticks2_dur( int ticks_i )
{
- /* this is cute,
- but filling an array using Duration_iterator
- might speed things up, a little
- */
- // should use mom2_dur
+// Duration dur( 4, 0 );
+// dur.set_plet( ticks_i, Duration::division_1_i_s / 4 );
+
Moment mom( ticks_i, Duration::division_1_i_s );
- Duration_iterator iter_dur;
- assert( iter_dur );
- while ( iter_dur ) {
- Duration dur = iter_dur++;
- if ( mom == dur2_mom( dur ) )
- return dur;
- }
- if ( midi_as_plet_b_s ) {
- Duration dur( 4, 0 );
- dur.set_plet( ticks_i, Duration::division_1_i_s / 4 );
+ if ( midi_as_plet_b_s )
+ return mom2_dur( mom );
+
+ Duration dur = mom2standardised_dur( mom );
+
+// if ( dur.mom() == mom )
+ if ( dur.length() == mom )
return dur;
- }
- Duration dur( 0 );
+
+// huh?
+#if 0
+ dur.type_i_ = 0;
+ dur.dots_i_ = 0;
dur.set_ticks( ticks_i );
return dur;
+#else
+ return mom2_dur( mom );
+#endif
}
Duration
Duration_convert::ticks2standardised_dur( int ticks_i )
{
- /* this is cute,
- but filling an array using Duration_iterator
- might speed things up, a little
- */
- // should use mom2standardised_dur
Moment mom( ticks_i, Duration::division_1_i_s );
- Duration_iterator iter_dur;
- assert( iter_dur );
- while ( iter_dur ) {
- Duration lower_dur = iter_dur++;
-// Duration upper_dur( 0 );
- Duration upper_dur( 1, 1 );
- 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 == 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 ) );
- if ( abs( mom - lower_mom ) < abs( mom - upper_mom ) )
- return lower_dur;
- else
- return upper_dur;
- }
- lower_dur = upper_dur;
- }
- return iter_dur();
+ Duration dur = mom2standardised_dur( mom );
+
+// if ( dur.mom() != mom )
+ if ( dur.length() != mom )
+ warning( String( "duration not exact: " ) + String( (Real)mom ) );
+ return dur;
}
Duration_iterator::Duration_iterator()
return bit_i == 1;
}
+// ugh, what's this?
+// i should be called "mom()", ... or at least "length_mom()"
Moment
Duration::length() const
{
#define DURATION_CONVERT_HH
#include "duration.hh"
#include "string.hh"
+//#include "array.hh"
+#include "varray.hh"
/**
Duration_convert handles all conversions to -n fro Duration (dur).
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().
+
+ [todo]
+ move all statics to real members, instantiate Duration_convert
+ object(s).
*/
struct Duration_convert {
static bool no_double_dots_b_s;
static bool no_triplets_b_s;
static int no_smaller_than_i_s;
+ static Array<Duration> dur_array_s;
// /// Most used division in MIDI, all fine with me.
// static int const division_1_c_i = 384;
/// Return plet factor (not a Moment: should use Rational?).
static Moment plet_factor_mom( Duration dur );
+ static void set_array();
+
/** Return synchronisation factor for mom, so that
mom2_dur( mom / sync_f ) will return the duration dur.
*/
MAJOR_VERSION = 0
MINOR_VERSION = 0
-PATCH_LEVEL = 61
+PATCH_LEVEL = 62
# use to send patches, always empty for released version:
# include separator: ".postfix", "-pl" makes rpm barf
-include /dev/null $(DEPFILES)
#
+
+localclean:
+ rm -f $(outdir)/parser.* $(outdir)/lexer.cc
return retval;
}
+
+Col_hpositions
+Break_algorithm::stupid_solution(Line_of_cols curline)const
+{
+ Spacing_problem sp;
+ sp.add_column(curline[0], true, 0.0);
+ for (int i=1; i< curline.size()-1; i++)
+ sp.add_column(curline[i]);
+ sp.add_column(curline.top(), true, linelength);
+ Col_hpositions colhpos;
+ colhpos.cols = curline;
+ colhpos.energy = INFTY;
+ colhpos.ugh_b_ = true;
+ colhpos.config = sp.try_initial_solution();
+ return colhpos;
+}
+
/// construct an appropriate Spacing_problem and solve it.
Col_hpositions
Break_algorithm::solve_line(Line_of_cols curline) const
for (iter_top(pscore_.suz,i); i.ok(); i++) {
sp.add_ideal(i);
}
+ sp.prepare();
+
Array<Real> the_sol=sp.solve();
Col_hpositions col_hpos;
col_hpos.cols = curline;
col_hpos.energy = the_sol.pop();
col_hpos.config = the_sol;
+ col_hpos.error_col_l_arr_ = sp.error_pcol_l_arr();
col_hpos.OK();
return col_hpos;
}
+/*
+ calcideal.cc -- implement Score::calc_idealspacing()
+
+ source file of the LilyPond music typesetter
+
+ (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
#include "idealspacing.hh"
#include "score.hh"
#include "p-score.hh"
effects into account, should be local (measure wide), should check
smallest divisions.
-
+ plus, calc_idealspacing() should be called per line.
*/
void
Score::calc_idealspacing()
Col_hpositions::Col_hpositions()
{
energy = INFTY;
+ ugh_b_ = false;
}
void
bool feasible(Line_of_cols)const;
virtual Array<Col_hpositions> solve()=0;
+
+ /** generate a solution with no regard to idealspacings or
+ constraints. should always work */
+ Col_hpositions stupid_solution(Line_of_cols) const;
};
/// wordwrap type algorithm: move to next line if current is optimal.
typedef Array<PCol*> Line_of_cols;
struct Col_hpositions {
+ bool ugh_b_;
+ Line_of_cols error_col_l_arr_;
Line_of_cols cols;
Array<Real> config;
Real energy;
-#ifndef PROBLEM_HH
-#define PROBLEM_HH
+/*
+ linespace.hh -- declare Colinfo, Spacing_problem
+ source file of the LilyPond music typesetter
+
+ (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef LINESPACE_HH
+#define LINESPACE_HH
#include "glob.hh"
#include "plist.hh"
#include "varray.hh"
#include "vector.hh"
#include "interval.hh"
+#include "pointer.hh"
/// helper struct for #Spacing_problem#
struct Colinfo {
- PCol const *pcol_;
- Real const * fixpos;
+ PCol *pcol_l_;
+ P<Real> fixpos_p_;
Interval width;
-
+ int rank_i_;
+ /// did some tricks to make this column come out.
+ bool ugh_b_;
/* *************** */
Colinfo();
- void operator=(Colinfo const&);
- Colinfo(Colinfo const&);
- ~Colinfo();
- Colinfo(PCol const *,Real const *);
+ Colinfo(PCol *,Real const *);
+
void print() const;
- bool fixed() const { return fixpos;}
- Real fixed_position()const { return *fixpos; }
+ bool fixed() const { return fixpos_p_.get_C();}
+ Real fixed_position()const { return *fixpos_p_; }
Real minright() const { return width.right; }
Real minleft() const { return -width.left; }
};
class Spacing_problem {
Array<Idealspacing const *> ideals;
Array<Colinfo> cols;
-
+ Array<Colinfo> loose_col_arr_;
+
+ /// mark column #i# as being loose.
+ void loosen_column(int i);
/// the index of #c# in #cols#
int col_id(PCol const *c) const;
/// generate the LP constraints
void make_constraints(Mixed_qp& lp) const;
+
+ void handle_loose_cols();
+ void position_loose_cols(Vector &) const;
public:
+ Array<PCol*> error_pcol_l_arr() const;
+
/** solve the spacing problem
@return the column positions, and the energy (last element)
/** add a col to the problem. columns have to be added left to right. The column contains
info on it's minimum width.
*/
- void add_column(PCol const *, bool fixed=false, Real fixpos=0.0);
+ void add_column(PCol *, bool fixed=false, Real fixpos=0.0);
void OK() const;
void print() const;
void print_ideal(Idealspacing const *)const;
+ void prepare();
};
Real hpos; // should use ptr?
+ bool error_mark_b_;
+
PScore * pscore_l_;
/* *************** */
-// the breaking problem for a score.
+/*
+ p-score.hh -- declare PScore
-#ifndef PSCORE_HH
-#define PSCORE_HH
+ source file of the LilyPond music typesetter
+
+ (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
+
+#ifndef P_SCORE_HH
+#define P_SCORE_HH
#include "colhpos.hh"
#include "varray.hh"
PScore(Paper_def*);
/// add a line to the broken stuff. Positions given in #config#
- void set_breaking(Array<Col_hpositions>);
+ void set_breaking(Array<Col_hpositions> const &);
void add(PStaff *);
Line_of_score {
Pointer_list<PCol *> cols;
+ bool error_mark_b_;
// need to store height of each staff.
IPointer_list<Line_of_staff*> staffs;
PScore * pscore_l_; // needed to generate staffs
#include "qlp.hh"
#include "unionfind.hh"
#include "idealspacing.hh"
+#include "pointer.tcc"
const Real COLFUDGE=1e-3;
-
+template class P<Real>; // ugh.
bool
Spacing_problem::contains(PCol const *w)
{
for (int i=0; i< cols.size(); i++)
- if (cols[i].pcol_ == w)
+ if (cols[i].pcol_l_ == w)
return true;
return false;
}
Spacing_problem::col_id(PCol const *w)const
{
for (int i=0; i< cols.size(); i++)
- if (cols[i].pcol_ == w)
+ if (cols[i].pcol_l_ == w)
return i;
assert(false);
return -1;
Spacing_problem::OK() const
{
#ifndef NDEBUG
+ for (int i = 1; i < cols.size(); i++)
+ assert(cols[i].rank_i_ > cols[i-1].rank_i_);
+ for (int i = 1; i < loose_col_arr_.size(); i++)
+ assert(loose_col_arr_[i].rank_i_ > loose_col_arr_[i-1].rank_i_);
+#endif
+}
+
+/**
+ Make sure no unconnected columns happen.
+ */
+void
+Spacing_problem::handle_loose_cols()
+{
Union_find connected(cols.size());
Array<int> fixed;
for (int i=0; i < ideals.size(); i++) {
for (int i = 0; i < cols.size(); i++)
if (cols[i].fixed())
fixed.push(i);
- for (int i = 0; i < cols.size(); i++) {
- bool c=false;
- for (int j =0; j<fixed.size(); j++)
- c |= connected.equiv(fixed[j],i);
- if (!c)
- WARN << "You have unconnected columns. \n"
- "Check if bars and music fit each other\n"
- "(crashing :-)\n";
- assert(c);
+ for (int i=1; i < fixed.size(); i++)
+ connected.connect(fixed[i-1], fixed[i]);
+
+ for (int i = cols.size(); i--; ) {
+ if (! connected.equiv(fixed[0], i)) {
+ warning("unconnected column: " + String(i));
+ loosen_column(i);
+ }
}
-#endif
+ OK();
}
+
+/** Guess a stupid position for loose columns. Put loose columns at
+ regular distances from enclosing calced columns */
+void
+Spacing_problem::position_loose_cols(Vector &sol_vec)const
+{
+ if (!loose_col_arr_.size())
+ return ;
+ assert(sol_vec.dim());
+ Array<bool> fix_b_arr;
+ fix_b_arr.set_size(cols.size() + loose_col_arr_.size());
+ Real utter_right_f=-INFTY;
+ Real utter_left_f =INFTY;
+ for (int i=0; i < loose_col_arr_.size(); i++) {
+ fix_b_arr[loose_col_arr_[i].rank_i_] = false;
+ }
+ for (int i=0; i < cols.size(); i++) {
+ int r= cols[i].rank_i_;
+ fix_b_arr[r] = true;
+ utter_right_f = utter_right_f >? sol_vec(i);
+ utter_left_f = utter_left_f <? sol_vec(i);
+ }
+ Vector v(fix_b_arr.size());
+ int j =0;
+ int k =0;
+ for (int i=0; i < v.dim(); i++) {
+ if (fix_b_arr[i]) {
+ assert(cols[j].rank_i_ == i);
+ v(i) = sol_vec(j++);
+ } else {
+ Real left_pos_f =
+ (j>0) ?sol_vec(j-1) : utter_left_f;
+ Real right_pos_f =
+ (j < sol_vec.dim()) ? sol_vec(j) : utter_right_f;
+ int left_rank = (j>0) ? cols[j-1].rank_i_ : 0;
+ int right_rank = (j<sol_vec.dim()) ? cols[j].rank_i_ : sol_vec.dim();
+
+ int d_r = right_rank - left_rank;
+ Colinfo loose=loose_col_arr_[k++];
+ int r = loose.rank_i_ ;
+ assert(r > left_rank && r < right_rank);
+
+ v(i) = (r - left_rank)*left_pos_f/ d_r +
+ (right_rank - r) *right_pos_f /d_r;
+ }
+ }
+ sol_vec = v;
+}
+
bool
Spacing_problem::check_constraints(Vector v) const
{
int dim=v.dim();
+ assert(dim == cols.size());
+
for (int i=0; i < dim; i++) {
if (cols[i].fixed()&&
return true;
}
+void
+Spacing_problem::prepare()
+{
+ handle_loose_cols();
+}
+
bool
Spacing_problem::check_feasible() const
{
return check_constraints(sol);
}
-// generate a solution which obeys the min distances and fixed positions
+/// generate a solution which obeys the min distances and fixed positions
Vector
Spacing_problem::try_initial_solution() const
{
Vector initsol(dim);
for (int i=0; i < dim; i++) {
if (cols[i].fixed()) {
- initsol(i)=cols[i].fixed_position();
+ initsol(i)=cols[i].fixed_position();
+
+ if (i > 0) {
+ Real r =initsol(i-1) + cols[i-1].minright();
+ if (initsol(i) < r ) {
+ warning("overriding fixed position");
+ initsol(i) =r;
+ }
+ }
+
} else {
Real mindist=cols[i-1].minright()
+cols[i].minleft();
- assert(mindist >= 0.0);
+ if (mindist < 0.0)
+ warning("Excentric column");
initsol(i)=initsol(i-1)+mindist;
-
- //nog niet
- //if (i>0)
- // assert(initsol(i) > initsol(i-1));
}
}
return initsol;
}
+
+
+
Vector
Spacing_problem::find_initial_solution() const
{
Array<Real>
Spacing_problem::solve() const
{
- print();
- OK();
assert(check_feasible());
+ print();
Mixed_qp lp(cols.size());
make_matrices(lp.quad,lp.lin, lp.const_term);
if (!check_constraints(sol)) {
WARN << "solution doesn't satisfy constraints.\n" ;
}
-
+ Real energy_f =lp.eval(sol);
+ position_loose_cols(sol);
Array<Real> posns(sol);
- posns.push(lp.eval(sol));
+
+ posns.push(energy_f);
return posns;
}
add one column to the problem.
*/
void
-Spacing_problem::add_column(PCol const *col, bool fixed, Real fixpos)
+Spacing_problem::add_column(PCol *col, bool fixed, Real fixpos)
{
Colinfo c(col,(fixed)? &fixpos : 0);
+ if (cols.size())
+ c.rank_i_ = cols.top().rank_i_+1;
+ else
+ c.rank_i_ = 0;
cols.push(c);
}
+Array<PCol*>
+Spacing_problem::error_pcol_l_arr()const
+{
+ Array<PCol*> retval;
+ for (int i=0; i< cols.size(); i++)
+ if (cols[i].ugh_b_)
+ retval.push(cols[i].pcol_l_);
+ for (int i=0; i < loose_col_arr_.size(); i++) {
+ retval.push(loose_col_arr_[i].pcol_l_);
+ }
+ return retval;
+}
+
+void
+Spacing_problem::loosen_column(int i)
+{
+ Colinfo c=cols.get(i);
+ for (int i=0; i < ideals.size(); ) {
+ Idealspacing const *i_l =ideals[i];
+ if (i_l->left == c.pcol_l_ || i_l->right == c.pcol_l_)
+ ideals.del(i);
+ else
+ i++;
+ }
+ c.ugh_b_ = true;
+
+ int i=0;
+ for (; i < loose_col_arr_.size(); i++) {
+ if (loose_col_arr_[i].rank_i_ > c.rank_i_)
+ break;
+ }
+ loose_col_arr_.insert(c,i);
+}
+
void
Spacing_problem::add_ideal(Idealspacing const *i)
{
mtor << "column { ";
if (fixed())
mtor << "fixed at " << fixed_position()<<", ";
- assert(pcol_);
+ assert(pcol_l_);
mtor << "[" << minleft() << ", " << minright() << "]";
mtor <<"}\n";
#endif
}
-Colinfo::Colinfo(Colinfo const&c)
+Colinfo::Colinfo(PCol *col_l, Real const *fixed_C)
{
- fixpos = (c.fixpos)?new Real(*c.fixpos):0;
- pcol_ = c.pcol_;
- width = c.width;
+ if (fixed_C)
+ fixpos_p_.set_l(fixed_C);
+ ugh_b_ = false;
+ pcol_l_ = col_l;
+ width = pcol_l_->width();
}
-Colinfo::Colinfo(PCol const *col_p, Real const *fixed_r_p )
-{
- fixpos = (fixed_r_p)? new Real(*fixed_r_p) : 0;
- pcol_ = col_p;
- width = pcol_->width();
-}
-
-Colinfo::~Colinfo()
-{
- delete fixpos;
-}
Colinfo::Colinfo()
{
- pcol_=0;
- fixpos = 0;
-}
-void
-Colinfo::operator=(Colinfo const&c )
-{
- delete fixpos;
- fixpos = (c.fixpos)?new Real(*c.fixpos):0;
- pcol_ = c.pcol_;
- width = c.width;
+ ugh_b_ = false;
+ pcol_l_ =0;
}
PCol::PCol(PCol *parent)
{
+ error_mark_b_ = false;
daddy_l_ = parent;
prebreak_p_=0;
postbreak_p_=0;
}
void
-PScore::set_breaking(Array<Col_hpositions> breaking)
+PScore::set_breaking(Array<Col_hpositions> const &breaking)
{
for (int j=0; j < breaking.size(); j++) {
- Array<PCol*> &curline(breaking[j].cols);
- Array<Real> &config(breaking[j].config);
+ const Array<PCol*> &curline(breaking[j].cols);
+ const Array<PCol*> &errors(breaking[j].error_col_l_arr_);
+ const Array<Real> &config(breaking[j].config);
Line_of_score *s_p = new Line_of_score(curline,this);
+ s_p->error_mark_b_ = breaking[j].ugh_b_;
lines.bottom().add(s_p);
for (int i=0; i < curline.size(); i++){
curline[i]->hpos = config[i];
}
+ for (int i=0; i < errors.size(); i++)
+ errors[i]->error_mark_b_ = true;
}
}
+/*
+ scoreline.cc -- implement Line_of_score
+
+ source file of the LilyPond music typesetter
+
+ (c) 1996, 1997 Han-Wen Nienhuys <hanwen@stack.nl>
+*/
+
#include "scoreline.hh"
#include "staffline.hh"
#include "dimen.hh"
Line_of_score::TeXstring() const
{
String s("\\vbox{%<- line of score\n");
+ if (error_mark_b_)
+ s+= "\\scorelineerrormark";
for (iter_top(staffs,sc); sc.ok(); sc++){
s += sc->TeXstring();
if ((sc+1).ok())
Line_of_score::Line_of_score(Array<PCol *> sv,
PScore *ps)
{
+ error_mark_b_ = 0;
pscore_l_ = ps;
for (int i=0; i< sv.size(); i++) {
PCol *p=(PCol *) sv[i];
// moveover
if (delta)
s +=String( "\\kern ") + print_dimen(delta);
-
+ if (cc->error_mark_b_) {
+ s += String("\\columnerrormark");
+ }
// now output the items.
for (iter_top(cc->its,i); i.ok(); i++) {
if (i->pstaff_l_ == pstaff_l_)
Stem::brew_molecule_p()const
{
Molecule *out =0;
- if (invisible_b() && ! rest_l_arr_.size())
- warning("Empty stem. Ugh!");
-
if ( invisible_b() )
return Staff_elem::brew_molecule_p();
// try to solve
if (!feasible(current.cols)) {
- if (!minimum.cols.size())
- error("sorry, this measure is too long, breakpoint: "
- + String(break_idx_i) );
- current.energy = INFTY; // make sure we go back
+ if (!minimum.cols.size()) {
+ warning("Ugh, this measure is too long, breakpoint: "
+ + String(break_idx_i) +
+ " (generating stupido solution)");
+ current = stupid_solution(current.cols);
+ current.energy = - 1; // make sure we break out.
+ } else
+ current.energy = INFTY; // make sure we go back
} else {
current = solve_line(current.cols);
current.print();
}
// update minimum, or backup.
- if (current.energy < minimum.energy) {
+ if (current.energy < minimum.energy || current.energy < 0) {
minimum = current;
} else { // we're one col too far.
break_idx_i--;
ifdef alldeps
rm -f $(alldeps)
endif
+ rm -f core
ifdef SUBDIRS
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i clean; done
endif
Begin3
Title: LilyPond
-Version: 0.0.61
-Entered-date: 05/12/97
+Version: 0.0.62
+Entered-date: 05/14/97
Description: LilyPond is a program which converts a music-script (mudela) into
TeX output, or MIDI to produce multi-staff scores. Features include multiple
meters, clefs, keys, lyrics, versatile input-language, cadenzas
jan@digicash.com (Jan Nieuwenhuizen)
Maintained-by: hanwen@stack.nl (Han-Wen Nienhuys)
Primary-site: pcnov095.win.tue.nl /pub/lilypond/
- 300k lilypond-0.0.61.tar.gz
+ 300k lilypond-0.0.62.tar.gz
Alternate-site:
Original-site:
Platform: unix/win32, GNU C++
Name: lilypond
-Version: 0.0.61
+Version: 0.0.62
Release: 1
Copyright: GPL
Group: Applications/Publishing
-Source0: pcnov095.win.tue.nl:/pub/lilypond/lilypond-0.0.61.tar.gz
+Source0: pcnov095.win.tue.nl:/pub/lilypond/lilypond-0.0.62.tar.gz
Summary: A preprocessor to make TeX typeset music.
URL: http://www.stack.nl/~hanwen/lilypond
Packager: Han-Wen Nienhuys <hanwen@stack.nl>
Buildroot: /tmp/lilypond_build
%description
-LilyPond is a program which converts a music-script (mudela) into
-TeX output, or MIDI to produce multi-staff scores. Features include multiple
-meters, clefs, keys, lyrics, versatile input-language, cadenzas
-beams, slurs, triplets, multiple voices.
+GNU LilyPond is a program which converts a music-script
+(mudela) into TeX output, or MIDI to produce multi-staff
+scores. Features include multiple meters, clefs, keys, lyrics,
+versatile input-language, cadenzas beams, slurs, triplets, multiple
+voices.
%prep
%setup
configure --enable-checking --disable-debugging --enable-printing --prefix=/usr --enable-optimise --enable-shared
make all
%install
+rm -rf $RPM_BUILD_ROOT
strip bin/lilypond bin/mi2mu
make prefix="$RPM_BUILD_ROOT/usr" install
%files
-%doc Documentation/out/AUTHORS.text Documentation/out/CodingStyle.text Documentation/out/INSTALL.text Documentation/out/MANIFESTO.text Documentation/out/convert-mudela.text Documentation/out/error.text Documentation/out/examples.text Documentation/out/faq.text Documentation/out/index.text Documentation/out/language.text Documentation/out/lilygut.text Documentation/out/lilypond.text Documentation/out/mi2mu.text Documentation/out/mudela.text input/cadenza.ly input/collisions.ly input/coriolan-alto.ly input/error.ly input/header.ly input/kortjakje.ly input/pedal.ly input/rhythm.ly input/scales.ly input/scripts.ly input/scsii-menuetto.ly input/scsii-menuetto.tex input/slurs.ly input/standchen.ly input/standchen.tex input/toccata-fuga-E.ly input/twinkle.ly input/wohltemperirt.ly Documentation/lelie_logo.gif
+%doc Documentation/out/AUTHORS.text Documentation/out/CodingStyle.text Documentation/out/INSTALL.text Documentation/out/MANIFESTO.text Documentation/out/convert-mudela.text Documentation/out/error.text Documentation/out/faq.text Documentation/out/index.text Documentation/out/language.text Documentation/out/lilygut.text Documentation/out/lilypond.text Documentation/out/mi2mu.text Documentation/out/mudela.text input/cadenza.ly input/collisions.ly input/coriolan-alto.ly input/error.ly input/header.ly input/keys.ly input/kortjakje.ly input/pedal.ly input/rhythm.ly input/scales.ly input/scripts.ly input/scsii-menuetto.ly input/scsii-menuetto.tex input/slurs.ly input/standchen.ly input/standchen.tex input/toccata-fuga-E.ly input/twinkle.ly input/wohltemperirt.ly Documentation/lelie_logo.gif
/usr/bin/convert-mudela
/usr/bin/lilypond
/usr/lib/libflower.so
Buildroot: /tmp/lilypond_build
%description
-LilyPond is a program which converts a music-script (mudela) into
-TeX output, or MIDI to produce multi-staff scores. Features include multiple
-meters, clefs, keys, lyrics, versatile input-language, cadenzas
-beams, slurs, triplets, multiple voices.
+GNU LilyPond is a program which converts a music-script
+(mudela) into TeX output, or MIDI to produce multi-staff
+scores. Features include multiple meters, clefs, keys, lyrics,
+versatile input-language, cadenzas beams, slurs, triplets, multiple
+voices.
%prep
%setup
configure --enable-checking --disable-debugging --enable-printing --prefix=/usr --enable-optimise --enable-shared
make all
%install
+rm -rf $RPM_BUILD_ROOT
strip bin/lilypond bin/mi2mu
make prefix="$RPM_BUILD_ROOT/usr" install
%files
MAJOR_VERSION = 0
MINOR_VERSION = 0
-PATCH_LEVEL = 14
+PATCH_LEVEL = 15
# use to send patches, always empty for released version:
-MY_PATCH_LEVEL = # include separator: "-1" or ".a"
+MY_PATCH_LEVEL =
#
#
-include /dev/null $(DEPFILES)
#
+localclean:
+ rm -f $(outdir)/{midi-parser,midi-lexer}.*
class Midi_note : public Midi_event {
public:
- int const c0_pitch_i_c_ = 60;
+// int const c0_pitch_i_c_ = 60; // huh?
+ int const c0_pitch_i_c_ = 48;
Midi_note( String name_str, Duration dur );
virtual Moment mom();
void process();
private:
- IPointerList<Midi_track*> midi_track_p_list_;
+ IPointer_list<Midi_track*> midi_track_p_list_;
int format_i_;
int tracks_i_;
int tempo_i_;
String name_str_;
Midi_tempo* midi_tempo_p_;
Midi_time* midi_time_p_;
+ int number_i_;
private:
- void add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom );
+ void add_begin_at( Pointer_list<Midi_voice*>& open_voices_r, Moment mom );
int check_begin_bar_i( Moment now_mom, int open_bar_i );
int check_end_bar_i( Moment now_mom, int open_bar_i );
Midi_voice* get_free_midi_voice_l( Moment mom );
- void remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom );
+ void remove_end_at( Pointer_list<Midi_voice*>& open_voices_r, Moment mom );
void output_mudela_begin_bar( Lily_stream& lily_stream_r, Moment now_mom, int bar_i );
void output_mudela_rest( Lily_stream& lily_stream_r, Moment begin_mom, Moment end_mom );
void output_mudela_rest_remain( Lily_stream& lily_stream_r, Moment mom );
- IPointerList<Track_column*> tcol_p_list_;
- IPointerList<Midi_voice*> midi_voice_p_list_;
- int number_i_;
-
+ IPointer_list<Track_column*> tcol_p_list_;
+ IPointer_list<Midi_voice*> midi_voice_p_list_;
};
#endif // MIDI_TRACK_HH
//
// copyright 1997 Jan Nieuwenhuizen <jan@digicash.com>
-/// (midi_voice)
#ifndef MIDI_VOICE_HH
#define MIDI_VOICE_HH
+/// (midi_voice)
class Midi_voice {
public:
Midi_voice( Moment begin_mom );
Moment begin_mom();
Moment end_mom();
- String mudela_str( Moment from_mom, Moment to_mom, bool multiple_bo );
+ String mudela_str( Moment to_mom, Moment to_mom, bool multiple_bo );
+ // ARE you sure? ^^ ^^
private:
- Moment begin_mom_;
- IPointerList<Midi_event*> midi_event_p_list_;
+ int events_i_;
+ Moment end_mom_;
+ Moment begin_mom_;
+ IPointer_list<Midi_event*> midi_event_p_list_;
};
#endif // MIDI_VOICE_HH
Moment mom();
//private:
- IPointerList<Midi_event*> midi_event_p_list_;
+ IPointer_list<Midi_event*> midi_event_p_list_;
Moment mom_;
};
*os_p_ << "% from input file: ";
*os_p_ << midi_parser_l_g->filename_str_;
*os_p_ << "\n\n";
- *os_p_ << "\\version \"0.0.58\";\n";
+ *os_p_ << "\\version \"0.0.57\";\n";
}
/*
snapnie: dit kan toch automaties? Zie ook dstream.
" -d, --debug print lots of debugging stuff\n"
" -h, --help this help\n"
" -I, --include=DIR add DIR to search path\n"
- " -n, --no-silly assume no plets or double dots, smallest is 16\n"
+ " -n, --no-silly assume no plets or double dots, smallest is 32\n"
" -o, --output=FILE set FILE as default output\n"
" -p, --no-plets assume no plets\n"
" -q, --quiet be quiet\n"
"\n"
"Mi2mu, translate midi to mudela.\n"
"Copyright (C) 1997 by\n"
- " Han-Wen Nienhuys <hanwen@stack.nl>\n"
-// "Contributors\n"
" Jan Nieuwenhuizen <jan@digicash.com>\n"
+ " Han-Wen Nienhuys <hanwen@stack.nl>\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"
case 'n':
Duration_convert::no_double_dots_b_s = true;
Duration_convert::no_triplets_b_s = true;
- Duration_convert::no_smaller_than_i_s = 16;
+ Duration_convert::no_smaller_than_i_s = 32;
break;
case 'o':
output_str = getopt_long.optarg;
}
// statics Midi_note
-bool const Midi_note::simple_plet_b_s = false;
+/*
+ this switch can be used to write simple plets like
+ c4*2/3
+ as
+ \plet{ 2/3 } c4 \plet{ 1/1 }
+ */
+bool const Midi_note::simple_plet_b_s = true;
Midi_note::Midi_note( String name_str, Duration dur )
{
Midi_score::output_mudela( String filename_str )
{
tor( NORMAL_ver ) << "Lily output to " << filename_str << " ..." << endl;
+
+ // ugh, ugly midi type 1 fix
+ if ( ( midi_track_p_list_.size() == 1 ) && !midi_track_p_list_.top()->number_i_ )
+ midi_track_p_list_.top()->number_i_ = 1;
int track_i = 0;
Lily_stream lily_stream( filename_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_ );
+ name_str_ = track_name_str;
midi_time_p_ = new Midi_time( 4, 2, 24, 8 );
midi_tempo_p_ = new Midi_tempo( 1000000 );
tcol_p_list_.bottom().add( new Track_column( Moment( 0 ) ) );
}
void
-Midi_track::add_begin_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
+Midi_track::add_begin_at( Pointer_list<Midi_voice*>& open_voices_r, Moment mom )
{
for ( PCursor<Midi_voice*> i( midi_voice_p_list_.top() ); i.ok(); i++ )
if ( i->begin_mom() == mom ) {
return midi_voice_l;
}
-// too much red tape?
String
Midi_track::name_str()
{
- return name_str_;
+ if ( name_str_.length_i() )
+ return name_str_;
+ return String( "track" ) + String( number_i_ );
}
Moment
void
Midi_track::process()
{
+ /*
+ columns to voices
+ */
int bar_i = 1;
for ( PCursor<Track_column*> i( tcol_p_list_.top() ); i.ok(); i++ ) {
int begin_bar_i = check_begin_bar_i( i->mom(), bar_i );
void
Midi_track::output_mudela( Lily_stream& lily_stream_r )
{
- lily_stream_r << name_str_ << " = \\melodic{";
+ lily_stream_r << name_str() << " = \\melodic{";
lily_stream_r.indent();
lily_stream_r << "% midi copyright:" << copyright_str_;
lily_stream_r.newline();
int bar_i = 0;
- PointerList<Midi_voice*> open_voices;
+ Pointer_list<Midi_voice*> open_voices;
Moment now_mom = 0.0;
- /// ugh, avoid status track 0...
+ Real now_f = now_mom;
+ Real begin_f = 0;
+ Real end_f = end_mom();
+ Real then_f;
+
+ /*
+ now we step through time while writing all voices
+
+ we can only output time slices that have a constant
+ number of open voices; each begin or end of a voice
+ starts or ends a chord or multivoice
+
+ [todo]
+ voice defragmentation/concatenation could make this
+ lost blonder
+ */
+
+ bool start_of_track_bo = true;
+
+ /// ugh, avoid status track 0 full of rests...
while ( number_i_ && ( now_mom < end_mom() ) ) {
int begin_bar_i = check_begin_bar_i( now_mom, bar_i );
if ( begin_bar_i )
tor( DEBUG_ver ) << "begin: " << begin_mom << " end: " << end_mom << endl;
tor( DEBUG_ver ) << "slice: " << now_mom << ", " << then_mom << endl;
-// rests, ugh
- String str;
-// if ( !open_voices.size() )
-// output_mudela_rest( lily_stream_r, now_mom, then_mom );
+ now_f = now_mom;
+ begin_f = begin_mom;
+ end_f = end_mom;
+ then_f = then_mom;
+
+// ugh, rests
+// checking for no open voice does not work for initial rests.
+// for some reason the voice is open, but does not procuce notes?
if ( open_voices.size() > 1 )
lily_stream_r << "< ";
- for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
-// lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
- str += i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
- if ( str.length_i() )
- lily_stream_r << str;
- else
- output_mudela_rest( lily_stream_r, now_mom, then_mom );
+ if ( start_of_track_bo ) {
+ start_of_track_bo = false;
+ String str;
+ for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
+ lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
+ if ( str.length_i() )
+ lily_stream_r << str;
+ else
+ output_mudela_rest( lily_stream_r, now_mom, then_mom );
+ }
+ else {
+ for ( PCursor<Midi_voice*> i( open_voices.top() ); i.ok(); i++ )
+ lily_stream_r << i->mudela_str( now_mom, then_mom, open_voices.size() - 1 );
+ if ( !open_voices.size() )
+ output_mudela_rest( lily_stream_r, now_mom, then_mom );
+ }
+// *lily_stream_r.os_p_ << flush;
if ( open_voices.size() > 1 )
lily_stream_r << "> ";
tor( NORMAL_ver ) << '[' << bar_i << ']' << flush;
lily_stream_r.tnedni();
- lily_stream_r << "} % " << name_str_;
+ lily_stream_r << "} % " << name_str();
lily_stream_r.newline();
}
{
Moment bar_mom = midi_time_p_->bar_mom();
Moment now_mom = begin_mom;
- int begin_bar_i =(int)( now_mom / bar_mom ) + 1;
- Moment remain_mom = now_mom - Moment( begin_bar_i - 1 ) * bar_mom;
- if ( remain_mom > Moment( 0 ) )
- output_mudela_rest_remain( lily_stream_r, remain_mom );
+ int begin_bar_i = (int)( now_mom / bar_mom ) + 1;
int end_bar_i = (int)( end_mom / bar_mom ) + 1;
- now_mom += remain_mom;
+ if ( end_bar_i == begin_bar_i ) {
+ output_mudela_rest_remain( lily_stream_r, end_mom - begin_mom );
+ return;
+ }
+
+ // multiple bars involved
int bar_i = (int)( now_mom / bar_mom ) + 1;
- bar_i = check_end_bar_i( now_mom, bar_i );
- for ( int i = 0; i < end_bar_i - begin_bar_i; i++ ) {
+
+ //fill current bar
+ Moment begin_bar_mom = Moment( begin_bar_i - 1 ) * bar_mom;
+ if ( now_mom > begin_bar_mom ) {
+ int next_bar_i = (int)( now_mom / bar_mom ) + 2;
+ Moment next_bar_mom = Moment( next_bar_i - 1 ) * bar_mom;
+ assert( next_bar_mom <= end_mom );
+
+ Moment remain_mom = next_bar_mom - now_mom;
+ if ( remain_mom > Moment( 0 ) ) {
+ output_mudela_rest_remain( lily_stream_r, remain_mom );
+ now_mom += remain_mom;
+ }
+
+ bar_i = check_end_bar_i( now_mom, bar_i );
+ }
+
+ // fill whole bars
+ int count_i = end_bar_i - bar_i;
+ for ( int i = 0; i < count_i; i++ ) {
int begin_bar_i = check_begin_bar_i( now_mom, bar_i );
if ( begin_bar_i )
output_mudela_begin_bar( lily_stream_r, now_mom, begin_bar_i );
lily_stream_r << "r1 ";
+// *lily_stream_r.os_p_ << flush;
tor( NORMAL_ver ) << begin_bar_i << flush;
bar_i = check_end_bar_i( now_mom, bar_i );
now_mom += bar_mom;
}
+
// use "int i" here, and gcc 2.7.2 hits internal compiler error
int ii = check_begin_bar_i( now_mom, bar_i );
if ( ii )
output_mudela_begin_bar( lily_stream_r, now_mom, ii );
- bar_i = check_end_bar_i( now_mom, bar_i );
- remain_mom = end_mom - Moment( end_bar_i - 1 ) * bar_mom;
- if ( remain_mom > Moment( 0 ) )
+// bar_i = check_end_bar_i( now_mom, bar_i );
+
+ Moment remain_mom = end_mom - Moment( end_bar_i - 1 ) * bar_mom;
+ if ( remain_mom > Moment( 0 ) ) {
output_mudela_rest_remain( lily_stream_r, remain_mom );
+ now_mom += remain_mom;
+ }
+ assert( now_mom == end_mom );
}
-
void
Midi_track::output_mudela_rest_remain( Lily_stream& lily_stream_r, Moment mom )
{
- int type_i = 2;
- while ( mom > Moment( 0 ) ) {
- Duration dur( type_i );
- Moment type_mom = Duration_convert::dur2_mom( dur );
- int count_i = (int)( mom / type_mom );
- for( int i = 0; i < count_i; i++ )
- lily_stream_r << "r" << dur.str() << " ";
- type_i *= 2;
- mom -= Moment( count_i ) * type_mom;
- if ( Duration_convert::no_smaller_than_i_s
- && ( type_i > Duration_convert::no_smaller_than_i_s ) )
- break;
+ if ( Duration_convert::no_quantify_b_s ) {
+ Duration dur = Duration_convert::mom2_dur( mom );
+ lily_stream_r << "r" << dur.str() << " ";
+// assert( mom == dur.mom() );
+ assert( mom == dur.length() );
+ return;
}
-
+
+ Duration dur = Duration_convert::mom2standardised_dur( mom );
+ if ( dur.type_i_ )
+ lily_stream_r << "r" << dur.str() << " ";
}
void
-Midi_track::remove_end_at( PointerList<Midi_voice*>& open_voices_r, Moment mom )
+Midi_track::remove_end_at( Pointer_list<Midi_voice*>& open_voices_r, Moment mom )
{
for ( PCursor<Midi_voice*> i( open_voices_r.top() ); i.ok(); i++ )
// if ( i->end_mom() == mom ) { }
Midi_voice::Midi_voice( Moment begin_mom )
{
begin_mom_ = begin_mom;
+ end_mom_ = begin_mom;
+ events_i_ = 0;
}
void
Moment
Midi_voice::end_mom()
{
+// if ( events_i_ == midi_event_p_list_.length_i() )
+ if ( events_i_ == midi_event_p_list_.size() )
+ return end_mom_;
Moment now_mom = begin_mom_;
tor( DEBUG_ver ) << now_mom << ", ";
for ( PCursor<Midi_event*> i( midi_event_p_list_.top() ); i.ok(); i++ ) {
now_mom += i->mom();
}
tor( DEBUG_ver ) << endl;
- return now_mom;
+ end_mom_ = now_mom;
+// events_i_ = midi_event_p_list_.length_i();
+ events_i_ = midi_event_p_list_.size();
+ return end_mom_;
}
String
String
mi2mu_version_str()
{
- return String ( "This is " ) + mi2mu_version_sz()
+ return String( mi2mu_version_sz())
+ "/" + flower_version_sz()
+ " of " + __DATE__ + " " + __TIME__;
}
\mdef\eighthrest{63}
\mdef\sixteenthrest{64}
\mdef\thirtysecondrest{65}
+\mdef\sixtyfourthrest{66}
+\mdef\hundredtwentyeighthrest{67}
\mdef\sharp{52}
\mdef\flat{50}
\mdef\natural{54}
\mdef\cbassclef{74}
\mdef\caltoclef{76}
-\mdef\deigthflag{45}
+\mdef\deighthflag{45}
\mdef\dsixteenthflag{46}
\mdef\dthirtysecondflag{47}
+\mdef\dsixtyfourthflag{48}
+\mdef\dhundredtwentyeighthflag{49}
% pointing up
-\mdef\ueigthflag{40}
+\mdef\ueighthflag{40}
\mdef\usixteenthflag{41}
\mdef\uthirtysecondflag{42}
+\mdef\usixtyfourthflag{43}
+\mdef\uhundredtwentyeighthflag{44}
\maccentdef\repeatcolon{55}{2/1}
\def\emptybar{}
% bottom at baseline
\def\linestafsym#1#2{\leftalign{\botalign{\lines{#1}{#2}}}}
-\def\eigthflag{\topalign{\ueigthflag}}
+\def\eighthflag{\topalign{\ueighthflag}}
\def\sixteenthflag{\topalign{\usixteenthflag}}
\def\thirtysecondflag{\topalign{\uthirtysecondflag}}
+\def\sixtyfourthflag{\topalign{\usixtyfourthflag}}
+\def\hundredtwentyeighthflag{\topalign{\uhundredtwentyeighthflag}}
\def\cquartrest{\vertcenter\quartrest}
\def\ceighthrest{\vertcenter\eighthrest}
\def\csixteenthrest{\vertcenter\sixteenthrest}
\def\cthirtysecondrest{\vertcenter\thirtysecondrest}
+\def\csixtyfourthrest{\vertcenter\sixtyfourthrest}
+\def\chundredtwentyeighthrest{\vertcenter\hundredtwentyeighthrest}
\def\lsingledot{\kern-\notewidth\singledot}
\def\ldoubledot{\kern-\notewidth\doubledot}
+\def\columnerrormark{\placebox{-5pt}{0pt}{\bf C!}}
+\def\linescoreerrormark{\placebox{0pt}{-10pt}{\bf L!}}