/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package geneticmusic.choraleRules;
import geneticmusic.domain.Note;
import geneticmusic.fitness.AbstractCompositionRule;
import org.jgap.Gene;
import org.jgap.IChromosome;
/**
*
* @author davide
*/
public class VEVoiceIntervalRelation extends AbstractCompositionRule{
private static final int SOPRANO = 0;
private static final int ALTO = 1;
private static final int TENOR = 2;
private static final int BASS = 3;
public VEVoiceIntervalRelation(double weight){
super(weight);
}
@Override
protected double evaluation(IChromosome ic) {
double result = 0.0;
//for each note within range, the note gets a score
Gene[] genes = ic.getGenes();
double totalChords = genes.length;
for (int i = 0; i < genes.length; i++) {
Note[] currentNotes = (Note[]) genes[i].getAllele(); //get the current chord
if(withinRange(SOPRANO, ALTO, currentNotes[0], currentNotes[1]))
result += 1 / (totalChords * 3.0);
if(withinRange(ALTO, TENOR, currentNotes[1],currentNotes[2]))
result += 1 / (totalChords * 3.0);
if(withinRange(TENOR, BASS, currentNotes[2],currentNotes[3]))
result += 1 / (totalChords * 3.0);
}
return result;
}
/**
* Interval between S A / A T <= 8
* Interval between T B <= 12
*
* @param position
* @param note
* @return
*/
private static boolean withinRange(int note1, int note2, Note firstNote, Note secondNote) {
boolean result = false;
if(note1 == TENOR && note2 == BASS){
result = Math.abs(firstNote.distance(secondNote)) <= 12;
}
else
result = Math.abs(firstNote.distance(secondNote)) <= 8;
return result;
}
@Override
public String getName() {
return "Voice Vertical Interval Rule";
}
}