]> git.donarmstrong.com Git - lilypond.git/blob - lily/duration.cc
* configure.in: Test for and accept lmodern if EC fonts not found.
[lilypond.git] / lily / duration.cc
1 /*
2   duration.cc -- implement Duration
3
4   source file of the LilyPond music typesetter
5
6   (c) 1997--2004 Jan Nieuwenhuizen <janneke@gnu.org>
7                  Han-Wen Nienhuys <hanwen@cs.uu.nl>
8
9 */
10
11 #include "duration.hh"
12
13 #include "misc.hh"
14 #include "lily-proto.hh"
15
16 #include "ly-smobs.icc"
17
18 int
19 Duration::compare (Duration const &left, Duration const &right)
20 {
21   return Rational::compare (left.get_length (), right.get_length ());
22 }
23
24 Duration::Duration ()
25 {
26   durlog_ = 0;
27   dots_ = 0;
28   factor_ = Rational (1, 1);
29 }
30
31 Duration::Duration (int log, int d)
32 {
33   durlog_ = log;
34   dots_ = d;
35   factor_ = Rational (1, 1);
36 }
37
38 Duration
39 Duration::compressed (Rational m) const
40 {
41   Duration d (*this);
42   d.factor_ *= m;
43   return d;
44 }
45
46 Rational
47 Duration::get_length () const
48 {
49   Rational mom (1 << abs (durlog_));
50
51   if (durlog_> 0)
52     mom = Rational (1) / mom;
53
54   Rational delta = mom;
55   for (int i = 0; i < dots_; i++)
56     {
57       delta /= Rational (2);
58       mom += delta;
59     }
60
61   return mom * factor_;
62 }
63
64 String
65 Duration::to_string () const
66 {
67   String s;
68
69   if (durlog_ < 0  )
70     s = "log = "  + ::to_string (durlog_);
71   else
72     s = ::to_string (1 << durlog_);
73
74   s += ::to_string ('.', dots_);
75   if (factor_ != Moment (Rational (1, 1)))
76     s += "*" + factor_.to_string ();
77   return s;
78 }
79
80
81 IMPLEMENT_TYPE_P (Duration, "ly:duration?");
82
83 SCM
84 Duration::mark_smob (SCM)
85 {
86   return SCM_EOL;
87 }
88
89 IMPLEMENT_SIMPLE_SMOBS (Duration);
90 int
91 Duration::print_smob (SCM s, SCM port, scm_print_state *)
92 {
93   Duration  *r = (Duration *) SCM_CELL_WORD_1 (s);
94
95   scm_puts ("#<Duration ", port);
96   scm_display (scm_makfrom0str (r->to_string ().to_str0 ()), port);
97   scm_puts (" >", port);
98
99   return 1;
100 }
101
102 SCM
103 Duration::equal_p (SCM a , SCM b)
104 {
105   Duration  *p = (Duration *) SCM_CELL_WORD_1 (a);
106   Duration  *q = (Duration *) SCM_CELL_WORD_1 (b);
107
108   bool eq = p->dots_ == q->dots_
109     && p->durlog_ == q->durlog_
110     && p->factor_ == q->factor_;
111
112   return eq ? SCM_BOOL_T : SCM_BOOL_F;
113 }
114
115 MAKE_SCHEME_CALLBACK (Duration, less_p, 2);
116 SCM
117 Duration::less_p (SCM p1, SCM p2)
118 {
119   Duration *a = unsmob_duration (p1);
120   Duration *b = unsmob_duration (p2);
121
122   if (compare (*a, *b) < 0)
123     return SCM_BOOL_T;
124   else
125     return SCM_BOOL_F;
126 }
127
128 LY_DEFINE (ly_duration_less_p, "ly:duration<?",
129            2, 0, 0, (SCM p1, SCM p2),
130           "Is @var{p1} shorter than @var{p2}?")
131 {
132   Duration *a = unsmob_duration (p1);
133   Duration *b = unsmob_duration (p2);
134
135   SCM_ASSERT_TYPE (a, p1, SCM_ARG1, __FUNCTION__, "Duration");
136   SCM_ASSERT_TYPE (b, p2, SCM_ARG2, __FUNCTION__, "Duration");
137
138   if (Duration::compare (*a, *b) < 0)
139     return SCM_BOOL_T;
140   else
141     return SCM_BOOL_F;
142 }
143
144 LY_DEFINE (ly_make_duration, "ly:make-duration",
145            1, 3, 0, (SCM length, SCM dotcount, SCM num, SCM den),
146            "@var{length} is the negative logarithm (base 2) of the duration:\n"
147            "1 is a half note, 2 is a quarter note, 3 is an eighth\n"
148            "note, etc.  The number of dots after the note is given by\n"
149            "the optional argument @var{dotcount}.\n"
150            "\n"
151            "The duration factor is optionally given by @var{num}\n"
152            "and @var{den}.\n\n"
153            "A duration is a musical duration, "
154            "i.e. a length of time described by a power of two "
155            "(whole, half, quarter, etc.) and a number of augmentation\n"
156            "dots. \n")
157 {
158   SCM_ASSERT_TYPE (scm_integer_p (length) == SCM_BOOL_T,
159                    length, SCM_ARG1, __FUNCTION__, "integer");
160
161   int dots = 0;
162   if (dotcount != SCM_UNDEFINED)
163     {
164       SCM_ASSERT_TYPE (scm_integer_p (dotcount) == SCM_BOOL_T,
165                        dotcount, SCM_ARG2, __FUNCTION__, "integer");
166       dots = scm_to_int (dotcount);
167     }
168
169   bool compress = false;
170   if (num != SCM_UNDEFINED)
171     {
172       SCM_ASSERT_TYPE (scm_is_number (num), length, SCM_ARG3, __FUNCTION__, "integer");
173       compress = true;
174     }
175   else
176     num = scm_int2num (1);
177
178   if (den != SCM_UNDEFINED)
179     {
180       SCM_ASSERT_TYPE (scm_is_number (den), length, SCM_ARG4, __FUNCTION__, "integer");
181       compress = true;
182     }
183   else
184     den = scm_int2num (1);
185
186   Duration p (scm_to_int (length), dots);
187   if (compress)
188     p = p.compressed (Rational (scm_to_int (num), scm_to_int (den)));
189
190   return p.smobbed_copy ();
191 }
192
193 LY_DEFINE (ly_duration_log, "ly:duration-log",
194            1, 0, 0, (SCM dur),
195           "Extract the duration log from @var{dur}")
196 {
197   SCM_ASSERT_TYPE (unsmob_duration (dur), dur, SCM_ARG1, __FUNCTION__, "duration");
198   return scm_int2num (unsmob_duration (dur)->duration_log ());
199 }
200
201 LY_DEFINE (ly_duration_dot_count, "ly:duration-dot-count",
202            1, 0, 0, (SCM dur),
203           "Extract the dot count from @var{dur}")
204 {
205   SCM_ASSERT_TYPE (unsmob_duration (dur), dur, SCM_ARG1, __FUNCTION__, "duration");
206   return scm_int2num (unsmob_duration (dur)->dot_count ());
207 }
208
209 LY_DEFINE (ly_intlog2, "ly:intlog2",
210            1, 0, 0, (SCM d),
211           "The 2-logarithm of 1/@var{d}.")
212 {
213   SCM_ASSERT_TYPE (scm_is_number (d), d, SCM_ARG1, __FUNCTION__, "integer");
214   int log = intlog2 (scm_to_int (d));
215   return scm_int2num (log);
216 }
217
218 LY_DEFINE (ly_duration_factor, "ly:duration-factor",
219            1, 0, 0, (SCM dur),
220           "Extract the compression factor from @var{dur}. Return as a pair.")
221 {
222   SCM_ASSERT_TYPE (unsmob_duration (dur), dur, SCM_ARG1, __FUNCTION__, "duration");
223   Rational r = unsmob_duration (dur)->factor ();
224   return scm_cons (scm_int2num (r.num ()), scm_int2num (r.den ()));
225 }
226
227 int
228 Duration::duration_log () const
229 {
230   return durlog_;
231 }
232
233 int
234 Duration::dot_count () const
235 {
236   return dots_;
237 }