/*
* JFugue - API for Music Programming
* Copyright (C) 2003-2008 David Koelle
*
* http://www.jfugue.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.jfugue;
import java.util.HashMap;
import java.util.Map;
/**
* Facilitates playing microtonal music - Indian, Turkish, Indonesian, etc.
* styles. Also useful for performing slides and other effects that rely on
* "the notes in between the notes".
*
* This feature is covered in detail in "The Complete Guide to JFugue"
*
* @author David Koelle
* @version 3.0
* @version 4.0 - renamed from MicrotoneHelper; mictoronal notes now encased in
* angle brackets instead of square brackets, for consistency
*/
public class MicrotoneNotation {
private Map<String, Double> keyToFreqDict;
private Map<String, String> keyToMusicStringDict;
public MicrotoneNotation() {
keyToFreqDict = new HashMap<String, Double>();
keyToMusicStringDict = new HashMap<String, String>();
}
public void put(String key, double freq) {
keyToFreqDict.put(key, freq);
keyToMusicStringDict.put(key, convertFrequencyToMusicString(freq));
}
public double get(String key) {
return keyToFreqDict.get(key);
}
public String getMusicString(String key) {
return keyToMusicStringDict.get(key);
}
/**
* Converts the given frequency to a music string that involves the Pitch
* Wheel and notes to create the frequency
*
* @param freq
* the frequency
* @return a MusicString that represents the frequency
*/
public static String convertFrequencyToMusicString(double freq) {
double totalCents = 1200 * Math.log(freq / 16.3515978312876)
/ Math.log(2);
double octave = Math.round(totalCents / 1200.0);
double semitoneCents = totalCents - (octave * 1200.0);
double semitone = Math.round(semitoneCents / 100.0);
double cents = 8192 + Math.round(semitoneCents - (semitone * 100));
double note = ((octave + 1) * 12) + semitone; // This gives a MIDI
// value, 0 - 128
if (note > 127) {
note = 127;
}
StringBuilder buffy = new StringBuilder();
buffy.append("&");
buffy.append((int) cents);
buffy.append(" [");
buffy.append((int) note);
buffy.append("]");
return buffy.toString();
}
public static String getResetPitchWheelString() {
return (" &8192"); // Reset the pitch wheel. 8192 = original pitch wheel
// position
}
public Pattern getPattern(String notation) {
StringBuilder buddy = new StringBuilder();
String[] tokens = notation.split(" ");
// Go through the Pattern, and replace known microtone keys with
// microtone music strings
for (int i = 0; i < tokens.length; i++) {
if ((tokens[i].length() > 0) && (tokens[i].charAt(0) == '<')) {
int end = tokens[i].indexOf('>');
String possibleKey = tokens[i].substring(1, end);
if (keyToMusicStringDict.containsKey(possibleKey)) {
buddy.append(keyToMusicStringDict.get(possibleKey));
buddy.append(
tokens[i].substring(end + 1, tokens[i].length())); // Add
// the
// rest
// of
// the
// token
buddy.append(getResetPitchWheelString());
} else {
buddy.append(tokens[i]);
}
} else {
buddy.append(tokens[i]);
}
buddy.append(" ");
}
return new Pattern(buddy.toString());
}
}