2010-11-28 76 views
1

继我的问题here我创建了一个列表,允许我排列需要播放的音符集合,然后将这些音符添加到音轨中,以便它们可以一气呵成地演奏。Java MIDI Track中的音符之间的延迟播放不正确

我想补充说明,以在轨道上播放的临时列表,像这样:

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添加到轨道。

播放曲目后,我注意到它只播放两个音符,无论列表中的数量如何。

我已经检查了临时收藏和曲目集合,他们都似乎有正确的数据。

我是否以错误的方式添加事件和消息?我只是希望能够以他们记录的方式演奏音符,并且他们应该在每个音符之间有合理的时间。

回答

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它确保所有的笔记有空间体面的数额,以它们分开在曲目中,因此音符被正确播放。

2

您似乎在将消息添加到通道0的消息中,并将注释消息添加到通道1中。我猜这不是你想要做的 - 将它们都设置在第一个通道上(即,0)。

+0

即使改变后也会发生同样的事情,我不明白为什么它会弹奏两个音符,即使我只添加一个音符。 – 2010-11-29 15:15:07

1

我知道这是几个月前问的,但我正在尝试做一些非常相似的事情。 我遇到了同样的问题,发现sequencer.setLoopCount(1);导致我的音序器播放音符两次。

通过删除它,它只播放一次笔记。希望这可以帮助。