簡體   English   中英

在 Java 中讀取 MIDI 消息:缺少音符關閉事件?

[英]Reading MIDI messages in Java: missing note-off event?

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文件只是不好?

MIDI 規范說:

MIDI 提供了兩種大致等效的關閉音符(聲音)的方法。 可以通過為相同的音符編號和通道發送 Note-Off 消息來關閉音符,或者通過為該音符和通道發送一個力度值為 0 的 Note-On 消息來關閉音符。 使用“Note-On at zero velocity”的優點是它可以避免在使用運行狀態時發送額外的狀態字節。

由於這種效率,發送速度值為 0 的 Note-On 消息是最常用的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM