]> git.donarmstrong.com Git - lilypond.git/blob - lib/duration-convert.cc
partial: 1.0.1.jcn
[lilypond.git] / lib / duration-convert.cc
1 /*
2   duration-convert.cc -- implement Duration_convert
3
4   source file of the LilyPond music typesetter
5
6   (c)  1997--1998 Han-Wen Nienhuys <hanwen@stack.nl>
7            Jan Nieuwenhuizen <jan@digicash.com>
8 */
9 #include <assert.h>
10 #include "duration-convert.hh"
11 #include "duration-iter.hh"
12 #include "warn.hh"
13
14 // statics Duration_convert
15 bool const Duration_convert::midi_as_plet_b_s = true;
16 bool Duration_convert::no_quantify_b_s = false;
17 bool Duration_convert::no_double_dots_b_s = false;
18 bool Duration_convert::no_triplets_b_s = false;
19 int Duration_convert::no_smaller_than_i_s = 0;
20 Array<Duration> Duration_convert::dur_array_s;
21         
22 String 
23 Duration_convert::dur2_str (Duration dur)
24 {
25   if (dur.ticks_i_)
26     return String ("[") + String (dur.ticks_i_) + "]";
27   
28   String str;
29   if (dur.durlog_i_ >= 0)
30     str = String ( type2_i (dur.durlog_i_) );
31   else if (dur.durlog_i_ == -1)
32     str = "\\breve";
33   else if (dur.durlog_i_ == -2)
34     str = "\\longa";
35   str += String ('.', dur.dots_i_);
36   if (dur.plet_b ())
37     str += String ("*") + String (dur.plet_.iso_i_)
38       + String ("/") + String (dur.plet_.type_i_);
39   return str;
40 }
41
42 int
43 Duration_convert::dur2ticks_i (Duration dur)
44 {
45   if (dur.ticks_i_)
46     return dur.ticks_i_;
47   return dur2_mom (dur) * Moment (Duration::division_1_i_s);
48 }
49
50
51 int
52 Duration_convert::i2_type (int i)
53 {
54   int t=0;
55   while (!(i & 1)) {
56     i >>= 1;
57     t++;
58   }
59   return t;
60 }
61
62 int
63 Duration_convert::type2_i (int type)
64 {
65   if (type<0)
66     return 0; 
67   else
68     return 1 << type;
69 }
70
71 Moment
72 Duration_convert::dur2_mom (Duration dur)
73 {
74   if (dur.ticks_i_)
75     return Moment (dur.ticks_i_, Duration::division_1_i_s);     
76
77   // or simply assert?
78   if (dur.durlog_i_<-10)
79     return Moment (0);
80   Moment mom;
81   if (dur.durlog_i_<0)
82     mom = Moment (type2_i (-dur.durlog_i_), 1);
83   else
84     mom = Moment (1 , type2_i (dur.durlog_i_));
85
86   Moment delta = mom;
87   while (dur.dots_i_--) 
88     {
89       delta /= 2.0;
90       mom += delta;
91     }
92
93   return mom * plet_factor_mom (dur);    
94 }
95
96 Duration
97 Duration_convert::mom2_dur (Moment mom)
98 {
99   if (!mom) 
100     {
101       Duration dur;
102       dur.set_plet (0,1);
103       return dur;
104     }
105         
106
107   Duration dur = mom2standardised_dur (mom);
108   //    if (!dur.mom () || (dur.mom () == mom))
109   if (!dur.length () || (dur.length () == mom))
110     return dur;
111   assert (midi_as_plet_b_s);
112
113   //    dur.set_plet (type_mom, Duration::division_1_i_s / 4); 
114
115   //    Moment as_plet_mom = mom / dur.mom ();
116   Moment as_plet_mom = mom / dur.length ();
117   as_plet_mom *= dur.plet_.mom ();
118   long num = as_plet_mom.num ();
119   long den = as_plet_mom.den ();
120   dur.set_plet (num, den);
121   return dur;
122 }
123
124 Duration
125 Duration_convert::mom2standardised_dur (Moment mom)
126 {
127   //    if (!dur_array_s.length_i ())
128   if (!dur_array_s.size ())
129     set_array ();
130   assert (dur_array_s.size ());
131   for (int i = 0; i < dur_array_s.size () - 1; i++) 
132     {
133       Moment lower_mom = dur2_mom (dur_array_s[ i ]);
134       if (mom <= lower_mom) 
135         {
136           // all arbitrary, but 3/4 will get rid of the noise...
137           // kinda ok
138           if (i || (mom / lower_mom > Moment (3, 4)))
139             return dur_array_s[ i ];
140           else 
141             {
142               Duration d;
143               d.durlog_i_ = -100;
144               return d;
145             }
146         }
147       Moment upper_mom = dur2_mom (dur_array_s[ i + 1 ]);
148       if ((mom < upper_mom)
149           && ((mom - lower_mom) / lower_mom
150               < (upper_mom - mom) / upper_mom))
151         return dur_array_s[ i ];
152     }
153   return dur_array_s[ dur_array_s.size () - 1 ];
154 }
155
156 void
157 Duration_convert::set_array ()
158 {
159   dur_array_s.clear ();
160
161   Duration_iterator iter_dur;
162   assert (iter_dur);
163   while (iter_dur)
164     dur_array_s.push (iter_dur++);
165 }
166
167
168 Moment
169 Duration_convert::plet_factor_mom (Duration dur)
170 {
171   return dur.plet_.mom ();
172 }
173
174 Real
175 Duration_convert::sync_f (Duration dur, Moment mom)
176 {
177   return mom / dur2_mom (dur);
178 }
179
180 Duration
181 Duration_convert::ticks2_dur (int ticks_i)
182 {
183   Moment mom (ticks_i, Duration::division_1_i_s);
184   if (midi_as_plet_b_s)
185     return mom2_dur (mom);
186
187   Duration dur = mom2standardised_dur (mom);
188
189   if (dur.length () == mom)
190     return dur;
191                 
192   return mom2_dur (mom);
193 }
194
195 Duration
196 Duration_convert::ticks2standardised_dur (int ticks_i)
197 {
198   Moment mom (ticks_i, Duration::division_1_i_s);
199   Duration dur = mom2standardised_dur (mom);
200   return dur;
201 }