/** * Get the probability of the given transition, but do not perform that transition. * * <p>This must be called before the given transition is actually performed with {@link * #doTransition(MidiNote, int, List)}. * * @param note The {@link MidiNote} whose transition probability we want. * @param transition The value of the transition whose probability we want to get, given the * {@link MidiNote} we want to check. A negative value tells us to add the {@link MidiNote} to * a new {@link Voice} at index (-transition - 1). Any non-negative value tells us to add the * {@link MidiNote} into the existing {@link Voice} at that index in newVoices. * @param newVoices A List of the {@link Voice}s available to have the given {@link MidiNote} * added to them. * @return The probability of the given transition. */ private double getTransitionProb(MidiNote note, int transition, List<Voice> newVoices) { double logProb; Voice prev, next; // For new Voices, we need to add the Voice, and then update the transition value to // point to that new Voice so the lower code works. if (transition < 0) { transition = -transition - 1; logProb = Math.log(params.NEW_VOICE_PROBABILITY); prev = transition == 0 ? null : newVoices.get(transition - 1); next = transition == newVoices.size() ? null : newVoices.get(transition); } else { logProb = Math.log(newVoices.get(transition).getProbability(note, params)); prev = transition == 0 ? null : newVoices.get(transition - 1); next = transition == newVoices.size() - 1 ? null : newVoices.get(transition + 1); } // Check if we are in the wrong order with the prev or next Voices (or both) if (prev != null && note.getPitch() < prev.getMostRecentNote().getPitch()) { logProb -= Math.log(2); } if (next != null && note.getPitch() > next.getMostRecentNote().getPitch()) { logProb -= Math.log(2); } if (logProb == Double.NEGATIVE_INFINITY) { logProb = -Double.MAX_VALUE; } return logProb; }
/** * Get a List of the indices at which an existing {@link Voice} lies in the given List which each * of thie given incoming {@link MidiNote}s could be added. * * @param incoming A List of the {@link MidiNote}s to check for open {@link Voice}s. * @param voices A List of the {@link Voice}s we want to check. * @return A List of the open voices in newVoices for each incoming note. <code> * return.get(i).get(j)</code> will return the index of the (j+1)th (since it is 0-indexed) * open {@link Voice} in newVoices for the ith {@link MidiNote} from incoming. */ private List<List<Integer>> getOpenVoiceIndices(List<MidiNote> incoming, List<Voice> voices) { long onsetTime = incoming.get(0).getOnsetTime(); List<List<Integer>> openIndices = new ArrayList<List<Integer>>(incoming.size()); for (MidiNote note : incoming) { List<Integer> noteOpen = new ArrayList<Integer>(); for (int i = 0; i < voices.size(); i++) { if (voices.get(i).canAddNoteAtTime(onsetTime, note.getDurationTime(), params)) { noteOpen.add(i); } } openIndices.add(noteOpen); } return openIndices; }