继我的问题here后,我创建了一个列表,允许我排队需要播放的音符集合,然后将这些音符按顺序添加到音轨中,以便它们可以在一个音轨中播放去。
我将要在轨道中播放的音符添加到临时列表中,如下所示:
int pitch = jComboBoxPitch.getSelectedIndex();
int velocity = ((Integer)jSpinnerVelocity.getValue());
collection.add(new MIDIMessage(pitch,velocity));
当用户添加了所需的所有笔记后,按“播放”按钮:
private void PlayMIDI()
{
try
{
Sequencer seq = MidiSystem.getSequencer();
seq.open();
Sequence sequence1 = new Sequence(Sequence.PPQ,16);
Track track = sequence1.createTrack();
Iterator itr = collection.iterator();
int i = 0;
while(itr.hasNext())
{
MIDIMessage msg = (MIDIMessage)itr.next();
ShortMessage noteOnMsg = new ShortMessage();
//Signal/Channel/Pitch/Velocity
noteOnMsg.setMessage(ShortMessage.NOTE_ON, 0,msg.GetPitch(),msg.GetVelocity());
ShortMessage noteOffMsg = new ShortMessage();
//Signal/Channel/Pitch/Velocity
noteOffMsg.setMessage(ShortMessage.NOTE_OFF,0,msg.GetPitch(),msg.GetVelocity());
track.add(new MidiEvent(noteOnMsg,msg.GetDelay()));
track.add(new MidiEvent(noteOffMsg,msg.GetDelay() + i));
i++;
}
sequencer.setSequence(sequence);
sequencer.setTempoInBPM(120);
sequencer.setLoopCount(1);
seq.start();
}
catch(Exception e)
{
}
}
如您所见,我遍历ArrayList并将每个noteOn / Off添加到轨道。
播放曲目后,我注意到它只播放两个音符,无论列表中的数量是多少。
我已经检查了临时收藏和曲目收藏,他们似乎都有正确的数据。
我是以错误的方式添加事件和消息吗?我只希望能够以记录的方式播放音符,并且每张音符之间应该有合理的时间。
答案 0 :(得分:2)
您似乎将消息中的注释添加到频道0,并将消息添加到频道1.我猜这不是您想要做的 - 将它们设置为第一个频道(即, 0
)。
答案 1 :(得分:1)
我设法修复了我遇到的问题,在查看我实现添加到轨道的消息的方式后,我发现每条消息的添加距离太近,因此当每个音符播放下一个音符时几乎立刻就玩了。
以下代码显示了我如何修复它:
int i = 0;
while(itr.hasNext())
{
MIDIMessage msg = (MIDIMessage)itr.next();
ShortMessage noteOnMsg = new ShortMessage();
//Signal/Channel/Pitch/Velocity
noteOnMsg.setMessage(ShortMessage.NOTE_ON, 0,msg.GetPitch(),msg.GetVelocity());
ShortMessage noteOffMsg = new ShortMessage();
//Signal/Channel/Pitch/Velocity
noteOffMsg.setMessage(ShortMessage.NOTE_OFF,0,msg.GetPitch(),msg.GetVelocity());
track.add(new MidiEvent(noteOnMsg,i));
i = i+50;
track.add(new MidiEvent(noteOffMsg,i));
i = i+50;
}
通过将 i 的数量增加到 50 ,可确保所有音符都具有相当大的空间将它们分开在轨道中,因此音符正确播放。
答案 2 :(得分:1)
我知道这是几个月前被问到的,但我正在尝试做一些非常相似的事情。
我遇到了同样的问题,发现sequencer.setLoopCount(1);
导致我的音序器播放音符两次。
通过删除它,它只播放了一次音符。希望这会有所帮助。