我目前正在编写一个简单的应用程序,它从midi设备接收输入并输出相应的声音。我现在已经完成了所有工作,但有两个问题:首先,当我在程序启动后插入midi设备或在程序运行时断开它时,它将无法识别。其次,OSX,Linux(Raspbian)和Windows等的延迟非常高。有谁知道这些问题的解决方案? 以下是我到目前为止的情况:
MidiHandler类读取输入并合成声音
public class MidiHandler {
MidiDevice device;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
List<Transmitter> transmitters;
MidiInputReceiver reciever;
public MidiHandler() {
for (int i = 0; i < infos.length; i++) {
try {
this.device = MidiSystem.getMidiDevice(this.infos[i]);
// does the device have any transmitters?
// if it does, add it to the device list
System.out.println(this.infos[i]);
// get all transmitters
this.transmitters = this.device.getTransmitters();
// using my own MidiInputReceiver
this.reciever = new MidiInputReceiver(this.device
.getDeviceInfo().toString());
// and for each transmitter
for (int j = 0; j < this.transmitters.size(); j++) {
// create a new receiver
this.transmitters.get(j).setReceiver(this.reciever);
}
Transmitter trans = this.device.getTransmitter();
trans.setReceiver(new MidiInputReceiver(this.device
.getDeviceInfo().toString()));
this.device.open();
} catch (MidiUnavailableException e) {
}
}
}
public void playNote(byte b) {
reciever.playNote(b);
}
public void stopNote(byte b) {
reciever.stopNote(b);
}
public void close() {
for (int i = 0; i < this.transmitters.size(); ++i) {
this.transmitters.get(i).close();
}
this.reciever.close();
this.device.close();
}
public String getInfos() {
String infos = "";
for (int i = 0; i < this.infos.length; i++) {
infos += "\n" + this.infos[i] + " ";
}
return infos;
}
// tried to write my own class. I thought the send method handles an
// MidiEvents sent to it
public class MidiInputReceiver implements Receiver {
Synthesizer synth;
MidiChannel[] mc;
Instrument[] instr;
int instrument;
int channel;
public MidiInputReceiver(String name) {
try {
patcher p = new patcher();
this.instrument = p.getInstrument();
this.channel = p.getChannel();
this.synth = MidiSystem.getSynthesizer();
this.synth.open();
this.mc = synth.getChannels();
instr = synth.getDefaultSoundbank().getInstruments();
this.synth.loadInstrument(instr[1]);
mc[this.channel].programChange(0, this.instrument);
} catch (MidiUnavailableException e) {
e.printStackTrace();
System.exit(1);
}
}
public void send(MidiMessage msg, long timeStamp) {
/*
* Use to display midi message
for (int i = 0; i < msg.getMessage().length; i++) {
System.out.print("[" + msg.getMessage()[i] + "] ");
}
System.out.println();
*/
if (msg.getMessage()[0] == -112) {
mc[this.channel].noteOn(msg.getMessage()[1],
msg.getMessage()[2] + 1000);
}
if (msg.getMessage()[0] == -128) {
mc[this.channel].noteOff(msg.getMessage()[1],
msg.getMessage()[2] + 1000);
}
}
public void playNote(byte b) {
mc[this.channel].noteOn(b, 1000);
}
public void stopNote(byte b) {
mc[this.channel].noteOff(b);
}
public void close() {
}
}
Shell类包含主要方法
public class Shell {
private static MidiHandler midi;
AudioServer server;
private Shell() {
}
/**
* The main method. Executes via BufferedReader, to communicate with the
* user
*
* @param args
* Command line parameter
* @throws IOException
* IOExeption can occur
*/
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
execute(in);
}
/**
* Method used for general interaction with the user. Utilizes a
* BufferedReader to read inputs, then proceeds to analyze the input for
* predefined commands
*
* @param in
* The BufferedReader in use
* @throws IOException
* @throws ParseException
*/
private static void execute(BufferedReader in) throws IOException {
boolean quit = false;
while (!quit) {
midi = new MidiHandler();
System.out.print("midi> ");
String input;
input = in.readLine(); // read line
if (input == null | input.isEmpty()) {
break;
} // No command given?
// First character is always the command.
char command = Character.toLowerCase(input.charAt(0));
try {
switch (command) {
case 'n':
midi = new MidiHandler();
break;
case 'c':
midi.close();
break;
case 'p':
midi.playNote((byte) 60);
break;
case 's':
midi.stopNote((byte) 60);
case 'q':
midi.close();
quit = true;
System.exit(0);
break;
default:
System.out.println("Unknown command");
break;
}
} catch (NumberFormatException e) {
System.out.println("Invalid parameter");
}
}
}
非常感谢任何帮助。提前谢谢。