X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fduration.cc;h=194ce3a89e2e3187b302e83ea615a399595e277c;hb=e90f0536f9be39ada0bef0aeb0d275dec3b2fb5b;hp=1618489027dd7d74c53c9e4952fb4a6b0fce4be3;hpb=a276a19dc6bd57832db3107f2f2cbb04cb4677b6;p=lilypond.git diff --git a/lily/duration.cc b/lily/duration.cc index 1618489027..194ce3a89e 100644 --- a/lily/duration.cc +++ b/lily/duration.cc @@ -1,10 +1,21 @@ /* - duration.cc -- implement Duration + This file is part of LilyPond, the GNU music typesetter. - source file of the LilyPond music typesetter - - (c) 1997--2007 Jan Nieuwenhuizen + Copyright (C) 1997--2011 Jan Nieuwenhuizen Han-Wen Nienhuys + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include "duration.hh" @@ -34,6 +45,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 = (int) r.num (); + int q = (int) r.den (); + int k = intlog2 (q) - intlog2 (p); + if (shift_left(p, k) < q) + k++; + + assert (shift_left(p, k) >= q && shift_left(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 = shift_left(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 {