On Fri, 2006-09-15 at 19:33 +0200, Han-Wen Nienhuys wrote:
>
> > else:
> > - return 0
> > + tolerance_exp = -4 # means that notes that are 1/32 or less
> > shorter
> > than 1/4 are quarter notes etc.
> > + return int (math.ceil (-math.log(self._duration) / math.log(2)
> > -
> > 2**tolerance_exp))
>
> Since music notation uses exact rational numbers, using math.log () is
> usually forbidden, and it's better to use exact arithmetic. Can you
> doublecheck whether or not exact arithmetic applies to your case, please
> add an explanation comment why you're using floating point numbers?
In this case inexactness doesn't matter. The term 2**tolerance_exp makes
sure that notes that are slightly shorter than the next whole duration
are rounded to the whole duration instead of somethin like "c8.....". In
some cases floating point arithmetic can cause some randomness regarding
whether the note becomes c8... or c4 (if the duration is exactly 1/32
from the next whole duration), but I don't think that matters -- such
note length are weird enough to start with.
When determining the number of dots the use of floating point arithmetic
doesn't obviously harm, because the result is rounded anyway.
I can't think of any simple way to achieve the same result without using
math.log().
The attached diff for musicxml.py now has an explanatory comment.
--- python/musicxml.py 2006-08-26 01:04:08.000000000 +0300
+++ /home/tuukka/musicxml.py 2006-09-15 19:07:23.000000000 +0300
@@ -1,4 +1,5 @@
import new
+import math
from rational import *
class Xml_node:
@@ -193,7 +194,16 @@
'long': -2,
'whole': 0} [log]
else:
- return 0
+ tolerance_exp = -4 # means that notes that are 1/32 or less shorter than 1/4 are quarter notes etc.
+ return int (math.ceil (-math.log(self._duration) / math.log(2) - 2**tolerance_exp))
+
+ def get_num_dots(self):
+ if self.get_maybe_exist_typed_child (class_dict['type']):
+ return len (self.get_typed_children (Dot))
+
+ else:
+ factor = self._duration / 2**(-self.get_duration_log())
+ return int (round (-math.log(2 - factor) / math.log(2)))
def get_factor (self):
return 1
@@ -351,27 +361,26 @@
elements.extend (m.get_all_children ())
start_attr = None
- for n in elements:
- voice_id = n.get_maybe_exist_typed_child (class_dict['voice'])
-
- if not (voice_id or isinstance (n, Attributes)):
- continue
-
- if isinstance (n, Attributes) and not start_attr:
- start_attr = n
- continue
-
- if isinstance (n, Attributes):
- for v in voices.values ():
+ for n in elements:
+ if (isinstance (n, Note)):
+ voice_id = n.get_maybe_exist_typed_child (get_class('voice'))
+ if voice_id:
+ id = voice_id.get_text ()
+ else:
+ id = '1'
+
+ if not voices.has_key (id):
+ voices[id] = Musicxml_voice()
+
+ voices[id].add_element (n)
+
+ elif isinstance (n, Attributes):
+ if not start_attr:
+ start_attr = n
+
+ for v in voices.values ():
v.add_element (n)
- continue
-
- id = voice_id.get_text ()
- if not voices.has_key (id):
- voices[id] = Musicxml_voice()
-
- voices[id].add_element (n)
-
+
if start_attr:
for (k,v) in voices.items ():
v.insert (0, start_attr)
--- scripts/musicxml2ly.py 2006-08-26 13:22:56.000000000 +0300
+++ /home/tuukka/musicxml2ly.py 2006-09-15 19:31:59.000000000 +0300
@@ -37,12 +37,8 @@
def musicxml_duration_to_lily (mxl_note):
d = musicexp.Duration ()
- if mxl_note.get_maybe_exist_typed_child (musicxml.Type):
- d.duration_log = mxl_note.get_duration_log ()
- else:
- d.duration_log = 0
-
- d.dots = len (mxl_note.get_typed_children (musicxml.Dot))
+ d.duration_log = mxl_note.get_duration_log ()
+ d.dots = mxl_note.get_num_dots()
d.factor = mxl_note._duration / d.get_length ()
return d
_______________________________________________
lilypond-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-devel