Delay between notes in Java MIDI Track playing incorrectly
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.G开发者_如何学PythonetPitch(),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.
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
).
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.
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.
精彩评论