]> git.donarmstrong.com Git - lilypond.git/blob - lib/duration-convert.cc
release: 0.0.47
[lilypond.git] / lib / duration-convert.cc
1 /*
2   duration-convert.cc -- implement 
3
4   source file of the LilyPond music typesetter
5
6   (c) 1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8 #include <assert.h>
9 #include "duration-convert.hh"
10 #include "debug.hh"
11
12 // statics Duration_convert
13 bool const Duration_convert::midi_as_plet_b_s = true;
14 bool Duration_convert::no_quantify_b_s = false;
15 bool Duration_convert::no_double_dots_b_s = false;
16 bool Duration_convert::no_triplets_b_s = false;
17 int Duration_convert::no_smaller_than_i_s = 0;
18         
19 String 
20 Duration_convert::dur2_str( Duration dur )
21 {
22         if ( dur.ticks_i_ )
23                 return String( "["  ) + String( dur.ticks_i_ ) + "]";
24
25         String str( dur.type_i_ );
26         str += String( '.', dur.dots_i_ );
27         if ( dur.plet_b())
28                 str += String( "*" ) + String( dur.plet_.iso_i_ )
29                         + String( "/" ) + String( dur.plet_.type_i_ );
30         return str;
31 }
32
33 #if 0
34 int
35 Duration_convert::dur2_i( Duration dur, int division_1_i )
36 {
37         return dur2_mom( dur ) * Moment( division_1_i );
38 }
39 #endif
40
41 int
42 Duration_convert::dur2ticks_i( Duration dur )
43 {
44         if ( dur.ticks_i_ )
45                 return dur.ticks_i_;
46         return dur2_mom( dur ) * Moment( Duration::division_1_i_s );
47 }
48
49 Moment
50 Duration_convert::dur2_mom( Duration dur )
51 {
52         if ( dur.ticks_i_ )
53                 return Moment( dur.ticks_i_, Duration::division_1_i_s );        
54
55         // or simply assert?
56         if ( !dur.type_i_ )
57                 return Moment( 0 );
58
59         Moment mom = Moment( 1 , dur.type_i_ );
60
61         Moment delta = mom;
62         while ( dur.dots_i_-- ) {
63                 delta /= 2.0;
64                 mom += delta;
65         }
66
67         return mom * plet_factor_mom( dur );    
68 }
69
70 #if 0
71 Moment
72 Duration_convert::i2_mom( int time_i, int division_1_i )
73 {
74         if ( !time_i )
75                 return Moment( 0 );
76
77         if ( division_1_i > 0 )
78                 return Moment( time_i, division_1_i );
79         else 
80                 return Moment( -division_1_i, time_i );
81 }
82 #endif
83
84 Duration
85 Duration_convert::mom2_dur( Moment mom )
86 {
87         /* this is cute, 
88            but filling an array using Duration_iterator
89            might speed things up, a little
90            */
91         Duration_iterator iter_dur;
92         assert( iter_dur );
93         while ( iter_dur ) {
94                 Duration dur = iter_dur++;
95                 if ( mom == dur2_mom( dur ) )
96                         return dur;
97         }
98         if ( midi_as_plet_b_s ) {
99                 Moment mom_4 = mom / Moment( 4 );
100                 long num = mom_4.numerator().as_long();
101                 long den = mom_4.denominator().as_long();
102                 Duration dur( 4, 0 );
103                 dur.set_plet( num, den );
104                 return dur;
105         }
106         assert( 0 );
107         // no can do
108         Duration dur( 0 );
109         return dur;
110 }
111
112 Duration
113 Duration_convert::mom2standardised_dur( Moment mom )
114 {
115         /* this is cute, 
116            but filling an array using Duration_iterator
117            might speed things up, a little
118            */
119         Duration_iterator iter_dur;
120         assert( iter_dur );
121         while ( iter_dur ) {
122                 Duration lower_dur = iter_dur++;
123                 Duration upper_dur( 0 );
124                 if ( iter_dur )
125                         upper_dur = iter_dur();
126                 Moment lower_mom = dur2_mom( lower_dur );
127                 Moment upper_mom = dur2_mom( upper_dur );
128                 if ( mom < lower_mom )
129                         return lower_dur;
130                 if ( mom == lower_mom )
131                         return lower_dur;
132         }
133         return iter_dur();
134 }
135
136
137 Moment
138 Duration_convert::plet_factor_mom( Duration dur )
139 {
140         return dur.plet_.mom();
141 }
142
143 Real
144 Duration_convert::sync_f( Duration dur, Moment mom )
145 {
146         return mom / dur2_mom( dur );
147 }
148
149 Duration
150 Duration_convert::ticks2_dur( int ticks_i )
151 {
152         /* this is cute, 
153            but filling an array using Duration_iterator
154            might speed things up, a little
155            */
156         // should use mom2_dur
157         Moment mom( ticks_i, Duration::division_1_i_s );
158         Duration_iterator iter_dur;
159         assert( iter_dur );
160         while ( iter_dur ) {
161                 Duration dur = iter_dur++;
162                 if ( mom == dur2_mom( dur ) )
163                         return dur;
164         }
165         if ( midi_as_plet_b_s ) {
166                 Duration dur( 4, 0 );
167                 dur.set_plet( ticks_i, Duration::division_1_i_s / 4 ); 
168                 return dur;
169         }
170         Duration dur( 0 );
171         dur.set_ticks( ticks_i );
172         return dur;
173 }
174
175 Duration
176 Duration_convert::ticks2standardised_dur( int ticks_i )
177 {
178         /* this is cute, 
179            but filling an array using Duration_iterator
180            might speed things up, a little
181            */
182         // should use mom2standardised_dur
183         Moment mom( ticks_i, Duration::division_1_i_s );
184         Duration_iterator iter_dur;
185         assert( iter_dur );
186         while ( iter_dur ) {
187                 Duration lower_dur = iter_dur++;
188 //              Duration upper_dur( 0 );
189                 Duration upper_dur( 1, 1 );
190                 if ( iter_dur )
191                         upper_dur = iter_dur();
192                 Moment lower_mom = dur2_mom( lower_dur );
193                 Moment upper_mom = dur2_mom( upper_dur );
194                 if ( mom < lower_mom )
195                         return lower_dur;
196                 if ( mom == lower_mom )
197                         return lower_dur;
198                 if ( mom == upper_mom ) // don-t miss last (sic)
199                         return upper_dur;
200                 if ( ( mom >= lower_mom ) && ( mom <= upper_mom ) ) {
201                         warning( String( "duration not exact: " ) + String( (Real)mom ) );
202                         if ( abs( mom - lower_mom ) < abs( mom - upper_mom ) )
203                                 return lower_dur;
204                         else
205                                 return upper_dur;
206                 }
207                 lower_dur = upper_dur;
208         }
209         return iter_dur();
210 }
211
212 Duration_iterator::Duration_iterator()
213 {
214         cursor_dur_.type_i_ = 128;
215         if ( Duration_convert::no_smaller_than_i_s )
216                 cursor_dur_.type_i_ = Duration_convert::no_smaller_than_i_s;
217 //      cursor_dur_.set_plet( 1, 1 );
218 }
219
220 Duration 
221 Duration_iterator::operator ++(int)
222 {
223         return forward_dur();
224 }
225
226 Duration
227 Duration_iterator::operator ()()
228 {
229         return dur();
230 }
231
232 Duration_iterator::operator bool()
233 {
234         return ok();
235 }
236
237 Duration
238 Duration_iterator::dur()
239 {
240         return cursor_dur_;
241 }
242
243 Duration
244 Duration_iterator::forward_dur()
245 {
246         /* should do smart table? guessing: 
247                 duration wholes
248                 16      0.0625
249                 32..    0.0703
250                 8:2/3   0.0833
251                 16.     0.0938
252                 8       0.1250
253                 16..    0.1406
254                 4:2/3   0.1667
255                 8.      0.1875
256                 
257         */
258         assert( ok() );
259
260         Duration dur = cursor_dur_;
261
262         if ( !cursor_dur_.dots_i_ && !cursor_dur_.plet_b() ) {
263                 cursor_dur_.type_i_ *= 2;
264                 cursor_dur_.dots_i_ = 2;
265         }
266         else if ( cursor_dur_.dots_i_ == 2 ) {
267                 assert( !cursor_dur_.plet_b() );
268                 cursor_dur_.dots_i_ = 0;
269                 cursor_dur_.type_i_ /= 4;
270                 cursor_dur_.set_plet( 2, 3 );
271         }
272         else if ( cursor_dur_.plet_b() 
273                 && ( cursor_dur_.plet_.iso_i_ == 2 )
274                 && ( cursor_dur_.plet_.type_i_ == 3 ) ) {
275                 assert( !cursor_dur_.dots_i_ );
276                 cursor_dur_.set_plet( 1, 1 );
277                 cursor_dur_.type_i_ *= 2;
278                 cursor_dur_.dots_i_ = 1;
279         }
280         else if ( cursor_dur_.dots_i_ == 1 ) {
281                 assert( !cursor_dur_.plet_b() );
282                 cursor_dur_.dots_i_ = 0;
283                 cursor_dur_.type_i_ /= 2;
284         }
285                 
286         if ( Duration_convert::no_triplets_b_s
287              && cursor_dur_.plet_b() && ok() )
288             forward_dur();
289         if ( Duration_convert::no_double_dots_b_s 
290              && ( cursor_dur_.dots_i_ == 2 ) && ok() )
291                 forward_dur();
292         if ( Duration_convert::no_smaller_than_i_s
293              && ( cursor_dur_.type_i_ > Duration_convert::no_smaller_than_i_s ) && ok() )
294                 forward_dur();
295         if ( Duration_convert::no_smaller_than_i_s
296              && cursor_dur_.dots_i_
297              && ( cursor_dur_.type_i_ >= Duration_convert::no_smaller_than_i_s )
298              && ok() )
299                 forward_dur();
300         if ( Duration_convert::no_smaller_than_i_s
301              && ( cursor_dur_.dots_i_ == 2 )
302              && ( cursor_dur_.type_i_ >= Duration_convert::no_smaller_than_i_s / 2 )
303              && ok() )
304                 forward_dur();
305
306         return dur;
307 }
308
309 bool
310 Duration_iterator::ok()
311 {
312         return ( cursor_dur_.type_i_ 
313                 && !( ( cursor_dur_.type_i_ == 1 ) && ( cursor_dur_.dots_i_ > 2 ) ) );
314 }