]> git.donarmstrong.com Git - lilypond.git/blob - lib/duration-convert.cc
release: 0.0.44
[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 Duration_convert::be_blonde_b_s = false;
14 bool Duration_convert::no_double_dots_b_s = false;
15 bool Duration_convert::no_triplets_b_s = false;
16 int Duration_convert::no_smaller_than_i_s = 0;
17         
18 String 
19 Duration_convert::dur2_str( Duration dur )
20 {
21         if ( dur.ticks_i_ )
22                 return String( "["  ) + String( dur.ticks_i_ ) + "]";
23
24         String str( dur.type_i_ );
25         str += String( '.', dur.dots_i_ );
26         if ( dur.plet_b())
27                 str += String( "*" ) + String( dur.plet_.iso_i_ )
28                         + String( "/" ) + String( dur.plet_.type_i_ );
29         return str;
30 }
31
32 #if 0
33 int
34 Duration_convert::dur2_i( Duration dur, int division_1_i )
35 {
36         return dur2_mom( dur ) * Moment( division_1_i );
37 }
38 #endif
39
40 int
41 Duration_convert::dur2ticks_i( Duration dur )
42 {
43         if ( dur.ticks_i_ )
44                 return dur.ticks_i_;
45         return dur2_mom( dur ) * Moment( Duration::division_1_i_s );
46 }
47
48 Moment
49 Duration_convert::dur2_mom( Duration dur )
50 {
51         if ( dur.ticks_i_ )
52                 return Moment( dur.ticks_i_, Duration::division_1_i_s );        
53
54         // or simply assert?
55         if ( !dur.type_i_ )
56                 return Moment( 0 );
57
58         Moment mom = Moment( 1 , dur.type_i_ );
59
60         Moment delta = mom;
61         while ( dur.dots_i_-- ) {
62                 delta /= 2.0;
63                 mom += delta;
64         }
65
66         return mom * plet_factor_mom( dur );    
67 }
68
69 #if 0
70 Moment
71 Duration_convert::i2_mom( int time_i, int division_1_i )
72 {
73         if ( !time_i )
74                 return Moment( 0 );
75
76         if ( division_1_i > 0 )
77                 return Moment( time_i, division_1_i );
78         else 
79                 return Moment( -division_1_i, time_i );
80 }
81 #endif
82
83 #if 0
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 lower_dur = iter_dur++;
95                 Duration upper_dur( 0 );
96                 if ( iter_dur )
97                         upper_dur = iter_dur();
98                 Moment lower_mom = dur2_mom( lower_dur );
99                 Moment upper_mom = dur2_mom( upper_dur );
100                 if ( mom == lower_mom )
101                         return lower_dur;
102                 if ( mom == upper_mom ) // don-t miss last (sic)
103                         return upper_dur;
104                 if ( ( mom >= lower_mom ) && ( mom <= upper_mom ) ) {
105                         warning( String( "duration not exact: " ) + String( (Real)mom ) , 0 );
106                         if ( abs( mom - lower_mom ) < abs( mom - upper_mom ) )
107                                 return lower_dur;
108                         else
109                                 return upper_dur;
110                 }
111                 lower_dur = upper_dur;
112         }
113         return Duration( 0 );
114 }
115 #endif
116
117 Moment
118 Duration_convert::plet_factor_mom( Duration dur )
119 {
120         return dur.plet_.mom();
121 }
122
123 Real
124 Duration_convert::sync_f( Duration dur, Moment mom )
125 {
126         return mom / dur2_mom( dur );
127 }
128
129 Duration
130 Duration_convert::ticks2_dur( int ticks_i )
131 {
132         /* this is cute, 
133            but filling an array using Duration_iterator
134            might speed things up, a little
135            */
136         Moment mom( ticks_i, Duration::division_1_i_s );
137         Duration_iterator iter_dur;
138         assert( iter_dur );
139         while ( iter_dur ) {
140                 Duration dur = iter_dur++;
141                 if ( mom == dur2_mom( dur ) )
142                         return dur;
143         }
144         Duration dur( 0 );
145         dur.set_ticks( ticks_i );
146         return dur;
147 }
148
149 Duration
150 Duration_convert::ticks2standardised_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         Moment mom( ticks_i, Duration::division_1_i_s );
157         Duration_iterator iter_dur;
158         assert( iter_dur );
159         while ( iter_dur ) {
160                 Duration lower_dur = iter_dur++;
161 //              Duration upper_dur( 0 );
162                 Duration upper_dur( 1, 1 );
163                 if ( iter_dur )
164                         upper_dur = iter_dur();
165                 Moment lower_mom = dur2_mom( lower_dur );
166                 Moment upper_mom = dur2_mom( upper_dur );
167                 if ( mom < lower_mom )
168                         return lower_dur;
169                 if ( mom == lower_mom )
170                         return lower_dur;
171                 if ( mom == upper_mom ) // don-t miss last (sic)
172                         return upper_dur;
173                 if ( ( mom >= lower_mom ) && ( mom <= upper_mom ) ) {
174                         warning( String( "duration not exact: " ) + String( (Real)mom ) , 0 );
175                         if ( abs( mom - lower_mom ) < abs( mom - upper_mom ) )
176                                 return lower_dur;
177                         else
178                                 return upper_dur;
179                 }
180                 lower_dur = upper_dur;
181         }
182         return iter_dur();
183 }
184
185 Duration_iterator::Duration_iterator()
186 {
187         cursor_dur_.type_i_ = 128;
188         if ( Duration_convert::no_smaller_than_i_s )
189                 cursor_dur_.type_i_ = Duration_convert::no_smaller_than_i_s;
190         cursor_dur_.set_plet( 0,1 ); // ugh?
191 }
192
193 Duration 
194 Duration_iterator::operator ++(int)
195 {
196         return forward_dur();
197 }
198
199 Duration
200 Duration_iterator::operator ()()
201 {
202         return dur();
203 }
204
205 Duration_iterator::operator bool()
206 {
207         return ok();
208 }
209
210 Duration
211 Duration_iterator::dur()
212 {
213         return cursor_dur_;
214 }
215
216 Duration
217 Duration_iterator::forward_dur()
218 {
219         /* should do smart table? guessing: 
220                 duration wholes
221                 16      0.0625
222                 32..    0.0703
223                 8:2/3   0.0833
224                 16.     0.0938
225                 8       0.1250
226                 16..    0.1406
227                 4:2/3   0.1667
228                 8.      0.1875
229                 
230         */
231         assert( ok() );
232
233         Duration dur = cursor_dur_;
234
235         if ( !cursor_dur_.dots_i_ && !cursor_dur_.plet_b() ) {
236                 cursor_dur_.type_i_ *= 2;
237                 cursor_dur_.dots_i_ = 2;
238         }
239         else if ( cursor_dur_.dots_i_ == 2 ) {
240                 assert( !cursor_dur_.plet_b() );
241                 cursor_dur_.dots_i_ = 0;
242                 cursor_dur_.type_i_ /= 4;
243                 cursor_dur_.set_plet( 2, 3  );
244         }
245         else if ( cursor_dur_.plet_b() 
246                 && ( cursor_dur_.plet_.iso_i_ == 2 )
247                 && ( cursor_dur_.plet_.type_i_ == 3 ) ) {
248                 assert( !cursor_dur_.dots_i_ );
249                 cursor_dur_.set_plet( 0,1 );
250                 cursor_dur_.type_i_ *= 2;
251                 cursor_dur_.dots_i_ = 1;
252         }
253         else if ( cursor_dur_.dots_i_ == 1 ) {
254                 assert( !cursor_dur_.plet_b() );
255                 cursor_dur_.dots_i_ = 0;
256                 cursor_dur_.type_i_ /= 2;
257         }
258                 
259         if ( Duration_convert::no_triplets_b_s
260              && cursor_dur_.plet_b() && ok() )
261             forward_dur();
262         if ( Duration_convert::no_double_dots_b_s 
263              && ( cursor_dur_.dots_i_ == 2 ) && ok() )
264                 forward_dur();
265         if ( Duration_convert::no_smaller_than_i_s
266              && ( cursor_dur_.type_i_ > Duration_convert::no_smaller_than_i_s ) && ok() )
267                 forward_dur();
268         if ( Duration_convert::no_smaller_than_i_s
269              && cursor_dur_.dots_i_
270              && ( cursor_dur_.type_i_ >= Duration_convert::no_smaller_than_i_s )
271              && ok() )
272                 forward_dur();
273         if ( Duration_convert::no_smaller_than_i_s
274              && ( cursor_dur_.dots_i_ == 2 )
275              && ( cursor_dur_.type_i_ >= Duration_convert::no_smaller_than_i_s / 2 )
276              && ok() )
277                 forward_dur();
278
279         return dur;
280 }
281
282 bool
283 Duration_iterator::ok()
284 {
285         return ( cursor_dur_.type_i_ 
286                 && !( ( cursor_dur_.type_i_ == 1 ) && ( cursor_dur_.dots_i_ > 2 ) ) );
287 }