Remove MidiEvent from Track fails - MIDI / Java

拈花ヽ惹草 提交于 2020-01-15 14:18:09

问题


A user has the ability to generate a set of MIDI events which are in turn added to an ArrayList and then iterated through and added to a Track object, waiting to be played. I'm trying to remove all of the events that are in a track, I do this by iterating through all of the MIDI Events in a collection and use the "CreateNoteOnEvent"/"CreateNoteOffEvent" in the .remove() method.

For some reason the method always returns as false, as in it can't find the event to delete or that it has failed to delete it.

Am I going about it the right way? I just assumed I delete the events in the same way that I add them.

Thanks!

Remove:

Iterator itr = collection.iterator();

        try
        {
            if(sequencer.isRunning())
            {
                Stop();
            }
            while (itr.hasNext())
            {
                MIDIMessageContainer msg = (MIDIMessageContainer) itr.next();

                if(!track.remove(CreateNoteOnEvent(msg.GetChannel(), msg.GetKey(), msg.GetTick(), msg.GetVelocity())))
                {
                    Logger.Add("MIDI Event not removed");
                    return false;
                }
                if(!track.remove(CreateNoteOffEvent(msg.GetChannel(), msg.GetKey(), msg.GetTick(), msg.GetVelocity())))
                {
                    Logger.Add("MIDI Event not removed");
                    return false;
                }
            }

            collection.clear();
            return true;
        }

CreateNoteOnEvent:

private static MidiEvent CreateNoteOnEvent(int channel, int pitch, long tick, int velocity)
    {
        ShortMessage noteOnMessage = new ShortMessage();

        try
        {
            noteOnMessage.setMessage(ShortMessage.NOTE_ON, channel, pitch, velocity);
        }
        catch (Exception e)
        {
            Logger.Add(e.getMessage());
        }

        MidiEvent event = new MidiEvent(noteOnMessage, tick);
        return event;
    }

CreateNoteOffEvent:

 private static MidiEvent CreateNoteOffEvent(int channel, int pitch, long tick, int velocity)
    {
        ShortMessage noteOffMessage = new ShortMessage();

        try
        {
            noteOffMessage.setMessage(ShortMessage.NOTE_OFF, channel, pitch, velocity);
        }
        catch (Exception e)
        {
            Logger.Add(e.getMessage());
        }

        MidiEvent event = new MidiEvent(noteOffMessage, tick + 1);
        return event;
    }

回答1:


After digging around the documentation I found that you can infact return a MidiEvent in the track if you specify the index, my first implementation of a solution went like this:

for(int i = 0; i < track.size(); i++)
{
       if(!track.remove(track.get(i)))
       {
              Logger.Add("MIDI Event not removed");
       }
}

The problem with this code is the loop is checking it's condition on the length of the Track, this will change as events are removed so it will eventually fail the condition and break out of the loop in turn leaving several events in the track still.

This is the working solution:

_sequence.deleteTrack(_track);
_track = _sequence.createTrack();

Simple but very effective, instead of iterating through a loop that could go on for a fair while I read through the documentation and decided upon this method instead. Although I have not profiled it's performance I have a feeling that this is a better solution than looping, especially when the number of iterations can be fairly high.

I hope it helps someone, I spent hours scratching my head over this.

Thanks for the additional feedback!



来源:https://stackoverflow.com/questions/5418773/remove-midievent-from-track-fails-midi-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!