java audio midi

Lectura de archivos MIDI en Java



audio (1)

Intento leer archivos .MID en un programa Java y me gustaría separar cada nota / acorde para mostrarlos en una IU de algún tipo. No tuve mucha suerte con el uso de la API Sequencer en Java, y tampoco intenté usar MidiFileReader directamente. Adjuntaré el código que usé aquí, si alguien quiere verlo:

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


Nunca he profundizado en el soporte MIDI en Java, y la última vez que jugué seriamente con la programación MIDI fue cuando Commodore Amiga fue el rey.

Parece que debe hacer bastante trabajo manual. Aquí hay un ejemplo crudo que interpreta todos los eventos NOTE_ON y NOTE_OFF, para el resto de los eventos solo imprime el número de comando.

La razón por la que podría parecer más complicado de lo que uno podría haber pensado al principio es porque MIDI se enfoca en capturar los eventos del instrumento (por ejemplo, cuando se presionó una tecla del teclado, cuando se lanzó, etc.) y no en notación de partituras.

Este código imprime una línea por evento, indicando con la marca (que es la información de tiempo para el evento), canal, tipo de evento, nombre de la nota, clave, velocidad

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

Por ejemplo, el peluche elise.mid que tenía por aquí produce algo como esto al principio:

@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

ACTUALIZACIÓN: Los canales son los 16 canales de la especificación MIDI.

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

Canales: los 16 canales MIDI son compatibles. Cada canal puede reproducir un número variable de voces (polifonía). Cada canal puede tocar un instrumento diferente (sonido / parche / timbre). La percusión basada en la clave siempre está en el Canal 10 MIDI.

Y la velocidad es uno de los atributos utilizados para controlar los sonidos. Por ejemplo, capturar datos MIDI en un teclado sería la fuerza con la que presionas una tecla. Normalmente controla el volumen del sonido. Consulte aquí para obtener más detalles: http://audio.tutsplus.com/tutorials/production/7-ways-to-use-and-edit-midi-velocity/