OK, I had a look at the source codes of JFugue 5.0.9 and here is what I got in ChordProgression.java:
/**
* Only converts Roman numerals I through VII, because that's all we need in music theory...
* VIII would be the octave and equal I!
*/
private int romanNumeralToIndex(String romanNumeral) {
String s = romanNumeral.toLowerCase();
if (s.startsWith("vii")) { return 6; }
else if (s.startsWith("vi")) { return 5; }
else if (s.startsWith("v")) { return 4; }
else if (s.startsWith("iv")) { return 3; }
else if (s.startsWith("iii")) { return 2; }
else if (s.startsWith("ii")) { return 1; }
else if (s.startsWith("i")) { return 0; }
else { return 0; }
}
A little laziness... :D One of the problems lies right here. If you use toLowerCase() method without specifying a locale, it causes some problems in runtime. In Turkish alphabet which I'm using right now lower case of I is "ı", not "i". So, the program converts my chords from "I-II-III" to "i-i-i" because as you can see there is no if statement for lower case I of Turkish alphabet (ı) and this leads it to return 0 as in the case of "i".
To solve this issue, we have to either delete lower case conversion and write all if statements for also upper case I's or set default locale to "en" to make sure it converts (upper case)I's to (lower case)i's. So, this should be used in the source:
Locale.setDefault(new Locale("en"));
Fortunately, JFugue is an open source software published under Apache 2.0.
This still doesn't explain why tunes sound wrong but now at least we know that these are totally different problems. Or maybe it seems so... I don't know. I will edit this answer if I ever find out an explanation or a solution for the rest.
Edit
Finally I figured out the problem with microtones by accident. I decided to look at microtone calculation functions in the source one more time.
In MicrotonePreprocessor class (which is in org.staccato package) there is a function named convertFrequencyToStaccato(). What this function does is convert frequency to midi note number and pitch bend value. At the 107th line, that code rounds semitone, octave and pitch values if calculated pitch value is very close to the next note:
// If we're close enough to the next note, just use the next note.
if (pitches >= 16380)
{
pitches = 0;
semitone += 1;
if (semitone == 12)
{
octave += 1;
semitone = 0;
}
}
The line where pitch is reset should be changed as:
pitches = 8192;
Because, you know, neutral pitch value is 8192. 0 (zero) is minimum pitch value and 16384 is maximum pitch value. At first, I thought the same way as the developer: "After 16384, it should be 0. That is okay. No problem here.". Then I said "What if I change pitch-reset value from 0 to 8192?". It worked. This was a beautiful perception error we both had. :D I'm really having a lot of laugh now.
This fixes the microtone issue. I can hear perfect intervals now! I feel happy and satisfied.
Edit2
I just wanted to share my further changes which results in better microtonal tunning:
if (pitches >= 12288)
{
int diff = 16384-pitches;
int applieddiff = 8192-diff;
pitches = applieddiff;
semitone += 1;
if (semitone == 12)
{
octave += 1;
semitone = 0;
}
}
This also helps use semitone (black) keys on a midi-board instead of only tone (white) keys with high pitch values. So, if you send the data to another software, it will detect all keys seperately. For example, there were no G and G# before, only G and G-with-high-pitch. These caused keys to stop eachother when note-on messages are sent simultaneously.