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

发布于 2024-10-05 01:32:13 字数 1797 浏览 1 评论 0原文

根据我的问题此处我创建了一个列表允许我对需要播放的一组音符进行排队,然后将它们按顺序添加到曲目中,以便可以一次性播放。

我将要在轨道中播放的音符添加到临时列表中,如下所示:

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 并将每个音符添加到轨道。

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

我检查了临时集合和轨道集合,它们似乎都包含正确的数据。

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

Following on from my question here I have created a List that allows me to queue up a collection of notes that need to be played, these are then added to the track in order so they can be played in one go.

I add the notes to be played in the track to the temporary list like so:

int pitch = jComboBoxPitch.getSelectedIndex();
int velocity = ((Integer)jSpinnerVelocity.getValue());

collection.add(new MIDIMessage(pitch,velocity));

When the user has added all the notes necessary they press the "Play" button:

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)
        {

        }
    }

As you can see I iterate through the ArrayList and add each noteOn/Off to the track.

After playing the track I've noticed that it only plays two notes regardless of the amount that are in the list.

I've checked both the temporary collection and the track collection and they both seem to have the correct data in them.

Am I adding the events and messages in the wrong way? I just wish to be able to play the notes in the way they are recorded and that they should have a reasonable amount of time inbetween each note.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

可是我不能没有你 2024-10-12 01:32:13

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

You seem to be adding your note on message to channel 0 and the note off message to channel 1. I'm guessing that's not really what you want to do -- set them both to be on the first channel (ie, 0).

思念满溢 2024-10-12 01:32:13

我设法解决了我遇到的问题,在查看了将消息添加到轨道中的实现方式后,我发现每条消息添加得太接近,因此当每个音符播放时,下一个音符几乎立即播放。

以下代码显示了我是如何修复它的:

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,它可以确保所有笔记在音轨中有足够的空间来分隔它们,因此音符可以正确播放。

I managed to fix the problem I was having, after looking at the way I was implementing my messages being added to the track I saw that each message was added too close to each other, therefore when each note played the next note was played almost instantly.

The following code shows how I fixed it:

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;
            }

By increasing the count of i to 50 it ensures all the notes have a decent amount of space to seperate them in the track, hence the notes being played correctly.

一场春暖 2024-10-12 01:32:13

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

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

I know this was asked a few months ago, but I'm trying to do something very similar.
I came across the same problem and found that sequencer.setLoopCount(1); was causing my Sequencer to play the notes twice.

By removing this it played the notes only once. Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文