2010-10-03 3 views
27

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

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(); 
    } 
} 
+0

Вы искали MIDI на SO? Об этом много вопросов и ответов. Пример: http://stackoverflow.com/questions/1182877/reading-midi-files первый ответ – extraneon

ответ

44

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

Похоже, вам, возможно, придется выполнить небольшую ручную работу. Вот грубый пример, который интерпретирует все события 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/

+0

У меня был другой вопрос: тик - это время, в которое звучит звук, но что представляет собой канал? А скорость? –

+0

См. Обновления моего первоначального ответа. –

+0

Большое спасибо за вашу помощь. –