0

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.

Qing Song
  • 517
  • 1
  • 3
  • 12

1 Answers1

1

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);
    }
}
David Koelle
  • 20,726
  • 23
  • 93
  • 130