Java MIDI Track中的音符之间的延迟播放不正确

时间:2010-11-28 20:50:23

标签: java midi

继我的问题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添加到轨道。

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

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

我是以错误的方式添加事件和消息吗?我只希望能够以记录的方式播放音符,并且每张音符之间应该有合理的时间。

3 个答案:

答案 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);导致我的音序器播放音符两次。

通过删除它,它只播放了一次音符。希望这会有所帮助。