Чтение MIDI-сообщений в Java: отсутствует заметка? - PullRequest
2 голосов
/ 21 февраля 2020
private static List<Note> midiEventsToNotes(List<MidiEvent> midiEvents) {
        List<Note> output = new ArrayList<>();
        Predicate<MidiEvent> noteEvent = me -> me.getMessage().getStatus() >> REST_OF_STATUS_BYTE == NOTE_ON
                || me.getMessage().getStatus() >> REST_OF_STATUS_BYTE == NOTE_OFF;
        List<MidiEvent> noteEvents = midiEvents.stream().filter(noteEvent).collect(Collectors.toList());
        for (int i = 0; i < noteEvents.size(); i++) {
            int eventType = noteEvents.get(i).getMessage().getStatus() >> REST_OF_STATUS_BYTE;
            if (eventType == NOTE_ON) {
                byte pitch = noteEvents.get(i).getMessage().getMessage()[1];
                int startBeat = (int) (noteEvents.get(i).getTick() / ticksPerBeat);
                for (MidiEvent ne: noteEvents) {
                    int pairType =  ne.getMessage().getStatus() >> REST_OF_STATUS_BYTE;
                    byte pitch2 = ne.getMessage().getMessage()[1];
                    if (pairType == NOTE_OFF && pitch == pitch2) {
                        int value = (int) (ne.getTick() / ticksPerBeat - startBeat);
                        int pianoKey = pitch - MIDI_A0_VALUE;
                        output.add(new Note(startBeat, value, pianoKey));
                        break;
                    }
                }
            }
        }
        return output;
    }

Я пытаюсь прочитать MIDI-файл (преобразовать данные в файле в данные, которые обрабатываются моделью моего приложения). Вот метод, о котором идет речь. Требуется список MidiEvent, который должен быть просто списком всех MidiEvent в последовательности файла. Метод должен вывести список Note, причем Note является классом в модели. Сначала метод отфильтровывает список только для событий заметок и заметок. Затем для каждого события, если событие является примечанием, оно пытается связать его с соответствующим примечанием и создать экземпляр примечания.

Я тестировал его с файлами midi, содержащими только одну примечание. , Как и ожидалось, отладчик сообщает мне, что в отфильтрованном списке есть два элемента noteEvents, но они как-то оба являются событиями заметок (они имеют одинаковый байт состояния), и, очевидно, метод не работает из-за этого. Что-то не так с методом, или Java конвертирует файл в события, или MIDI-файлы просто плохи?

1 Ответ

3 голосов
/ 21 февраля 2020

Спецификация MIDI гласит:

MIDI предоставляет два примерно эквивалентных средства отключения ноты (голоса). Заметка может быть отключена либо путем отправки сообщения об отключении для того же номера и канала, либо путем отправки сообщения о включении для этой заметки и канала со значением скорости, равным нулю. Преимущество использования «Note-On с нулевой скоростью» состоит в том, что он может избежать отправки дополнительных байтов состояния, когда используется состояние выполнения.

Благодаря этой эффективности отправка сообщений Note-On со значениями скорости, равными нулю, является Наиболее часто используемый метод.

...