When analysing some apparently well-formed MIDI files, the PhraseAnalysis.getStatisticsAsDoubles() method returns quantisation exceptions for these four statistics:
03 - Key Centeredness: QuantisationException
04 - Tonal Deviation: QuantisationException
13 - Note Density: QuantisationException
14 - Rest Density: QuantisationException
I'm pretty sure the reason this happens is that the statistics are using the PhraseAnalysis.isQuantised() method, and it regards a note of rhythm value 0.500000001 (or similar) as NOT quantised. See this code in PhraseAnalysis.isQuantised():
for (int i = 0; i < noteArray.length; i++) {
if (noteArray[i].getRhythmValue () % duration != 0.0) {
return false;
}
}
This will return false if the duration doesn't divide each note's rhythm value perfectly. Floats and doubles can't represent every number exactly, so sometimes 0.5f turns out to be 0.5000000001. I don't fully understand this, but in general it's dangerous to compare floating-point numbers using "==" and "!=". Maybe this code would be better?
for (int i = 0; i < noteArray.length; i++) {
// allow for floating-point error
if (noteArray[i].getRhythmValue () % duration > 0.0001) {
return false;
}
}
The MIDI file which gave me these slightly-off rhythm values is this one: http://www.glasspages.org/opening.mid
Also, I'll attach source code which performs the analysis, so you can see the exceptions as I pasted them above. It also prints out the rhythm values.
Thanks for your attention, and of course for making jMusic!
James McDermott
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
Source file: demonstrates bug using http://www.glasspages.org/opening.mid
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
Analyses a MIDI file. This version uses correct quantum for "opening.mid".
View and moderate all "bugs Discussion" comments posted by this user
Mark all as spam, and block user from posting to "Bugs"
Oops -- just noticed two extra things.
First, the MIDI file I mentioned includes rhythm values like 0.3333333333 as well as like 0.25 and 0.500000001, so the correct quantum is (1/3)*(1/4) = 1/12. This is reflected in the new FileAnalysis.java, attached.
Also, in addition to 0.50000001, it's possible to get 0.4999999999. This causes a similar error, but needs to be taken care of in the isQuantised() code also. This seems to work for me:
for (int i = 0; i < noteArray.length; i++) {
// allow for floating-point error
double epsilon = 0.000001;
double excessRV = noteArray[i].getRhythmValue () % duration;
if (excessRV > epsilon && excessRV < duration - epsilon) {
System.out.println("not quantised: rv = " + noteArray[i].getRhythmValue ());
System.out.println("also: rv % dur = " + excessRV);
return false;
}
}
return true;