Подтвердить что ты не робот

Чтение MIDI файлов в Java

Я пытаюсь прочитать файлы .MID в программе Java и хотел бы разделить каждую ноту/аккорд, чтобы отобразить их в пользовательском интерфейсе какого-либо типа. Мне не очень повезло с использованием интерфейса Sequencer API на Java, и попытка использовать MidiFileReader напрямую тоже не работала для меня. Я приложу код, который я использовал здесь, если кто-то захочет его увидеть:

package miditest;
import java.io.File;
import java.io.IOException;
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;

public class Main {
    public static void main(String[] args) throws InvalidMidiDataException, IOException, MidiUnavailableException{
    Sequence sequence = MidiSystem.getSequence(new File("test.mid"));

    // Create a sequencer for the sequence
    Sequencer sequencer = MidiSystem.getSequencer();
    sequencer.open();
    sequencer.setSequence(sequence);

    // Start playing
    sequencer.start();
    }
}
4b9b3361

Ответ 1

Я никогда не заглядывал в поддержку MIDI в Java, и в последний раз, когда я играл серьезно с MIDI-программированием, это было когда Commodore Amiga был королем.

Похоже, вам, возможно, придется немного поработать вручную. Вот грубый пример, который интерпретирует все события NOTE_ON и NOTE_OFF, для остальных событий он просто печатает номер команды.

Причина, по которой это может показаться сложнее, чем можно было подумать, это потому, что MIDI фокусируется на захвате инструментальных событий (например, когда нажата клавиша клавиатуры, когда она была выпущена и т.д.), а не нотной нотации.

Этот код выводит одну строку на событие, указывая с тиком (который является информацией о времени для события), каналом, типом события, именем заметки, клавишей, скоростью

import java.io.File;

import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;

public class Test {
    public static final int NOTE_ON = 0x90;
    public static final int NOTE_OFF = 0x80;
    public static final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};

    public static void main(String[] args) throws Exception {
        Sequence sequence = MidiSystem.getSequence(new File("test.mid"));

        int trackNumber = 0;
        for (Track track :  sequence.getTracks()) {
            trackNumber++;
            System.out.println("Track " + trackNumber + ": size = " + track.size());
            System.out.println();
            for (int i=0; i < track.size(); i++) { 
                MidiEvent event = track.get(i);
                System.out.print("@" + event.getTick() + " ");
                MidiMessage message = event.getMessage();
                if (message instanceof ShortMessage) {
                    ShortMessage sm = (ShortMessage) message;
                    System.out.print("Channel: " + sm.getChannel() + " ");
                    if (sm.getCommand() == NOTE_ON) {
                        int key = sm.getData1();
                        int octave = (key / 12)-1;
                        int note = key % 12;
                        String noteName = NOTE_NAMES[note];
                        int velocity = sm.getData2();
                        System.out.println("Note on, " + noteName + octave + " key=" + key + " velocity: " + velocity);
                    } else if (sm.getCommand() == NOTE_OFF) {
                        int key = sm.getData1();
                        int octave = (key / 12)-1;
                        int note = key % 12;
                        String noteName = NOTE_NAMES[note];
                        int velocity = sm.getData2();
                        System.out.println("Note off, " + noteName + octave + " key=" + key + " velocity: " + velocity);
                    } else {
                        System.out.println("Command:" + sm.getCommand());
                    }
                } else {
                    System.out.println("Other message: " + message.getClass());
                }
            }

            System.out.println();
        }

    }
}

Например, мех elise.mid, который я лежал здесь, производит что-то вроде этого в начале:

@0 Channel: 1 Note on, E5 key=76 velocity: 127
@192 Channel: 1 Note off, E5 key=76 velocity: 64
@192 Channel: 1 Note on, D#5 key=75 velocity: 127
@384 Channel: 1 Note off, D#5 key=75 velocity: 64
@384 Channel: 1 Note on, E5 key=76 velocity: 127
@576 Channel: 1 Note off, E5 key=76 velocity: 64
@576 Channel: 1 Note on, D#5 key=75 velocity: 127
@768 Channel: 1 Note off, D#5 key=75 velocity: 64
@768 Channel: 1 Note on, E5 key=76 velocity: 127
@960 Channel: 1 Note off, E5 key=76 velocity: 64
@960 Channel: 1 Note on, B4 key=71 velocity: 127
@1152 Channel: 1 Note off, B4 key=71 velocity: 64
@1152 Channel: 1 Note on, D5 key=74 velocity: 127
@1344 Channel: 1 Note off, D5 key=74 velocity: 64
@1344 Channel: 1 Note on, C5 key=72 velocity: 127
@1536 Channel: 1 Note off, C5 key=72 velocity: 64
@1536 Channel: 1 Note on, A4 key=69 velocity: 127
@1920 Channel: 1 Note off, A4 key=69 velocity: 64

UPDATE: Каналы представляют собой 16 каналов спецификации MIDI.

http://www.midi.org/techspecs/gm.php

Каналы: все 16 MIDI-каналов поддерживается. Каждый канал может воспроизводить переменное количество голосов (полифония). Каждый канал может воспроизводить инструмент (звук/патч/тембр). Перкуссия на основе клавиш всегда на MIDI Канал 10.

И скорость - один из атрибутов, используемых для управления звуками. Например, захват MIDI-данных на клавиатуре будет силой, с которой вы нажимаете клавишу. Обычно он контролирует громкость звука. См. Здесь для более подробной информации: http://audio.tutsplus.com/tutorials/production/7-ways-to-use-and-edit-midi-velocity/