X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fduration.cc;h=755679fd71cf2d84469e69062efd4b7dabd71be9;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=642d7b250ceda79acb2626a7506ffdca698c548e;hpb=eea589c2d7bee6ab38bc611eb205d4c74e2011f7;p=lilypond.git diff --git a/lily/duration.cc b/lily/duration.cc index 642d7b250c..755679fd71 100644 --- a/lily/duration.cc +++ b/lily/duration.cc @@ -3,9 +3,8 @@ source file of the LilyPond music typesetter - (c) 1997--2004 Jan Nieuwenhuizen - Han-Wen Nienhuys - + (c) 1997--2008 Jan Nieuwenhuizen + Han-Wen Nienhuys */ #include "duration.hh" @@ -35,6 +34,56 @@ Duration::Duration (int log, int d) factor_ = Rational (1, 1); } +Duration::Duration (Rational r, bool scale) +{ + factor_ = Rational (1, 1); + + if (r.num () == 0.0) + { + durlog_ = 0; + dots_ = 0; + } + else + { + /* we want to find the integer k for which 2q/p > 2^k >= q/p. + It's simple to check that k' = \floor \log q - \floor \log p + satisfies the left inequality and is within a factor of 2 of + satistying the right one. Therefore either k = k' or k = k'+1 */ + + int p = r.num (); + int q = r.den (); + int k = intlog2 (q) - intlog2 (p); + if ((p << k) < q) + k++; + + assert ((p << k) >= q && (p << (k-1)) < q); + + /* If we were to write out log (p/q) in base 2, then the position of the + first non-zero bit (ie. k in our notation) would be the durlog + and the number of consecutive 1s after that bit would be the number of + dots */ + p = (p << k) - q; + dots_ = 0; + while ((p *= 2) >= q) + { + p -= q; + dots_++; + } + + /* we only go up to 64th notes */ + if (k > 6) + { + durlog_ = 6; + dots_ = 0; + } + else + durlog_ = k; + + if (scale || k > 6) + factor_ = r / get_length (); + } +} + Duration Duration::compressed (Rational m) const { @@ -48,7 +97,7 @@ Duration::get_length () const { Rational mom (1 << abs (durlog_)); - if (durlog_> 0) + if (durlog_ > 0) mom = Rational (1) / mom; Rational delta = mom; @@ -61,13 +110,13 @@ Duration::get_length () const return mom * factor_; } -String +string Duration::to_string () const { - String s; + string s; - if (durlog_ < 0 ) - s = "log = " + ::to_string (durlog_); + if (durlog_ < 0) + s = "log = " + ::to_string (durlog_); else s = ::to_string (1 << durlog_); @@ -77,7 +126,6 @@ Duration::to_string () const return s; } - IMPLEMENT_TYPE_P (Duration, "ly:duration?"); SCM @@ -90,20 +138,20 @@ IMPLEMENT_SIMPLE_SMOBS (Duration); int Duration::print_smob (SCM s, SCM port, scm_print_state *) { - Duration *r = (Duration *) SCM_CELL_WORD_1 (s); + Duration *r = (Duration *) SCM_CELL_WORD_1 (s); scm_puts ("#to_string ().to_str0 ()), port); + scm_display (ly_string2scm (r->to_string ()), port); scm_puts (" >", port); return 1; } SCM -Duration::equal_p (SCM a , SCM b) +Duration::equal_p (SCM a, SCM b) { - Duration *p = (Duration *) SCM_CELL_WORD_1 (a); - Duration *q = (Duration *) SCM_CELL_WORD_1 (b); + Duration *p = (Duration *) SCM_CELL_WORD_1 (a); + Duration *q = (Duration *) SCM_CELL_WORD_1 (b); bool eq = p->dots_ == q->dots_ && p->durlog_ == q->durlog_ @@ -112,7 +160,6 @@ Duration::equal_p (SCM a , SCM b) return eq ? SCM_BOOL_T : SCM_BOOL_F; } - int Duration::duration_log () const {