/* * 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; /** * Provides the ability to build a rhythm using a simple strings in which * individual characters represent MusicString elements. * * For example, you can develop a drum beat that looks like this: <code> * oo'' o' oo'' o' oo'' o' oo'' o'... * </code> * * As of JFugue 4.0, the Rhythm allows the addition of voices outside of the * percussion track using the addVoice() method. * * This feature is covered in detail in "The Complete Guide to JFugue" * * @see Player * @author David Koelle * @version 3.0 * @version 4.0.3 - Now implements Serializable */ public class Rhythm { private Map<Character, String> charToNote; private String[] layers; private String[] voices; private String[] voiceDetails; private int MAX_LAYERS = 127; private int MAX_VOICES = 16; private int PERCUSSION_TRACK = 9; public Rhythm() { charToNote = new HashMap<Character, String>(); layers = new String[MAX_LAYERS]; voices = new String[MAX_VOICES]; voiceDetails = new String[MAX_VOICES]; } public void addSubstitution(char stringChar, String musicString) { charToNote.put(stringChar, musicString); } public String getSubstitution(char stringChar) { return charToNote.get(stringChar); } public void removeSubstitution(char stringChar) { charToNote.remove(stringChar); } public void setLayer(int layer, String rhythmString) { if ((layer < 0) || (layer > MAX_LAYERS)) { throw new JFugueException(JFugueException.LAYER_EXC, Integer.toString(layer), rhythmString); } layers[layer] = rhythmString; } public String getLayer(int layer) { return this.layers[layer]; } public void clearLayer(int layer) { this.layers[layer] = null; } public void setVoice(int voice, String rhythmString) { if ((voice < 0) || (voice > MAX_LAYERS) || (voice == PERCUSSION_TRACK)) { throw new JFugueException(JFugueException.VOICE_EXC, Integer.toString(voice), rhythmString); } voices[voice] = rhythmString; } public String getVoice(int voice) { return this.voices[voice]; } public void clearVoice(int voice) { this.voices[voice] = null; } public void setVoiceDetails(int voice, String musicString) { if ((voice < 0) || (voice > MAX_LAYERS) || (voice == PERCUSSION_TRACK)) { throw new JFugueException(JFugueException.VOICE_EXC, Integer.toString(voice), musicString); } voiceDetails[voice] = musicString; } public String getVoiceDetails(int voice) { return this.voiceDetails[voice]; } public void clearVoiceDetails(int voice) { this.voiceDetails[voice] = null; } public String getMusicString() { StringBuffer buffy = new StringBuffer(); // Start by adding the percussion track buffy.append("V9 "); for (int i = 0; i < MAX_LAYERS; i++) { String rhythmString = getLayer(i); if (rhythmString != null) { buffy.append("L"); buffy.append(i); buffy.append(" "); for (int r = 0; r < rhythmString.length(); r++) { char ch = rhythmString.charAt(r); String substitution = getSubstitution(ch); if (substitution != null) { buffy.append(substitution); buffy.append(" "); } } } } // Add the voices for (int i = 0; i < MAX_VOICES; i++) { boolean voiceCommandAdded = false; String detailsString = getVoiceDetails(i); if (detailsString != null) { buffy.append("V"); buffy.append(i); voiceCommandAdded = true; buffy.append(" "); buffy.append(detailsString); buffy.append(" "); } String rhythmString = getVoice(i); if (rhythmString != null) { if (!voiceCommandAdded) { buffy.append("V"); buffy.append(i); buffy.append(" "); } for (int r = 0; r < rhythmString.length(); r++) { char ch = rhythmString.charAt(r); String substitution = getSubstitution(ch); if (substitution != null) { buffy.append(substitution); buffy.append(" "); } } } } return buffy.toString(); } public Pattern getPattern() { return new Pattern(getMusicString()); } public Pattern getPatternWithInterval(Pattern pattern) { IntervalNotation interval = new IntervalNotation(getMusicString()); return interval.getPatternForRootNote(pattern); } public Pattern getPatternWithInterval(String string) { IntervalNotation interval = new IntervalNotation(getMusicString()); return interval.getPatternForRootNote(string); } public Pattern getPatternWithInterval(Note rootNote) { IntervalNotation interval = new IntervalNotation(getMusicString()); return interval.getPatternForRootNote(rootNote); } }