|
SonicCell
package midi;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiUnavailableException;
@author
@version
@serial
public class SonicCell {
private Map<String,Integer[]>soundLibrary = new HashMap<>();
private Integer[] tempPatchAddress(int part){
switch (part){
case 1: return new Integer[]{0x11,0x20,0,0};
case 2: return new Integer[]{0x11,0x40,0,0};
case 3: return new Integer[]{0x11,0x60,0,0};
case 4: return new Integer[]{0x12,0x00,0,0};
case 5: return new Integer[]{0x12,0x20,0,0};
case 6: return new Integer[]{0x12,0x40,0,0};
case 7: return new Integer[]{0x12,0x50,0,0};
case 8: return new Integer[]{0x13,0x00,0,0};
case 9: return new Integer[]{0x13,0x20,0,0};
case 10: return new Integer[]{0x13,0x40,0,0};
case 11: return new Integer[]{0x13,0x60,0,0};
case 12: return new Integer[]{0x14,0x00,0,0};
case 13: return new Integer[]{0x14,0x20,0,0};
case 14: return new Integer[]{0x14,0x40,0,0};
case 15: return new Integer[]{0x14,0x60,0,0};
default: return new Integer[]{0x11,0x00,0,0};
}
}
private void initSoundLibrary(){
soundLibrary = SonicCellConstants.NameToMsbLsbPrg();
}
Berechnet die Roland-Checksumme
@param sequence
@param offset
@return
private int checkSum(List<Integer> sequence, int offset){
int sum = 0;
for (int i=offset; i<sequence.size(); i++){
sum += sequence.get(i);
sum %= 128;
}
return 128-sum;
}
Baut eine SyxX-Nachricht für den SonicCell zusammen
@param address
@param data
@return
protected List<Integer> createSysX(Integer[] address, Integer[] data){
List<Integer> result = new ArrayList<>();
Integer[] starter = {0xF0,0x41,0x10,0x00,0x00,0x25,0x12};
result.addAll(Arrays.asList(starter));
result.addAll(Arrays.asList(address));
result.addAll(Arrays.asList(data));
result.add(checkSum(result,starter.length));
result.add(0xF7);
return result;
}
public SonicCell(){
initSoundLibrary();
}
Gibt eine Map zurück, in der alle (für mich wichtigen) Sounds symbolisch gespeichert sind.
@return
public Map<String,Integer[]> getSoundLibrary(){
return soundLibrary;
}
Setzt die Performance so, dass alle Parts ausgeschaltet sind und auf Midikanal 1 stehen
@return
public List<Integer> resetAllPartBasics(){
List<Integer> sequence = new ArrayList<>();
for (int i=0; i<16; i++){
sequence.addAll(createSysX(new Integer[]{0x10,00,0x20+i,0x00},new Integer[]{0,0}));
sequence.addAll(setPartKeyRange(i,0,127));
sequence.addAll(setPartMute(i,false));
sequence.addAll(setPartShift(i,0));
}
return sequence;
}
Setzt den Sound für einen Part der temporären Performance
@param part
@param msb
@param lsb
@param prg
@return
public List<Integer> setPartProgram(int part, int msb, int lsb, int prg){
return createSysX(new Integer[]{0x10,00,0x20+part,0x04},new Integer[]{msb,lsb,prg});
}
Setzte den Sound für einen Part der temporären Performance
@param part
@param symbolicName
@return
public List<Integer> setPartProgram(int part, String symbolicName){
Integer[] tmp = soundLibrary.get(symbolicName);
if (tmp==null) return null;
return setPartProgram(part,tmp[0],tmp[1],tmp[2]);
}
Setzt die untere und obere Note für den Keyrange dieses Parts
@param part
@param lower
@param upper
@return
public List<Integer> setPartKeyRange(int part, int lower, int upper){
return createSysX(new Integer[]{0x10,00,0x20+part,0x17},new Integer[]{lower,upper});
}
Setzt den Receive-Switch des Parts
@param part
@param state
@return
public List<Integer> setPartSwitch(int part, boolean state){
int tmp = state?1:0;
System.out.println("send switch: "+part+"->"+tmp);
return createSysX(new Integer[]{0x10,000,0x20+part,0x01},new Integer[]{tmp});
}
Setzt die Midi-kontrollierbare Lautstärke eines Parts
@param part
@param level
@return
public List<Integer> setPartLevel(int part, int level){
return createSysX(new Integer[]{0x10,000,0x20+part,0x07},new Integer[]{level});
}
Setzt die End-Lautstärke eines Parts
@param part
@param level
@return
public List<Integer> setPartOutputLevel(int part, int level){
return createSysX(new Integer[]{0x10,000,0x20+part,0x1C},new Integer[]{level});
}
public List<Integer> setPartLevelInTempPatch(int part, int level){
Integer[] address = tempPatchAddress(part);
address[3] = 0x0E;
return createSysX(address,new Integer[]{level});
}
public List<Integer> setPartHold(int part, boolean receive){
return createSysX(new Integer[]{0x10,0x00,0x10+part,0x09},new Integer[]{receive?1:0});
}
Setzt die Verschiebung um bis zu 3 Oktaven nach unten oder oben.
@param part
@param shift
@return
public List<Integer> setPartShift(int part, int shift){
shift += 64;
return createSysX(new Integer[]{0x10,000,0x20+part,0x15},new Integer[]{shift});
}
public List<Integer> setPartMute(int part, boolean mute){
int tmp = mute?1:0;
System.out.println("mute switch: "+part+"->"+tmp);
return createSysX(new Integer[]{0x10,000,0x20+part,0x1B},new Integer[]{tmp});
}
Wechselt das Program auf Kanal "channel
@param channel
@param msb
@param lsb
@param program
@return
public List<Integer> changeProgram(int channel, int msb, int lsb, int program){
return Arrays.asList(new Integer[]{0xC0+channel,program});
}
Only for test-purposes
@param args
@throws
@throws
@throws
public static void main(String[] args) throws MidiUnavailableException, InvalidMidiDataException, InterruptedException{
SonicCell sonicCell = new SonicCell();
MidiBase.init();
MidiBase.setDevice("1:Roland SonicCell:External MIDI Port (5.10)");
MidiBase.send(sonicCell.setPartSwitch(3, false));
}
}
|