summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHan-Wen Nienhuys <hanwen@xs4all.nl>1996-11-28 12:02:01 +0100
committerHan-Wen Nienhuys <hanwen@xs4all.nl>1996-11-28 12:02:01 +0100
commitfc22f69328fd2d5030bb1feff8d0f6da37e8217d (patch)
tree9e9c59c8c0c104cf4388f728b19f0e9be7b6991d
parentc3fe80ddeb9acfcf5d569fcef1caaef6ef7a01fb (diff)
release: 0.0.8
-rw-r--r--.dstreamrc3
-rw-r--r--Documentation/CodingStyle (renamed from CodingStyle)0
-rw-r--r--Documentation/Makefile4
-rw-r--r--Documentation/algorithms98
-rw-r--r--Makefile19
-rw-r--r--README9
-rw-r--r--Sources.make7
-rw-r--r--TODO13
-rw-r--r--calcideal.cc3
-rw-r--r--flower/Makefile4
-rw-r--r--flower/README10
-rw-r--r--flower/Sources.make5
-rw-r--r--flower/TODO7
-rw-r--r--flower/cursor.cc31
-rw-r--r--flower/cursor.hh2
-rw-r--r--flower/fproto.hh38
-rw-r--r--flower/interval.cc18
-rw-r--r--flower/interval.hh58
-rw-r--r--flower/lgetopt.cc2
-rw-r--r--flower/pcursor.hh6
-rw-r--r--flower/plist.hh2
-rw-r--r--flower/textstr.hh4
-rw-r--r--identifier.cc7
-rw-r--r--identifier.hh8
-rw-r--r--item.cc13
-rw-r--r--item.hh19
-rw-r--r--lexer.hh1
-rw-r--r--lilyponddefs.tex26
-rw-r--r--lookupsyms.cc24
-rw-r--r--lookupsyms.hh7
-rw-r--r--maartje.ly2
-rw-r--r--melodicstaff.cc24
-rw-r--r--misc.cc22
-rw-r--r--misc.hh6
-rw-r--r--notehead.cc67
-rw-r--r--notehead.hh38
-rw-r--r--paper.cc23
-rw-r--r--paper.hh4
-rw-r--r--parser.y14
-rw-r--r--pscore.cc18
-rw-r--r--pscore.hh6
-rw-r--r--request.cc3
-rw-r--r--rhythmstaff.cc18
-rw-r--r--score.cc7
-rw-r--r--simpleprint.cc7
-rw-r--r--spanner.cc1
-rw-r--r--spanner.hh5
-rw-r--r--stem.cc15
-rw-r--r--stem.hh21
-rw-r--r--symbol.ini5
-rw-r--r--table.cc12
-rw-r--r--tex.hh1
-rw-r--r--tstream.cc5
-rw-r--r--voice.hh2
54 files changed, 646 insertions, 128 deletions
diff --git a/.dstreamrc b/.dstreamrc
index 7dcded772c..bb7e1bb71d 100644
--- a/.dstreamrc
+++ b/.dstreamrc
@@ -18,4 +18,5 @@ Command 1
Score_commands 1
Note_req 1
Rhythmic_req 1
-Rest_req 1 \ No newline at end of file
+Rest_req 1
+delete_identifiers 1
diff --git a/CodingStyle b/Documentation/CodingStyle
index c5d730c0a6..c5d730c0a6 100644
--- a/CodingStyle
+++ b/Documentation/CodingStyle
diff --git a/Documentation/Makefile b/Documentation/Makefile
new file mode 100644
index 0000000000..da2847045e
--- /dev/null
+++ b/Documentation/Makefile
@@ -0,0 +1,4 @@
+
+DOCFILES=CodingStyle algorithms Makefile
+dist:
+ ln $(DOCFILES) $(DDIR)/Documentation/ \ No newline at end of file
diff --git a/Documentation/algorithms b/Documentation/algorithms
new file mode 100644
index 0000000000..f422332e41
--- /dev/null
+++ b/Documentation/algorithms
@@ -0,0 +1,98 @@
+Date: Tue, 5 Nov 1996 00:01:32 +0100
+From: Werner Icking <Werner.Icking@gmd.de>
+To: hanwen@stack.urc.tue.nl
+Cc: dsimons@logicon.com
+Subject: Re: font sizes.
+
+> Date: Mon, 4 Nov 1996 22:37:54 +0100 (MET)
+> From: Han-Wen Nienhuys <hanwen@stack.urc.tue.nl>
+> >
+> >There were different schemes when music was typeset by hand. If I remember
+> >right Harder uses another scheme that Gomberg. Both scheme may be used
+>
+> Who are Harder and Gomberg? Do you have references?
+
+Both are mentioned in the master thesis by Steinbach & Schofer who
+invented M(u)TeX, the grandmother of all M...TeXs. The Musiclibrary
+in Bonn has the harder (printed in 1948?) and there are not many books
+I liked more to own.
+
+The master thesis should be available at the CTAN archives under MuTeX
+or MTEX maybe subdirectory DIPL (for Diplom). I have the TEX-source
+and I may pack it to ftp.gmd.de if you are interested and can't find it
+on CTAN.
+================================================================
+
+[breaking lines]
+>
+>Incidentally, I use a different approach in PMX, starting with the
+>total number of systems for the piece instead of assuming a starting
+>physical value for \elemskip. That's equivalent to setting the
+>physical length of the whole piece if laid out in one long line.
+>Knowing the total amount of scalable and fixed space I compute a
+>starting physical value for \elemskip. I use that to get how many
+>bars go in the first line. Then I force a line break there, remove
+>those bars and their scalable and fixed space from the accounting, and
+>start over with the second line, etc.
+
+
+Since you are getting into technical details, I will show mine too: I
+think my way is the most elegant algorithm i've seen so far. Some
+terminology: I call a vertical group of symbols (notes) which start at
+the same time a "column". Each line of a score has notes in it,
+grouped in columns. The difference in starting time between those
+columns makes it possible to determine ideal distances between those
+columns.
+
+Example:
+
+ time ----->
+
+ col1 col2 col3 col4
+
+
+voice1 1 1
+
+voice2 2 2 2 2
+
+
+(1 is a whole note, 2 a half note.)
+
+time_difference (col1 , col2) = 0.5 wholes,
+time_difference (col1 , col3) = 1 wholes,
+time_difference (col2 , col3) = 0.5 wholes,
+etc.
+
+these differences are translated into ideal distances (these translations
+have been the subject of discussion in this thread).
+
+ distance (col1,col2) = 10 pt
+ distance (col1,col3) = 14.1 pt
+ distance (col2,col3) = 10 pt
+ etc.
+
+as you can see, these distance are conflicting. So instead of
+satisfying all those ideals simultaneously, a compromise is sought.
+
+This is Columbus' egg: LilyPond attaches "springs" to each
+column-pair. each spring has an equilibrium-position which is equal to
+the above mentioned distance, so
+
+ spring (col1, col2) and spring(col2,col3) try to push column 1
+and 3 away (to a distance of 20pt) from each other, whereas the spring
+between col 1 and col 3 tries to pull those two together (to a
+distance of 14.1 pt). The net result of this pushing and pulling is an
+equilibrium situation (the pushing cancels the pulling), which can be
+calculated as the solution of Quadratic program: it is the solution
+with minimum potential energy, for you physicists out there.
+
+This algorithm for doing one line, gives a "badness" parameter for
+each line (the potential energy). Now one can use TeX's algorithm for
+making paragraphs (using this new version of "badness"): one should
+try to minimise the overall badness of a paragraph. LilyPond also uses the
+concept of pre- and post-breaks.
+
+(actually, it is a bit more complicated: each column also has a
+minimum distance to other columns, to prevent symbols from running
+into symbols of other columns.)
+
diff --git a/Makefile b/Makefile
index 4f747e6c95..2d8fa8a3ca 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
MAJVER=0
MINVER=0
-PATCHLEVEL=7
+PATCHLEVEL=8
+
+TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
#
#
@@ -13,6 +15,7 @@ obs=$(cc:.cc=.o)
#dist
+.EXPORT_ALL_VARIABLES:
DOCDIR=docdir
VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
@@ -22,9 +25,8 @@ othersrc=lexer.l parser.y
SCRIPTS=make_version make_patch genheader
IFILES=dimen.tex symbol.ini suzan.ly maartje.ly\
lilyponddefs.tex test.tex .dstreamrc
-OFILES=Makefile Sources.make
-DOC=COPYING README TODO CodingStyle
-DFILES=$(hdr) $(mycc) $(othersrc) $(OFILES) $(IFILES) $(SCRIPTS) $(DOC)
+OFILES=Makefile Sources.make COPYING README
+DFILES=$(hdr) $(mycc) $(othersrc) $(OFILES) $(IFILES) $(SCRIPTS)
#compiling
LOADLIBES=-L$(FLOWERDIR) -lflower
@@ -83,11 +85,16 @@ version.hh: Makefile make_version
lexer.cc: lexer.l
$(FLEX) -+ -t $< > $@
-DDIR=$(DNAME)
+DDIR=$(TOPDIR)/$(DNAME)
+SUBDIRS=Documentation
dist:
-mkdir $(DDIR)
ln $(DFILES) $(DDIR)/
- tar cfz $(DNAME).tar.gz $(DDIR)/
+ for a in $(SUBDIRS); \
+ do mkdir $(DDIR)/$$a; \
+ $(MAKE) -C $$a dist;\
+ done
+ tar cfz $(DNAME).tar.gz $(DNAME)/
rm -rf $(DDIR)/
diff --git a/README b/README
index 41c366eec3..fd1c616b3a 100644
--- a/README
+++ b/README
@@ -56,5 +56,12 @@ stacktrace of the crash.
HOW DOES IT WORK
-Use The Source, Luke. If you don't know C++, you can try editing
+* Use The Source, Luke. If you don't know C++, you can try editing
.dstreamrc for copious debugging output.
+
+* see also the subdir Documentation
+
+* The source is commented in the DOC++ style.
+Check out doc++ at
+
+ http://www.ZIB-Berlin.DE/VisPar/doc++/doc++.html
diff --git a/Sources.make b/Sources.make
index fcc62df96c..6e860c07d4 100644
--- a/Sources.make
+++ b/Sources.make
@@ -1,5 +1,5 @@
# -*- Makefile-*-
-# sourcefiles to be shipped. Also for depedencies
+# sourcefiles to be shipped. Also for dependencies
hdr= qlp.hh linespace.hh qlpsolve.hh\
pcol.hh proto.hh pstaff.hh line.hh\
@@ -10,7 +10,8 @@ hdr= qlp.hh linespace.hh qlpsolve.hh\
misc.hh score.hh notename.hh lexer.hh symtable.hh\
symbol.hh main.hh dimen.hh paper.hh lookupsyms.hh\
sccol.hh stcol.hh scommands.hh melodicstaff.hh\
- identifier.hh simplestaff.hh spanner.hh stem.hh
+ identifier.hh simplestaff.hh spanner.hh stem.hh\
+ notehead.hh
mycc= qlp.cc qlpsolve.cc \
break.cc linespace.cc molecule.cc line.cc\
@@ -24,6 +25,6 @@ mycc= qlp.cc qlpsolve.cc \
dimen.cc paper.cc lookupsyms.cc scommands.cc\
sccol.cc stcol.cc getcommands.cc simplestaff.cc\
melodicstaff.cc simpleprint.cc stem.cc\
- spanner.cc\
+ spanner.cc notehead.cc\
template1.cc template2.cc template3.cc\
version.cc \ No newline at end of file
diff --git a/TODO b/TODO
deleted file mode 100644
index 1f96a09b76..0000000000
--- a/TODO
+++ /dev/null
@@ -1,13 +0,0 @@
- * clefs
-
- * beam
-
- * fonttables -> fontdims
-
- * clear IDENTIFIERs
-
- * Paperdef -> fontsize .
-
- * merge Paper, Lookup, Outputfile, and Symtable.
-
- * all places in the code marked TODO! and ugh/ARGH
diff --git a/calcideal.cc b/calcideal.cc
index 1dc0e1d385..8099e0e4c7 100644
--- a/calcideal.cc
+++ b/calcideal.cc
@@ -3,7 +3,6 @@
#include "pscore.hh"
#include "staff.hh"
#include "paper.hh"
-#include "misc.hh"
#include "sccol.hh"
#include "debug.hh"
@@ -50,7 +49,7 @@ Score::calc_idealspacing()
if (sc->musical)
for (int i=0; i < sc->durations.sz(); i++) {
Real d = sc->durations[i];
- Real dist = duration_to_idealspace(d, paper_->whole_width);
+ Real dist = paper_->duration_to_dist(d);
PCol * c2 = find_col(sc->when + d,true)->pcol;
connect_nonmus(sc->pcol, c2, dist);
c2 = find_col(sc->when + d,false)->pcol;
diff --git a/flower/Makefile b/flower/Makefile
index e17cbdb0d8..dffea2fb37 100644
--- a/flower/Makefile
+++ b/flower/Makefile
@@ -1,6 +1,6 @@
MAJVER=1
MINVER=0
-PATCHLEVEL=7
+PATCHLEVEL=8
PACKAGENAME=flower
VERSION=$(MAJVER).$(MINVER).$(PATCHLEVEL)
@@ -26,7 +26,7 @@ clean:
rm -f $(obs) $(staticlib)
realclean: clean
rm -f depend
-DFILES=$(hh) $(cc) $(inl) $(templatecc) Makefile Sources.make TODO
+DFILES=$(hh) $(cc) $(inl) $(templatecc) Makefile Sources.make TODO README
DDIR=$(DNAME)
dist:
diff --git a/flower/README b/flower/README
new file mode 100644
index 0000000000..d33c68f3df
--- /dev/null
+++ b/flower/README
@@ -0,0 +1,10 @@
+This library contains some general purpose routines which aren't
+standardised yet. It was written by:
+
+ Han-Wen Nienhuys <hanwen@stack.nl>
+
+and
+
+ Jan Nieuwenhuizen <jan@digicash.com>
+
+It is licensed under the GNU GPL. \ No newline at end of file
diff --git a/flower/Sources.make b/flower/Sources.make
index 8016e67323..7f2f6441a1 100644
--- a/flower/Sources.make
+++ b/flower/Sources.make
@@ -1,7 +1,7 @@
cc=lgetopt.cc string.cc dataf.cc textdb.cc unionfind.cc \
smat.cc matrix.cc choleski.cc vector.cc dstream.cc\
- matdebug.cc
+ matdebug.cc interval.cc
templatecc=cursor.cc list.cc tsmat.cc plist.cc
inl=findcurs.inl link.inl list.inl cursor.inl plist.inl
@@ -9,5 +9,6 @@ hh=cursor.hh pcursor.hh lgetopt.hh link.hh list.hh dstream.hh \
string.hh stringutil.hh vray.hh textdb.hh textstr.hh assoc.hh\
findcurs.hh unionfind.hh compare.hh handle.hh matrix.hh\
smat.hh vsmat.hh vector.hh real.hh choleski.hh\
- tsmat.hh tvsmat.hh plist.hh associter.hh\
+ tsmat.hh tvsmat.hh plist.hh associter.hh fproto.hh\
+ interval.hh
diff --git a/flower/TODO b/flower/TODO
index 4d0774ff7c..ef0ab6bac6 100644
--- a/flower/TODO
+++ b/flower/TODO
@@ -4,6 +4,8 @@
* efficient copy cons for List
+ * extend Interval
+
* change String::pos
s[s.pos('%')] == '%'
@@ -12,9 +14,10 @@
* use template handle in handle.hh for strings.
- * Restricted cursor/list: make sublist from a list, and use rcursor as if list is as big as the sublist.
+ * Restricted cursor/list: make sublist from a list, and use rcursor
+as if list is as big as the sublist.
- * move towards gnu?
+ * move towards gnu or STL?
parsestream.h
vector.h
diff --git a/flower/cursor.cc b/flower/cursor.cc
index 2a9f885689..75f607dcaa 100644
--- a/flower/cursor.cc
+++ b/flower/cursor.cc
@@ -68,27 +68,38 @@ Cursor<T>::operator -( int i ) const
return r;
}
-
+/*
+ warning: can't use Cursor::operator == (Cursor),
+ since it uses Cursor::operator-(Cursor)
+ */
template<class T>
int
-Cursor<T>::operator-(Cursor<T> c) const
+Cursor<T>::operator-(Cursor<T> rhs) const
{
- assert(c.list == list);
+ assert(rhs.list == list);
int dif = 0;
- Cursor<T> upward(c);
- while (upward.ok() && upward.pointer_ != pointer_) {
- upward++;
+
+ // search from *this on further up (positive difference)
+ Cursor<T> c(*this);
+ while (c.ok() && c.pointer_ != rhs.pointer_) {
+ c--;
dif++;
}
- if (upward.ok())
- return dif;
+ if (c.ok())
+ goto gotcha; // so, sue me.
+
+ // search in direction of bottom. (negative diff)
dif =0;
- while (c.ok()&& c.pointer_ != pointer_) {
+ c=*this;
+ while (c.ok() && c.pointer_ !=rhs.pointer_) {
dif --;
- c--;
+ c++;
}
assert(c.ok());
+
+gotcha:
+ assert((*this - dif).pointer_ == c.pointer_);
return dif;
}
diff --git a/flower/cursor.hh b/flower/cursor.hh
index 4babf96545..6bd4e1895d 100644
--- a/flower/cursor.hh
+++ b/flower/cursor.hh
@@ -107,7 +107,7 @@ private:
template<class T>
inline int cursor_compare(Cursor<T> a,Cursor<T>b)
{
- return b-a;
+ return a-b;
}
template_instantiate_compare(Cursor<T>, cursor_compare, template<class T>);
diff --git a/flower/fproto.hh b/flower/fproto.hh
new file mode 100644
index 0000000000..5241a13dd0
--- /dev/null
+++ b/flower/fproto.hh
@@ -0,0 +1,38 @@
+/*
+ fproto.hh -- typenames in flowerlib
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef FPROTO_HH
+#define FPROTO_HH
+
+template<class T> struct svec;
+template<class T> struct sstack;
+template<class T,class K> struct Assoc;
+template<class T> struct List;
+template<class T> struct PointerList;
+template<class T> struct IPointerList;
+template<class T> struct Cursor;
+template<class T> struct PCursor;
+template<class T> struct Link;
+template<class T> struct Handle ;
+
+
+struct Assoc_ent_ ;
+struct Assoc ;
+struct Assoc_iter ;
+struct Choleski_decomposition ;
+struct Interval ;
+struct long_option_init ;
+struct Getopt_long ;
+struct Matrix ;
+struct StringData ;
+struct String_handle ;
+struct virtual_smat ;
+struct Vector ;
+class Text_stream;
+class Data_file ;
+struct Text_db;
+#endif // FPROTO_HH
+
diff --git a/flower/interval.cc b/flower/interval.cc
new file mode 100644
index 0000000000..b307f4c634
--- /dev/null
+++ b/flower/interval.cc
@@ -0,0 +1,18 @@
+#include <assert.h>
+#include "interval.hh"
+#include <math.h>
+
+const Real INFTY = HUGE;
+
+void
+Interval::set_empty() {
+ min = INFTY;
+ max = -INFTY;
+}
+
+Real
+Interval::length() const {
+ assert(max >= min);
+ return max-min;
+}
+
diff --git a/flower/interval.hh b/flower/interval.hh
new file mode 100644
index 0000000000..950945ca87
--- /dev/null
+++ b/flower/interval.hh
@@ -0,0 +1,58 @@
+/*
+ interval.hh -- part of flowerlib
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef INTERVAL_HH
+#define INTERVAL_HH
+
+#include <assert.h>
+#include "real.hh"
+
+
+/// a Real interval
+struct Interval {
+ Real min, max;
+
+ void translate(Real t) {
+ min += t;
+ max += t;
+ }
+ Real operator[](int j) {
+ if (j==-1)
+ return min;
+ else if (j==1)
+ return max;
+ else
+ assert(false);
+ return 0.0;
+
+ }
+ void unite(Interval h) {
+ if (h.min<min)
+ min = h.min;
+ if (h.max>max)
+ max = h.max;
+ }
+ Real length() const;
+ void set_empty() ;
+ bool empty() { return min > max; }
+ Interval() {
+ set_empty();
+ }
+ Interval(Real m, Real M) {
+ min =m;
+ max = M;
+ }
+ Interval &operator += (Real r) {
+ min += r;
+ max +=r;
+ return *this;
+ }
+};
+
+
+#endif // INTERVAL_HH
+
+
diff --git a/flower/lgetopt.cc b/flower/lgetopt.cc
index ac9a12d035..523d54ee5f 100644
--- a/flower/lgetopt.cc
+++ b/flower/lgetopt.cc
@@ -2,7 +2,7 @@
process command line, GNU style.
- this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.urc.tue.nl>
+ this is (Copyleft) 1996, Han-Wen Nienhuys, <hanwen@stack.nl>
*/
#include <stdio.h>
#include <iostream.h>
diff --git a/flower/pcursor.hh b/flower/pcursor.hh
index 6cc3433e25..5e535300d7 100644
--- a/flower/pcursor.hh
+++ b/flower/pcursor.hh
@@ -17,7 +17,9 @@ struct PCursor : public Cursor<void *> {
PCursor<T> operator -( int no) const {
return PCursor<T> (Cursor<void*>::operator-(no));
}
-
+ int operator -(PCursor<T> op) const {
+ return Cursor<void*>::operator-(op);
+ }
/// make cursor with #no# items further
PCursor<T> operator +( int no) const {
return PCursor<T> (Cursor<void*>::operator+(no));
@@ -45,7 +47,7 @@ don't create PointerList<void*>'s
template<class T>
inline int pcursor_compare(PCursor<T> a,PCursor<T>b)
{
- return cursor_compare(Cursor<void*>(b),Cursor<void*> (a));
+ return cursor_compare(Cursor<void*>(a),Cursor<void*> (b));
}
#include "compare.hh"
diff --git a/flower/plist.hh b/flower/plist.hh
index 1bfc2d4ab4..78df40cb17 100644
--- a/flower/plist.hh
+++ b/flower/plist.hh
@@ -51,7 +51,7 @@ template<class T>
void PL_copy(IPointerList<T*> &dst,IPointerList<T*> const&src);
-#define PL_instantiate(a) L_instantiate(a *); template class PointerList<a*>
+#define PL_instantiate(a) template class PointerList<a*>
#define IPL_instantiate(a) PL_instantiate(a); template class IPointerList<a*>
#include "plist.inl"
diff --git a/flower/textstr.hh b/flower/textstr.hh
index 41a979f27f..c64a989c3c 100644
--- a/flower/textstr.hh
+++ b/flower/textstr.hh
@@ -1,3 +1,6 @@
+#ifndef TEXTSTR_HH
+#define TEXTSTR_HH
+
#include <stdio.h>
#include <ctype.h>
@@ -112,3 +115,4 @@ class Data_file : private Text_stream
exit(1);
}
};
+#endif
diff --git a/identifier.cc b/identifier.cc
index 94d48c8d74..5405d5f710 100644
--- a/identifier.cc
+++ b/identifier.cc
@@ -12,10 +12,15 @@ Identifier::Identifier(String n)
Identifier::~Identifier()
-{
+{
}
Staff_id::~Staff_id()
{
delete staff();
}
+
+Voice_id::~Voice_id()
+{
+ delete voice();
+}
diff --git a/identifier.hh b/identifier.hh
index 0510f181d1..9cb80386c0 100644
--- a/identifier.hh
+++ b/identifier.hh
@@ -18,6 +18,7 @@ struct Identifier
Identifier(String n) ;
virtual ~Identifier();
virtual Staff * staff() { assert(false); }
+ virtual Voice * voice() { assert(false); }
};
struct Staff_id : Identifier {
@@ -26,7 +27,10 @@ struct Staff_id : Identifier {
~Staff_id();
};
-
-
+struct Voice_id : Identifier {
+ Voice_id(String s, Voice*st):Identifier(s) { data = st; }
+ virtual Voice * voice() { return (Voice*)data; }
+ ~Voice_id();
+};
#endif // IDENTIFIER_HH
diff --git a/item.cc b/item.cc
index 4a84f47704..f10187bbb2 100644
--- a/item.cc
+++ b/item.cc
@@ -3,6 +3,19 @@
#include "molecule.hh"
#include "pcol.hh"
+void
+Item::postprocess()
+{
+ // default: do nothing
+}
+
+
+void
+Item::preprocess()
+{
+ // default: do nothing
+}
+
String
Item::TeXstring() const
{
diff --git a/item.hh b/item.hh
index cf3d11c313..b450ab59ea 100644
--- a/item.hh
+++ b/item.hh
@@ -4,8 +4,6 @@
#include "glob.hh"
#include "boxes.hh"
#include "string.hh"
-#include "tex.hh"
-
/// a horizontally fixed size element of the score
struct Item {
@@ -17,7 +15,17 @@ struct Item {
*/
/****************/
+
+ /// do calculations after determining horizontal spacing
+ virtual void postprocess();
+ /// do calculations before determining horizontal spacing
+ virtual void preprocess();
+ /**
+ This is executed directly after the item is added to the
+ PScore
+ */
+
virtual Interval width() const;
virtual Interval height() const;
String TeXstring () const ;
@@ -25,7 +33,12 @@ struct Item {
void print()const;
virtual ~Item();
};
-/** An item must be part of a Column
+/** Item is the datastructure for printables whose width is known
+ before the spacing is calculated
+
+ NB. This doesn't mean an Item has to initialize the output field before
+ spacing calculation.
+
*/
diff --git a/lexer.hh b/lexer.hh
index 31be74169f..ec7c9b929f 100644
--- a/lexer.hh
+++ b/lexer.hh
@@ -12,4 +12,5 @@ int lookup_keyword(String s);
Identifier* lookup_identifier(String s);
void add_identifier(Identifier*i);
+void delete_identifiers();
#endif
diff --git a/lilyponddefs.tex b/lilyponddefs.tex
index 45152140cb..41748636de 100644
--- a/lilyponddefs.tex
+++ b/lilyponddefs.tex
@@ -70,18 +70,26 @@
\vskip 40pt\par\vbox{\hbox to 0pt{\vrule width30pt height1pt\hss}}\par\vskip 40pt
}
\def\interscoreline{\beauty}
-%
-% a staffsymbol with #1 lines, width #2
-% bottom at baseline
-\def\linestafsym#1#2{\vbox to 0pt{\hbox to 0pt%
- {\vbox to 0pt{\vss%
- \kern-\interstaffrule
+
+
+\def\lines#1#2{%
+ \vbox{\kern-\interstaffrule
\n=0\nointerlineskip%
\loop\ifnum\n<#1\advance\n by1%
- \kern\interstaffrule \hrule height \staffrulethickness width#2
+ \kern\interstaffrule
+ \hrule height \staffrulethickness width#2
\repeat
- }%
-\hss}}}
+ }}
+
+\def\toplines#1{ % why space needed here?
+ \vbox to 0pt{\hbox{\kern-6pt\lines{#1}{12pt}}\vss}}
+\def\botlines#1{ % idem ditto
+ \vbox to 0pt{\vss\hbox{\kern-6pt\lines{#1}{12pt}}}}
+
+%
+% a staffsymbol with #1 lines, width #2
+% bottom at baseline
+\def\linestafsym#1#2{\hbox to 0pt{\vbox to 0pt{\vss\lines{#1}{#2}}\hss}}
\def\vcenter#1{\vbox to 0pt{\vss #1\vss}}
\def\topalign#1{\vbox to 0pt{#1\vss}}
diff --git a/lookupsyms.cc b/lookupsyms.cc
index 294f2e9af4..e6ad52ca5a 100644
--- a/lookupsyms.cc
+++ b/lookupsyms.cc
@@ -3,6 +3,7 @@
#include "symtable.hh"
#include "dimen.hh"
#include "tex.hh"
+
void
Lookup::parse(Text_db&t)
{
@@ -55,6 +56,29 @@ Lookup::flag(int j)
return (*symtables_)("flags")->lookup(j);
}
+Symbol
+Lookup::streepjes(int i)
+{
+ assert(i);
+
+ int arg;
+ String idx ;
+ if (i<0) {
+ idx = "botlines";
+ arg = -i;
+ }else {
+ arg = i;
+ idx = "toplines";
+ }
+ Symbol ret = (*symtables_)("streepjes")->lookup(idx);
+
+ svec<String> a;
+ a.add(arg);
+ ret.tex = substitute_args(ret.tex, a);
+
+ return ret;
+}
+
/****************************************************************/
// bare bones.
diff --git a/lookupsyms.hh b/lookupsyms.hh
index f7ac3858ac..1ec0d04d10 100644
--- a/lookupsyms.hh
+++ b/lookupsyms.hh
@@ -15,6 +15,13 @@ struct Lookup {
Parametric_symbol *linestaff(int n);
Parametric_symbol *meter(String);
Parametric_symbol *stem();
+ Symbol streepjes(int pos);
+ /**
+ pos == 3 : 3 lines above staff (extending below note)
+
+ pos == -3: below staff
+ */
+
Symbol ball(int);
Symbol flag(int);
Symbol rest(int);
diff --git a/maartje.ly b/maartje.ly
index 50ce2cb577..e12fc345e6 100644
--- a/maartje.ly
+++ b/maartje.ly
@@ -4,7 +4,7 @@ ritme = rhythmstaff {
}
melody=
melodicstaff {
- voice { $ c2.. r8 r4 r8 r16 r32 r32 d8 e8 f8 g8 ''fis1 a8 b8 'c8 c8 `c8 ``c8 c4 c4 c4 c4 $ }
+ voice { $ ''c2.. r8 r4 r8 r16 r32 r32 d8 e8 f8 g8 ''fis1 a8 b8 'c8 c8 ''c8 ```c8 c4 c4 c4 c4 $ }
}
score {
paper {
diff --git a/melodicstaff.cc b/melodicstaff.cc
index 83e038652f..2937f45dfe 100644
--- a/melodicstaff.cc
+++ b/melodicstaff.cc
@@ -1,6 +1,6 @@
#include "melodicstaff.hh"
#include "stem.hh"
-
+#include "notehead.hh"
#include "paper.hh"
#include "molecule.hh"
#include "linestaff.hh"
@@ -29,15 +29,18 @@ Melodic_column::typeset_command(Command *com, int breakst)
void
Melodic_column::typeset_req(Request *rq)
{
- Item *i =new Item;
- Molecule*m=create_req_mol(rq);
-
+ Item *i ;
if (rq->note()) {
- int h = rq->note()->height();
- Real dy = staff_->paper()->interline()/2;
- m->translate(Offset(0,(h-BOTTOM_POSITION)*dy));
+ Notehead *n =new Notehead((NO_LINES-1)*2);
+ n->balltype = rq->rhythmic()->balltype;
+ n->dots = rq->rhythmic()->dots;
+ n->position = rq->note()->height() - BOTTOM_POSITION;
+ i = n;
+ } else if (rq->rest()) {
+ i =new Item;
+ Molecule*m=create_req_mol(rq);
+ i->output=m;
}
- i->output = m;
typeset_item(i);
}
@@ -49,10 +52,7 @@ Melodic_column::typeset_stem(Stem_req*rq)
int n = the_note->note()->height()-BOTTOM_POSITION;
s->minnote =s->maxnote=n;
s->flag = rq->stem_number;
- s->calculate();
- typeset_item(s);
-
- s->brew_molecole();
+ typeset_item(s);
}
/*
diff --git a/misc.cc b/misc.cc
index 174e4224bc..54746fd836 100644
--- a/misc.cc
+++ b/misc.cc
@@ -12,25 +12,3 @@ int intlog2(int d) {
return i;
}
-double log2(double x) {
- return log(x) /log(2.0);
-}
-
-
-// golden ratio
- const Real PHI = (1+sqrt(5))/2;
-const double ENGRAVERS_SPACE = PHI;
-
-
-
-
-Real
-duration_to_idealspace(Real d, Real w)
-{
- // see Roelofs, p. 57
- return w * pow(ENGRAVERS_SPACE, log2(d));
-}
-
-
-
-
diff --git a/misc.hh b/misc.hh
index 0321113242..64c8ca4102 100644
--- a/misc.hh
+++ b/misc.hh
@@ -1,7 +1,7 @@
#ifndef MISC_HH
#define MISC_HH
-#include "real.hh"
-int intlog2(int d);
-Real duration_to_idealspace(Real d,Real w);
+
+
+
#endif
diff --git a/notehead.cc b/notehead.cc
new file mode 100644
index 0000000000..fe026b1036
--- /dev/null
+++ b/notehead.cc
@@ -0,0 +1,67 @@
+#include "notehead.hh"
+#include "dimen.hh"
+#include "debug.hh"
+#include "pstaff.hh"
+#include "pscore.hh"
+#include "paper.hh"
+#include "lookupsyms.hh"
+#include "molecule.hh"
+
+
+Notehead::Notehead(int ss)
+{
+ staff_size=ss;
+ position = 0;
+ balltype = 0;
+ dots = 0;
+}
+
+void
+Notehead::print()const
+{
+ mtor << "Head "<<balltype<<", position = "<< position << "dots " << dots;
+ Item::print();
+}
+
+void
+Notehead::preprocess()
+{
+ brew_molecole();
+}
+
+void
+Notehead::brew_molecole()
+{
+ assert(pstaff_);
+ assert(!output);
+
+ Paperdef *p = pstaff_->pscore_->paper_;
+
+ Real dy = p->interline()/2;
+ Symbol s = p->lookup_->ball(balltype);
+
+ output = new Molecule(Atom(s));
+ if (dots) {
+ Symbol d = p->lookup_->dots(dots);
+ Molecule dm;
+ dm.add(Atom(d));
+ if (!(position %2))
+ dm.translate(Offset(0,dy));
+ output->add_right(dm);
+ }
+ bool streepjes = (position<-1)||(position > staff_size+1);
+ if (streepjes) {
+ int dir = sgn(position);
+ int s =(position<-1) ? -((-position)/2): (position-staff_size)/2;
+ Symbol str = p->lookup_->streepjes(s);
+ Molecule sm;
+ sm.add(Atom(str));
+ if (position % 2)
+ sm.translate(Offset(0,-dy* dir));
+ output->add(sm);
+ }
+
+
+ output->translate(Offset(0,dy*position));
+}
+
diff --git a/notehead.hh b/notehead.hh
new file mode 100644
index 0000000000..b694e95af8
--- /dev/null
+++ b/notehead.hh
@@ -0,0 +1,38 @@
+/*
+ notehead.hh -- part of LilyPond
+
+ (c) 1996 Han-Wen Nienhuys
+*/
+
+#ifndef NOTEHEAD_HH
+#define NOTEHEAD_HH
+#include "item.hh"
+
+/// ball at the end of the stem
+struct Notehead : public Item
+{
+ int position;
+ int staff_size;
+ int dots;
+ int balltype;
+
+ /****************/
+ void preprocess();
+
+ Notehead(int staff_size);
+ /**
+ position of top line (5 linestaff: 8)
+ */
+ void print()const;
+private:
+ void brew_molecole();
+};
+/**
+ takes care of:
+
+ * help lines
+ * proper placing of dots
+
+ */
+#endif // NOTEHEAD_HH
+
diff --git a/paper.cc b/paper.cc
index a0e533f626..89f9a9fe5c 100644
--- a/paper.cc
+++ b/paper.cc
@@ -1,16 +1,33 @@
+#include <math.h>
+
#include "paper.hh"
#include "debug.hh"
#include "lookupsyms.hh"
#include "dimen.hh"
#include "textdb.hh"
+double log2(double x) {
+ return log(x) /log(2.0);
+}
+
+
+// golden ratio
+const Real PHI = (1+sqrt(5))/2;
+
+// see Roelofs, p. 57
+Real
+Paperdef::duration_to_dist(Real d)
+{
+ return whole_width * pow(geometric_, log2(d));
+}
+
Paperdef::Paperdef()
{
- linewidth = convert_dimen(15,"cm"); // in cm for now
- whole_width= convert_dimen(2,"cm");
lookup_ = new Lookup();
parse();
-
+ linewidth = convert_dimen(15,"cm"); // in cm for now
+ whole_width= 6*note_width();
+ geometric_ = PHI;
}
void
diff --git a/paper.hh b/paper.hh
index e96d9b089f..ffe4f795a8 100644
--- a/paper.hh
+++ b/paper.hh
@@ -8,6 +8,9 @@ struct Paperdef {
Real linewidth;
/// how much space does a whole note take (ideally?)
Real whole_width;
+
+ // ideal = geometric_ ^ log2(duration)
+ Real geometric_;
/****************/
void parse();
@@ -17,5 +20,6 @@ struct Paperdef {
Real standard_height()const;
Real note_width() const;
void print() const;
+ Real duration_to_dist(Real);
};
diff --git a/parser.y b/parser.y
index 4ca199bb77..3ce26028b1 100644
--- a/parser.y
+++ b/parser.y
@@ -37,7 +37,7 @@
%token VOICE STAFF SCORE TITLE RHYTHMSTAFF BAR NOTENAME OUTPUT
%token CM IN PT MM PAPER WIDTH METER UNITSPACE SKIP COMMANDS
-%token MELODICSTAFF
+%token MELODICSTAFF GEOMETRIC START
%type <consstr> unit
%token <id> IDENTIFIER
@@ -76,6 +76,10 @@ declaration:
$$ = new Staff_id(*$1, $3);
delete $1; // this sux
}
+ | NEWIDENTIFIER '=' voice_block {
+ $$ = new Voice_id(*$1, $3);
+ delete $1;
+ }
;
@@ -108,6 +112,7 @@ paper_body:
delete $3;
}
| paper_body UNITSPACE dim { $$->whole_width = $3; }
+ | paper_body GEOMETRIC REAL { $$->geometric_ = $3; }
;
dim:
@@ -160,10 +165,14 @@ voice_block:
voice_body:
- REAL voice_elts_dollar { $$ = $2; $$->start = $1; }
+ IDENTIFIER { $$ = new Voice(*$1->voice()); }
| voice_elts_dollar { $$ = $1; }
+ | voice_body START REAL { $$->start = $3; }
;
+
+
+
voice_elts_dollar:
'$' voice_elts '$' { $$ = $2; }
;
@@ -219,5 +228,6 @@ parse_file(String s)
#endif
new_input(s);
yyparse();
+ delete_identifiers();
*mlog << "\n";
}
diff --git a/pscore.cc b/pscore.cc
index e1c8a7204a..3f6f289d26 100644
--- a/pscore.cc
+++ b/pscore.cc
@@ -50,6 +50,7 @@ PScore::typeset_item(Item *i, PCol *c, PStaff *s, int breakstat)
its.bottom().add(i);
s->add(i);
c->add(i);
+ i->preprocess();
}
void
@@ -154,3 +155,20 @@ PScore::print() const
#endif
}
+void
+PScore::preprocess()
+{
+#if 0
+ for (PCursor<Item*> ic(its); ic.ok(); ic++){
+ ic->preprocess();
+ }
+#endif
+}
+
+void
+PScore::postprocess()
+{
+ for (PCursor<Item*> ic(its); ic.ok(); ic++){
+ ic->postprocess();
+ }
+}
diff --git a/pscore.hh b/pscore.hh
index 58a6910bbd..91436b369e 100644
--- a/pscore.hh
+++ b/pscore.hh
@@ -33,6 +33,9 @@ struct PScore {
/****************************************************************/
svec<Item*> select_items(PStaff*, PCol*);
+
+ /// before calc_breaking
+ void preprocess();
void calc_breaking();
/**
@@ -43,6 +46,9 @@ struct PScore {
lines contain the broken lines.
*/
+ /// after calc_breaking
+ void postprocess();
+
/// search all pcols which are breakable.
svec<const PCol *> find_breaks() const;
diff --git a/request.cc b/request.cc
index fd032fcfd8..35a9ae9718 100644
--- a/request.cc
+++ b/request.cc
@@ -41,13 +41,13 @@ Note_req::height() const
return s + octave*7;
}
-/****************************************************************/
Rhythmic_req::Rhythmic_req(Voice_element*v)
:Request(v)
{
balltype = 1;
dots = 0;
}
+
void
Rhythmic_req::print() const
{
@@ -57,6 +57,7 @@ Rhythmic_req::print() const
mtor << '.';
mtor<<"\n";
}
+
void
Note_req::print() const
{
diff --git a/rhythmstaff.cc b/rhythmstaff.cc
index 7e2706e02d..98d17d522c 100644
--- a/rhythmstaff.cc
+++ b/rhythmstaff.cc
@@ -1,4 +1,5 @@
#include "molecule.hh"
+#include "notehead.hh"
#include "stem.hh"
#include "linestaff.hh"
#include "rhythmstaff.hh"
@@ -28,9 +29,18 @@ Rhythmic_column::typeset_command(Command *com, int breakst)
void
Rhythmic_column::typeset_req(Request *rq)
{
- Item *i =new Item;
- Molecule*m=create_req_mol(rq);
- i->output=m;
+ Item *i ;
+ if (rq->note()) {
+ Notehead *n =new Notehead(1);
+ n->balltype = rq->rhythmic()->balltype;
+ n->dots = rq->rhythmic()->dots;
+ n->position = 0;
+ i = n;
+ } else if (rq->rest()) {
+ i =new Item;
+ Molecule*m=create_req_mol(rq);
+ i->output=m;
+ }
typeset_item(i);
}
@@ -40,9 +50,7 @@ Rhythmic_column::typeset_stem(Stem_req*rq)
Stem * s = new Stem(0);
s->minnote = s->maxnote = 0;
s->flag = rq->stem_number;
- s->calculate();
typeset_item(s);
- s->brew_molecole();
}
/*
diff --git a/score.cc b/score.cc
index 097e2aa50d..1df13365f2 100644
--- a/score.cc
+++ b/score.cc
@@ -13,6 +13,7 @@ Score::set(Paperdef*p)
delete paper_;
paper_ = p;
}
+
void
Score::output(String s)
{
@@ -29,7 +30,7 @@ Score::output(String s)
void
Score::process()
{
- *mlog << "Processing ...";
+ *mlog << "Processing ... ";
set(commands_->parse(last()));
commands_->print();
@@ -53,8 +54,12 @@ Score::process()
clean_cols();
OK();
// print();
+
+ pscore_->preprocess();
*mlog << "Calculating ... ";
pscore_->calc_breaking();
+ pscore_->postprocess();
+
// TODO: calculate vertical structs
// TODO: calculate mixed structs.
*mlog << "\n";
diff --git a/simpleprint.cc b/simpleprint.cc
index b8f02c5798..b069978dce 100644
--- a/simpleprint.cc
+++ b/simpleprint.cc
@@ -9,12 +9,10 @@
Molecule *
Simple_column::create_req_mol(Request *rq)
{
+ assert(rq->rest());
Symbol s;
int dots=0;
-
- if (rq->note())
- s = staff_->paper()->lookup_->ball(rq->note()->balltype);
- else if (rq->rest())
+ if (rq->rest())
s = staff_->paper()->lookup_->rest(rq->rest()->balltype);
if (rq->rhythmic())
@@ -30,6 +28,7 @@ Simple_column::create_req_mol(Request *rq)
}
return m;
}
+
Molecule *
Simple_column::create_command_mol(Command *com)
{
diff --git a/spanner.cc b/spanner.cc
index f9eb65367b..be30c04659 100644
--- a/spanner.cc
+++ b/spanner.cc
@@ -14,6 +14,7 @@ Spanner::TeXstring() const
return strets->eval(w).tex;
}
+// todo.
Spanner *
Spanner::broken_at(const PCol *c1, const PCol *c2) const
{
diff --git a/spanner.hh b/spanner.hh
index 542357f7a2..1908d2f013 100644
--- a/spanner.hh
+++ b/spanner.hh
@@ -13,8 +13,8 @@ struct Spanner {
const PCol *left, *right;
Parametric_symbol *strets;
PStaff * pstaff_;
- /// clone a piece of this spanner.
- Spanner *broken_at(const PCol *c1, const PCol *c2) const;
+ /// clone a piece of this spanner.
+ virtual Spanner *broken_at(const PCol *c1, const PCol *c2) const;
/**
PRE
@@ -23,6 +23,7 @@ struct Spanner {
/****************/
String TeXstring () const ;
Spanner();
+ virtual void process();
};
/** Spanner should know about the items which it should consider:
e.g. slurs should be steep enough to "enclose" all those items. This
diff --git a/stem.cc b/stem.cc
index 33198addde..fd6634c6bf 100644
--- a/stem.cc
+++ b/stem.cc
@@ -47,6 +47,13 @@ Stem::calculate()
}
}
+void
+Stem::postprocess()
+{
+ calculate();
+ brew_molecole();
+}
+
Interval
Stem::width()const
{
@@ -60,16 +67,18 @@ void
Stem::brew_molecole()
{
assert(pstaff_);
- Paperdef *p = pstaff_->pscore_->paper_;
- Parametric_symbol *stem = p->lookup_->stem();
-
assert(bot!=top);
assert(!output);
+ Paperdef *p = pstaff_->pscore_->paper_;
+ Parametric_symbol *stem = p->lookup_->stem();
+
Real dy = p->interline()/2;
String y1 =print_dimen( dy * bot);
String y2 = print_dimen(dy * top);
Symbol ss =stem->eval(y1,y2);
+ delete stem;
+
output = new Molecule(Atom(ss));
if (ABS(flag) > 4){
diff --git a/stem.hh b/stem.hh
index 039bc5182c..acbebe0d92 100644
--- a/stem.hh
+++ b/stem.hh
@@ -8,6 +8,7 @@
#define STEM_HH
#include "item.hh"
+/// the rule attached to the ball
struct Stem : public Item {
// heads the stem encompasses (positions)
int minnote, maxnote;
@@ -20,12 +21,24 @@ struct Stem : public Item {
// flagtype? 4 none, 8 8th flag, 0 = beam.
int flag;
-
/****************/
- void brew_molecole();
- void calculate();
+
+ void postprocess();
Stem(int center);
void print() const;
- Interval width() const;
+ Interval width() const;
+private:
+ void calculate();
+ void brew_molecole();
};
+/**
+ takes care of:
+
+ \begin{itemize}
+ \item the rule
+ \item the flag
+ \item up/down position.
+ \end{itemize}
+ */
+
#endif
diff --git a/symbol.ini b/symbol.ini
index 39553133ec..ea303b04f1 100644
--- a/symbol.ini
+++ b/symbol.ini
@@ -13,6 +13,11 @@ table balls
4 \quartball 0pt 6pt -2.5pt 2.5pt
end
+table streepjes
+ toplines \toplines{%} -6pt 6pt 0pt 0pt
+ botlines \botlines{%} -6pt 6pt 0pt 0pt
+end
+
table bars
empty \emptybar 0pt 0pt 0pt 0pt
| \maatstreep 0pt 1pt -12pt 12pt
diff --git a/table.cc b/table.cc
index 5352574399..58d1c425e1 100644
--- a/table.cc
+++ b/table.cc
@@ -3,6 +3,7 @@
#include "string.hh"
#include "identifier.hh"
#include "keyword.hh"
+#include "associter.hh"
#include "parser.hh"
static Keyword_ent the_key_tab[]={
@@ -23,6 +24,7 @@ static Keyword_ent the_key_tab[]={
"skip", SKIP,
"commands", COMMANDS,
"staff", STAFF,
+ "geometric", GEOMETRIC,
0,0
} ;
@@ -50,3 +52,13 @@ add_identifier(Identifier*i)
{
the_id_tab[i->name] = i;
}
+
+void
+delete_identifiers()
+{
+
+ for (Assoc_iter<String,Identifier*> ai(the_id_tab); ai.ok(); ai++) {
+ mtor << "deleting: " << ai.key()<<'\n';
+ delete ai.val();
+ }
+}
diff --git a/tex.hh b/tex.hh
index 2f60630fd5..546797a7c1 100644
--- a/tex.hh
+++ b/tex.hh
@@ -4,6 +4,7 @@
#include "string.hh"
#include "boxes.hh"
+/// parameter substitution in TeXstrings
String
substitute_args(String source, svec<String> args);
/**
diff --git a/tstream.cc b/tstream.cc
index b7c88f1b0b..05e2e9c93e 100644
--- a/tstream.cc
+++ b/tstream.cc
@@ -32,7 +32,8 @@ Tex_stream::~Tex_stream()
// print string. don't forget indent.
Tex_stream &
Tex_stream::operator<<(String s)
-{
+{
+
for (const char *cp = s; *cp; cp++) {
if (outputting_comment) {
*os << *cp;
@@ -56,7 +57,7 @@ Tex_stream::operator<<(String s)
nest_level--;
*os << *cp;
assert (nest_level >= 0);
- /* FALL THROUGH */
+ /* FALTHROUGH */
case '\n':
*os << "%\n";
diff --git a/voice.hh b/voice.hh
index 59b0dc8315..7180ece99e 100644
--- a/voice.hh
+++ b/voice.hh
@@ -14,7 +14,7 @@ struct Voice {
Real when(const Voice_element*)const;
Real last() const;
Voice();
- Voice( Voice const&);
+ Voice(Voice const&);
void add(Voice_element*);
void print() const;
};