Задержка воспроизведения нот в 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);
заставлял мой секвенсор дважды играть ноты.
Убрав это, он проиграл ноты только один раз. Надеюсь это поможет.