2011-01-13 13 views
3

我创建一个应用程序,用户可以添加多个MIDI音符的集合,从这里他们可以按“播放”按钮,该应用程序将通过每一个音符迭代,并通过扬声器播放这些。Java的MIDI播放曲目重复指出

我已经创建了一个保存用户已选择添加到列表中的说明细节的MidiMessage类,存储时音准,速度,延迟和通道的细节。

将这些消息中的每一个都保存到类型为MIDIMessage的ArrayList中。

我接下来要集合的迭代器attatch一个迭代器对象和播放声音,同时还有尚未使用的集合中的元素。

因为即使我只有一个音符添加到集合中始终有两个具有完全相同的间距,长度和速度玩一些原因。

而且每一个音符的同时起到无论多少都存在集合中,我以为会有某种延迟在他们之间。

以下是我使用的那一刻代码:

的MidiMessage:

package javatest; 

public class MIDIMessage 
{ 
    private int pitch; 
    private int velocity; 
    private int channel; 

    public MIDIMessage(int p, int v, int c) 
    { 
     pitch = p; 
     velocity = v; 
     channel = c; 
    } 

    public int GetPitch() 
    { 
     return this.pitch; 
    } 

    public int GetVelocity() 
    { 
     return this.velocity; 
    } 

    public int GetChannel() 
    { 
     return this.channel; 
    } 
} 

添加备注到集合:

public void AddToList() 
    { 
     int channel = jComboBoxChannels.getSelectedIndex(); 
     int pitch = jComboBoxPitch.getSelectedIndex(); 
     int velocity = ((Integer)jSpinnerVelocity.getValue());  
     collection.add(new MIDIMessage(pitch,velocity,channel)); 
    } 

演奏的音符:

try 
     { 
      jButton1.setEnabled(false); 
      Sequencer sequencer = MidiSystem.getSequencer(); 
      sequencer.open(); 
      Sequence sequence = new Sequence(Sequence.PPQ,1); 
      Track track = sequence.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, msg.GetChannel(),msg.GetPitch(),msg.GetVelocity()); 

       ShortMessage noteOffMsg = new ShortMessage(); 
       //Signal/Channel/Pitch/Velocity 
       noteOffMsg.setMessage(ShortMessage.NOTE_OFF,msg.GetChannel(),msg.GetPitch(),msg.GetVelocity()); 

       track.add(new MidiEvent(noteOnMsg,0)); 
       track.add(new MidiEvent(noteOffMsg,1)); 
       //i = i+1; 
      } 

      sequencer.setSequence(sequence); 
      sequencer.setTempoInBPM(120); 
      sequencer.setLoopCount(1); 

      sequencer.start(); 

      Thread.sleep(1000); 
     } 

回答

1

我不知道为什么音符则为两次,但是这绝对是错误的:

  track.add(new MidiEvent(noteOnMsg,0)); 
      track.add(new MidiEvent(noteOffMsg,1)); 

正如你可以看到here,一个MidiEvent由消息和MIDI节拍的。您总是在tick 1上添加noteOnMsg,在tick 1上添加noteOffMsg,这解释了为什么多个音符同时播放。你想要做这样的事情,而不是:

startTick = 0; 

while(itr.hasNext()) { 
    [...] 
    track.add(new MidiEvent(noteOnMsg,startTick)); 
    track.add(new MidiEvent(noteOffMsg,startTick + how_long_the_note_is_played)); 
    startTick += difference_between_this_note_and_the_next; 
    [...] 
} 

我不知道你的delay手段,如果你能在这里使用它,所以我用描述性的变量名来代替。

请注意,您必须使用MIDI蜱在这里 - 如果你要转换秒MIDI蜱,看到this SO question(或者更确切地说,它的答案):[?多久是一个MIDI节拍]

的公式为60000/(BPM * PPQ) (毫秒)。

+0

对不起,我不明白,我怎么知道音符已播放了多长时间,以及当前音符和下一个音符之间的差异?此外,延迟是一个错误,我是来自旧源文件的C/P代码。 – 2011-01-13 14:41:03