我继承了一个Java项目,该项目使用旧的C ++ dll从连接到计算机的钢琴接收MIDI数据。
既然Java内置了对MIDI设备的支持,我想摆脱旧的C ++ dll,而只使用纯Java。Java是否支持从连接到计算机的钢琴接收数据?我已经在Google上搜索了一些示例,但都无济于事。
是的,JavaSound API可用于从MIDI设备读取MIDI数据。
JFugue是用于音乐编程的Java API,它使用JavaSoundAPI,可以帮助简化与JavaSound的交互。在JFugue5.x中,从MIDI设备捕获10秒MIDI数据的示例代码如下:
MidiDevice device = /* specify a MIDI device */ MusicTransmitterToSequence transmitter = new MusicTransmitterToSequence(device); transmitter.listenForMillis(10000); Sequence music = transmitter.getSequence(); 您还可以开始和停止收听设备: MidiDevice device = /* specify a MIDI device */ MusicTransmitterToSequence transmitter = new MusicTransmitterToSequence(device); transmitter.startListening(); // Do stuff transmitter.stopListening(); Sequence music = transmitter.getSequence();
如果您只想使用Java的MIDI api(javax.sound.midi。*)进行录制,则非常容易做到。这不是要复制和粘贴的代码,但是它应该可以帮助您开始编写自己的MIDI录音机,这实际上非常容易。
第一步是定义您的输入和输出MidiDevice。因此,首先您必须找到IO可能性的列表,并创建一个GUI,在其中可以选择用于MIDI记录和播放的输入和输出设备。
Info[] infos = MidiSystem.getMidiDeviceInfo(); for(int i=0;i<infos.length;i++) { System.out.println(infos[i].getName() + " - " + infos[i].getDescription()); }
因此,这里有您的MIDI设备列表。接下来,您要选择一个MIDI设备,例如,您可以在infos数组中选择索引。
MidiDevice inputDevice = MidiSystem.getMidiDevice(infos[x]); MidiDevice outputDevice = MidiSystem.getMidiDevice(infos[y]);
您还需要指定一些全局变量:定序器,发送器和接收器。
Sequencer sequencer = MidiSystem.getSequencer(); Transmitter transmitter; Receiver receiver; 现在,有一个您要使用的记录按钮。 // Open a connection to your input device inputDevice.open(); // Open a connection to the default sequencer (as specified by MidiSystem) sequencer.open(); // Get the transmitter class from your input device transmitter = inputDevice.getTransmitter(); // Get the receiver class from your sequencer receiver = sequencer.getReceiver(); // Bind the transmitter to the receiver so the receiver gets input from the transmitter transmitter.setReceiver(receiver); // Create a new sequence Sequence seq = new Sequence(Sequence.PPQ, 24); // And of course a track to record the input on Track currentTrack = seq.createTrack(); // Do some sequencer settings sequencer.setSequence(seq); sequencer.setTickPosition(0); sequencer.recordEnable(currentTrack, -1); // And start recording sequencer.startRecording();
当心,此代码可能会引发MidiUnavailableExceptions,并且您应该在finally语句中打开的所有内容上调用close方法。
MidiUnavailableExceptions
但这只是代码外观的核心。seq调用方法后,它将所有内容记录到Sequence 中sequencer.startRecording()。
seq
Sequence
sequencer.startRecording()
然后,您要停止录制,并能够将序列作为MIDI保存到文件或进行播放。例如,当您按下“停止记录”按钮时,这可能是代码。
// Stop recording if(sequencer.isRecording()) { // Tell sequencer to stop recording sequencer.stopRecording(); // Retrieve the sequence containing the stuff you played on the MIDI instrument Sequence tmp = sequencer.getSequence(); // Save to file MidiSystem.write(tmp, 0, new File("MyMidiFile.mid")); }
同样,Track类(一个序列可以具有多个轨道)包含实际的输入数据,您可以通过get方法轻松访问该数据。Track类包含MidiEvents。例如,轨道为:
MidiEvent 0: The C key is pressed MidiEvent 1: The D key is pressed MidiEvent 2: The C key of MidiEvent 0 is released MidiEvent 3: The sustain pedal is pressed etc...
而且每个MidiEvent都有一定的时间戳,以MIDI音调表示,因此您可以通过增加或减少每秒的滴答声数量来轻松更改速度。
这里最困难的问题是MidiEvents用字节码表示,因此您将不得不使用参考字节码表,该表告诉您哪个字节代表什么动作。这应该使您开始:http : //www.onicos.com/staff/iz/formats/midi-event.html