我将首先明确说明我的主要问题:当使用 Java 合成器录制到 Java 音序器时,用正确的“滴答”从 ShortMessages 中以正确的微秒位置创建 midi 事件的正确方法是什么?
几天来,我一直试图弄清楚这一点。我的小 MIDI 程序非常简单,或者至少应该如此。有一个钢琴布局和三个按钮。使用合成器的钢琴效果很好;您可以使用鼠标或电脑键盘弹奏音符。
我已经前后阅读了 Oracle Docs 说明(以及许多论坛主题),但显然我遗漏了一些东西。
目前,我可以通过手动创建一个 ShortMessage、一个 MidiEvent 并将它们发送到音序器/将它们添加到音轨来让音序器录制,但它只会录制一次。回放也会以错误的时间回放它们。这是执行这些的代码:(如果您希望我发布其他或所有代码,请告知)。
单击记录/停止/按钮时发生的情况的代码:
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand() == "Record")
{
mySeq.deleteTrack(track);
track = mySeq.createTrack();
try {
seq.setSequence(mySeq);
} catch (InvalidMidiDataException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
seq.recordEnable(track, ChannelNum);
seq.startRecording();
}
else if(e.getActionCommand() == "Stop")
{
seq.stop();
}
else if(e.getActionCommand() == "Play")
{
mySeq.deleteTrack(track);
track = mySeq.createTrack();
addEvents(track);
seq.setTickPosition(10);
seq.start();
}
}
这是用户在钢琴上弹奏音符时的代码:
// The Mouse presses a key, the note on the channel is turned on
// A MidiEvent and ShortMessage are created using the CreateOnEvent method
public void mousePressed (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOn (key.getNote (), 127);
CreateOnEvent(key);
}
public void mouseReleased (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOff (key.getNote ());
CreateOffEvent(key);
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
最后是 CreateOnEvent 方法:
// I originally was sending the events directly to the sequencer
// but here I'm adding the events to an ArrayList of MidiEvents to attempt a work around
// I can then add those events to a track to play them
public void CreateOnEvent(Key key)
{
if(seq.isRecording())
{
ShortMessage myMsg = new ShortMessage();
try {
myMsg.setMessage(ShortMessage.NOTE_ON, ChannelNum, key.getNote(), 127);
} catch (InvalidMidiDataException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
long timeStamp = synth.getMicrosecondPosition();
long tick = seq.getTickPosition();
event = new MidiEvent(myMsg, tick);
seqReceiver.send(myMsg, timeStamp);
Events.add(event);
}
}