Java MIDI Track воспроизводит дубликаты нот - PullRequest
3 голосов
/ 13 января 2011

Я создаю приложение, в котором пользователь может добавить несколько MIDI-нот в коллекцию, отсюда они могут нажать кнопку «Воспроизведение», и приложение будет перебирать каждую ноту и воспроизводить их через динамики.

Я создал класс MIDIMessage, в котором содержатся сведения о заметке, которую пользователь решил добавить в список, причем сохраняются следующие данные: Pitch, Velocity, Delay и Channel.

Каждое из этих сообщений сохраняется вArrayList с типом MIDIMessage.

Затем я продолжаю привязывать итератор коллекции к объекту итератора и воспроизводить звук, пока в коллекции все еще есть элемент, который не использовался.

По какой-то причине, даже если я добавляю только одну ноту в коллекцию, всегда есть две ноты, играющие с одинаковой высотой, длиной и скоростью.

Кроме того, каждая нота играет одновременно, независимо от того,сколько из них присутствует в коллекции, я предположил, что между ними будет какая-то задержка.

Ниже приведен код, который я использую в данный момент:

MIDIMessage:

package javatest;

public class MIDIMessage
{
    private int pitch;
    private int velocity;
    private int channel;

    public MIDIMessage(int p, int v, int c)
    {
        pitch = p;
        velocity = v;
        channel = c;
    }

    public int GetPitch()
    {
        return this.pitch;
    }

    public int GetVelocity()
    {
        return this.velocity;
    }

    public int GetChannel()
    {
        return this.channel;
    }
}

Добавление заметки в коллекцию:

public void AddToList()
    {
        int channel = jComboBoxChannels.getSelectedIndex();
        int pitch = jComboBoxPitch.getSelectedIndex();
        int velocity = ((Integer)jSpinnerVelocity.getValue());    
        collection.add(new MIDIMessage(pitch,velocity,channel));
    }

Воспроизведение нот:

try
        {
            jButton1.setEnabled(false);
            Sequencer sequencer = MidiSystem.getSequencer();
            sequencer.open();
            Sequence sequence = new Sequence(Sequence.PPQ,1);
            Track track = sequence.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, msg.GetChannel(),msg.GetPitch(),msg.GetVelocity());

                ShortMessage noteOffMsg = new ShortMessage();
                //Signal/Channel/Pitch/Velocity
                noteOffMsg.setMessage(ShortMessage.NOTE_OFF,msg.GetChannel(),msg.GetPitch(),msg.GetVelocity());

                track.add(new MidiEvent(noteOnMsg,0));
                track.add(new MidiEvent(noteOffMsg,1));
                //i = i+1;
            }

            sequencer.setSequence(sequence);
            sequencer.setTempoInBPM(120);
            sequencer.setLoopCount(1);

            sequencer.start();

            Thread.sleep(1000);
        }

1 Ответ

1 голос
/ 13 января 2011

Я не уверен, почему ноты играются дважды, но это определенно неправильно:

            track.add(new MidiEvent(noteOnMsg,0));
            track.add(new MidiEvent(noteOffMsg,1));

Как вы можете видеть здесь , MidiEvent состоит из сообщения и MIDI-галочки. Вы всегда добавляете noteOnMsg на тик 0 и noteOffMsg на тик 1, что объясняет, почему для нескольких нот все они воспроизводятся одновременно. Вы хотите сделать что-то вроде этого:

startTick = 0;

while(itr.hasNext()) {
   [...]
   track.add(new MidiEvent(noteOnMsg,startTick));
   track.add(new MidiEvent(noteOffMsg,startTick + how_long_the_note_is_played));
   startTick += difference_between_this_note_and_the_next;
   [...]
}

Я не уверен, что означает ваш delay и можете ли вы использовать его здесь, поэтому вместо этого я использую описательные имена переменных.

Обратите внимание, что здесь вам придется использовать MIDI-тики - если вы хотите преобразовать секунды в MIDI-тиках, см. этот SO вопрос (точнее, его ответ):

[Как долго длится один тик MIDI?]

Формула 60000 / (BPM * PPQ) (миллисекунды).

...