一尘不染

Java MIDI-从钢琴获取数据?

javascript

我继承了一个Java项目,该项目使用旧的C ++ dll从连接到计算机的钢琴接收MIDI数据。

既然Java内置了对MIDI设备的支持,我想摆脱旧的C ++ dll,而只使用纯Java。Java是否支持从连接到计算机的钢琴接收数据?我已经在Google上搜索了一些示例,但都无济于事。


阅读 376

收藏
2020-09-24

共2个答案

一尘不染

是的,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();
2020-09-24
一尘不染

如果您只想使用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方法。

但这只是代码外观的核心。seq调用方法后,它将所有内容记录到Sequencesequencer.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

2020-09-25