/*
* Created on Feb 2, 2007
*
* Copyright (c) 2007 Jens Gulden
*
* http://www.frinika.com
*
* This file is part of Frinika.
*
* Frinika is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Frinika 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 General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Frinika; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.frinika.sequencer.midi.sysex;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.SysexMessage;
/**
* Sysex-macro for setting interal effects on a Roland E70.
*
* This macro not only returns sysex-events, but also generates bank-select
* controller messages. (An example how flexible SysexMacros are.)
*
* @author Jens Gulden
*/
public class E70fx extends E70SysexMacroAbstract {
public String usage() {
return "Usage: e70fx <reverb-type> <reverb-intensity> <chorus-type> <chorus-intensity> [ <user-prg> ] [ <use-prg-change> ]";
}
public final static int ADDR_OFFSET_REVERB = 0x15;
public final static int ADDR_OFFSET_CHORUS = 0x16;
public final static String[] REVERB_TYPES = {
"Off",
"Room1",
"Room2",
"Room3",
"Hall1",
"Hall2",
"Plate",
"Delay",
"Panning"
};
public final static String[] CHORUS_TYPES = {
"Off",
"Chorus1",
"Chorus2",
"Chorus3",
"Chorus4",
"Feedback",
"Flanger",
"Delay1",
"Delay2"
};
/**
* Macro: e70fx <reverb-type> <reverb-intensity> <chorus-type> <chorus-intensity> [ <user-prg> ] [ <use-prg-change> ]
*
* Sets the built-in reverb-effect style on one of the user-programs.
* There are two modes of operation:
* In order to overcome the limitation that the actively
* selected user-program cannot be configured via sysex, the current
* user-program will be changed to before sending the sysex message
* and after having made the changes will be switched back again.
* This has the effect that after setting the effect this way, the
* <user-prg> will be the actively selected one, even if it hadn't
* been selected before.
* To disable the special behaviour of switching user-programs, use
*
* arg[0]: reverb-type (0: none, 1: room1, 2: room2, 3: room3, 4: hall1, etc.)
* arg[1]: reverb-intensity (0-7)
* arg[2]: chorus-type (0: none, 1: chorus1, 2: chorus2, etc.)
* arg[3]: chorus-intensity (0-7)
* arg[4] (optional): user-program to modify, default "11" (0)
* arg[5] (optional): channel on which to send user program switch, may differ
* from current Frinika-track's channel. Default is 16 (i.e.
* 15 if counting from 0 to 15), use -1 to disable sending
* user-program changes before and after the sysex data.
*/
public MidiMessage[] parseMessages(String macro) throws InvalidMidiDataException {
String[] args = splitArgs(macro);
int usrPrg = 0;
int chn = 15;
if (args.length > 4) {
usrPrg = parseInt(args[4], 10);
}
if (args.length > 5) {
chn = parseInt(args[5], 10);
}
byte[] data = parse(args); // get sysex data
SysexMessage syxm = new SysexMessage();
syxm.setMessage(data, data.length);
if ((chn >= 0) && (chn <= 15)) {
int otherUsrPrg = (usrPrg == 0) ? 1 : 0;
MidiMessage[] prgChg = usrPrgChg( otherUsrPrg, chn );
MidiMessage[] prgChgBack = usrPrgChg( usrPrg, chn );
MidiMessage[] mm = { prgChg[0], prgChg[1], prgChg[2],
syxm,
prgChgBack[0], prgChgBack[1], prgChgBack[2] };
return mm;
} else {
return new MidiMessage[] { syxm };
}
}
public byte[] parse(String[] args) throws InvalidMidiDataException {
if (args.length < 4) {
error("At least 4 parameters are required.");
}
int reverbType = parseType(args[0], REVERB_TYPES);
int reverbIntensity = parseInt(args[1], 10, 1, 8);
int chorusType = parseType(args[2], CHORUS_TYPES);
int chorusIntensity = parseInt(args[3], 10, 1, 8);
int usrPrg = 0;
if (args.length > 4) {
usrPrg = parseInt(args[4], 10, 0, 99);
}
// let intensities start with 1 (except set to 0 already)
if (reverbIntensity > 0) reverbIntensity -= 1;
if (chorusIntensity > 0) chorusIntensity -= 1;
byte reverbData = (byte)(((reverbType << 4) & 0xf0) | (reverbIntensity & 0xf));
byte chorusData = (byte)(((chorusType << 4) & 0xf0) | (chorusIntensity & 0xf));
return e70UserProgramSet(usrPrg, ADDR_OFFSET_REVERB, new byte[] { reverbData, chorusData } );
}
}