In jFugue 4.0 there's a nice function: Transforming Patterns with PatternTransformer
but all pattern transformers are removed in jFugue 5.0. I understand it must be replaced with something cool. but what to do in jFugue 5.0 please? i get no clue. I googled but have so far had no outcome.
The class "PatternTransformer" has gone, but transforming patterns has never been easier!
In older versions of JFugue, there was actually very little difference between a PatternTransformer and a ParserListener. Older versions of JFugue also referred to a PatternTool, which was like a Transformer but instead of transforming a pattern, it would just measure it; for example, you could write a tool to tell you what instruments were used in a piece.
To transform a Pattern in JFugue, just create a class that implements ParserListener (or extends ParserListenerAdapter), and add it as a listener to a parser - such as a StaccatoParser:
For example, here's a tool that finds what instruments are used in a piece:
public class InstrumentTool extends ParserListenerAdapter
{
private List<String> instrumentNames;
public InstrumentTool() {
super();
instrumentNames = new ArrayList<String>();
}
@Override
public void onInstrumentParsed(byte instrument) {
String instrumentName = MidiDictionary.INSTRUMENT_BYTE_TO_STRING.get(instrument);
if (!instrumentNames.contains(instrumentName)) {
instrumentNames.add(instrumentName);
}
}
public List<String> getInstrumentNames() {
return this.instrumentNames;
}
}
and here's how to use it:
MidiParser midiParser = new MidiParser();
InstrumentTool instrumentTool = new InstrumentTool();
midiParser.addParserListener(instrumentTool);
midiParser.parse(MidiSystem.getSequence(new File("filename")));
List<String> instrumentNames = instrumentTool.getInstrumentNames();
for (String name : instrumentNames) {
System.out.println(name);
}
There's a new class in JFugue 5 that lets you chain ParserListeners together. This would let you create a chain of listeners that each modify a pattern before sending events to the next listener in the chain. For example, suppose you have a pattern, and you want to transform all of the instruments (say, change GUITAR to PIANO); then you want to take any note played with PIANO and stretch its duration by two; then you want to take any note with a new duration greater than 2.0 (two whole notes) and you want to change its octave. A bit of a crazy example, but it shows the need for a "chaining" series of parser listeners.
Here's a demo example that uses chaining. This class reads a MIDI pattern; it then changes all of the instruments, and then it creates a Staccato pattern from the original MIDI.
public class ChainingParserListenerDemo {
public static void main(String[] args) throws InvalidMidiDataException, IOException {
MidiParser parser = new MidiParser();
InstrumentChangingParserListener instrumentChanger = new InstrumentChangingParserListener();
StaccatoParserListener staccatoListener = new StaccatoParserListener();
instrumentChanger.addParserListener(staccatoListener);
parser.addParserListener(instrumentChanger);
parser.parse(MidiSystem.getSequence(new File("filename")));
System.out.println("Changed "+instrumentChanger.counter+" Piano's to Guitar! "+ staccatoListener.getPattern().toString());
}
}
class InstrumentChangingParserListener extends ChainingParserListenerAdapter {
int counter = 0;
@Override
public void onInstrumentParsed(byte instrument) {
if (instrument == MidiDictionary.INSTRUMENT_STRING_TO_BYTE.get("PIANO")) {
instrument = MidiDictionary.INSTRUMENT_STRING_TO_BYTE.get("GUITAR");
counter++;
}
super.onInstrumentParsed(instrument);
}
}