Java MIDI Track播放重复音符

时间:2011-01-13 14:03:48

标签: java midi

我正在创建一个应用程序,用户可以在其中添加多个MIDI音符到一个集合,从这里他们可以按“播放”按钮,应用程序将遍历每个音符并通过扬声器播放。

我创建了一个MIDIMessage类,其中包含用户选择添加到列表中的注释的详细信息,存储的详细信息为Pitch,Velocity,Delay和Channel。

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

然后我继续将集合的迭代器附加到迭代器对象并播放声音,同时集合中仍有一个元素尚未使用。

出于某种原因,即使我只在集合中添加一个音符,总会有两个音符以完全相同的音高,长度和速度播放。

同样,每个音符同时播放,无论集合中有多少音符,我都认为它们之间会有某种延迟。

以下是我目前使用的代码:

的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 个答案:

答案 0 :(得分:1)

我不确定为什么音符会播放两次,但这绝对是错误的:

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

正如您所见hereMidiEvent由消息和MIDI标记组成。您总是在刻度线0上添加noteOnMsg,在刻度线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)   (毫秒)。