/*
* 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;
/**
* EXPERIMENTAL - Contains a variety of static methods that create Patterns that
* play various musical ornaments
*
* @author David Koelle
* @version 4.0
*/
public class MusicalEffects {
/**
* Returns a Pattern that plays two notes in rapid succession (for a total
* of each note being played numHammers times) over the given duration.
*
* The resulting Pattern will have note1 and note2 both represented
* numHammers times.
*
* Example: hammerOn(new Note("C5"), new Note("E5"), 0.5, 4); will produce
* this Pattern: [60]/0.125 [64]/0.125 [60]/0.125 [64]/0.125 [60]/0.125
* [64]/0.125 [60]/0.125 [64]/0.125
*
* @param note1
* First note to play
* @param note2
* Second note to play
* @param duration
* Value representing total duration for the resulting pattern.
* 1.0=whole note
* @param numHammers
* Number of times to repeat each note
*/
public static Pattern hammerOn(Note note1, Note note2, double duration,
int numHammers) {
StringBuilder buddy = new StringBuilder();
double durationPerHammer = duration / numHammers;
buddy.append("[");
buddy.append(note1.getValue());
buddy.append("]/");
buddy.append(durationPerHammer / 2.0);
buddy.append(" [");
buddy.append(note2.getValue());
buddy.append("]/");
buddy.append(durationPerHammer / 2.0);
Pattern pattern = new Pattern(buddy.toString());
pattern.repeat(numHammers);
return pattern;
}
/**
* Returns a Pattern that plays a slide between two notes over the given
* duration.
*
* TODO: This is currently a naive implementation, which sounds 'numSteps'
* notes, each with a duration of 'duration/numSteps'. This means that if
* you're sliding from a F to a G, for example, you could get music that
* looks like F F F F F F F F G G G G G G, with each note having a very
* short duration. The problem with this is that the sound of each note
* stopping and starting again is noticeable. A more intelligent
* implementation would sound each note for as long as necessary, then sound
* a different note only when the microtonal math requires it. Otherwise,
* the pitch wheel messages should cause the note to change while it is
* playing. This implementation may require one or more new methods in
* MicrotoneNotation.
*/
public static Pattern slide(Note note1, Note note2, double duration,
int numSteps) {
StringBuilder buddy = new StringBuilder();
double durationPerStep = duration / numSteps;
double freq1 = Note.getFrequencyForNote(note1.getValue());
double freq2 = Note.getFrequencyForNote(note2.getValue());
double differencePerStep = (freq2 - freq1) / numSteps;
for (int i = 0; i < numSteps; i++) {
buddy.append(
MicrotoneNotation.convertFrequencyToMusicString(freq1));
buddy.append("/");
buddy.append(durationPerStep);
buddy.append(MicrotoneNotation.getResetPitchWheelString());
buddy.append(" ");
freq1 += differencePerStep;
}
Pattern pattern = new Pattern(buddy.toString());
return pattern;
}
/**
* Right now, this is a pass-through to hammerOn()
*
* @see hammerOn
*/
public static Pattern trill(Note note1, Note note2, double duration,
int numSteps) {
return hammerOn(note1, note2, duration, numSteps);
}
}