Задержка воспроизведения нот в MIDI-треке Java некорректно

Исходя из этого вопроса, я создал список, который позволяет мне ставить в очередь коллекцию нот, которые необходимо воспроизвести, затем они добавляются в дорожку, чтобы их можно было воспроизвести за один раз.

Я добавляю ноты для воспроизведения на дорожке во временный список следующим образом:

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 и добавляю каждую заметку On/Off к дорожке.

После воспроизведения трека я заметил, что он воспроизводит только две ноты независимо от количества в списке.

Я проверил как временную коллекцию, так и коллекцию треков, и они, похоже, содержат правильные данные.

Я неправильно добавляю события и сообщения? Я просто хотел бы иметь возможность воспроизводить ноты так, как они записаны, и чтобы у них было достаточное количество времени между каждой нотой.

3 ответа

Решение

Мне удалось устранить проблему, которая возникла у меня, после того, как я посмотрел на то, как я реализовывал добавление своих сообщений на дорожку, я увидел, что каждое сообщение было добавлено слишком близко друг к другу, поэтому, когда каждая нота воспроизводилась, следующая нота воспроизводилась практически мгновенно.,

Следующий код показывает, как я это исправил:

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, он гарантирует, что все ноты имеют достаточно места для разделения их в дорожке, следовательно, ноты воспроизводятся правильно.

Похоже, вы добавляете заметку в сообщении на канал 0, а сообщение с отключенной записью на канал 1. Я предполагаю, что это не совсем то, что вы хотите сделать - установите их обоих на первый канал (т. Е. 0).

Я знаю, что об этом спросили несколько месяцев назад, но я пытаюсь сделать что-то очень похожее. Я столкнулся с той же проблемой и обнаружил, что sequencer.setLoopCount(1); заставлял мой секвенсор дважды играть ноты.

Убрав это, он проиграл ноты только один раз. Надеюсь это поможет.

Другие вопросы по тегам