Java | Introducción MIDI

El estándar de interfaz digital de instrumentos musicales (MIDI) define un protocolo de comunicación para dispositivos de música electrónica, como instrumentos de teclado electrónico y computadoras personales. Los datos MIDI se pueden transmitir a través de cables especiales durante una actuación en vivo y también se pueden almacenar en un tipo de archivo estándar para su posterior reproducción o edición.
Un archivo midi contiene datos que representan la música en términos de eventos. Cada evento proporciona una descripción de la nota musical que se reproducirá: duración, tono, velocidad, canal, etc. El paquete javax.sound.midi proporciona interfaces y clases para E/S, secuenciación y síntesis de datos MIDI.
MIDI es tanto una especificación de hardware como una especificación de software. 
El javax.sonido.midiEl paquete se usa para crear y usar eventos midi para producir una banda sonora simple en Java. 
 

Representación de dispositivo MIDI de Java Sound API

  • Interfaz MidiDevice: La interfaz MidiDevice incluye una API para abrir y cerrar un dispositivo. También incluye una clase interna llamada MidiDevice.Info que proporciona descripciones textuales del dispositivo, incluido su nombre, proveedor y versión.
  • Transmisores y receptores: la forma en que un dispositivo envía datos es a través de uno o más objetos transmisores que «posee». De manera similar, la forma en que un dispositivo recibe datos es a través de uno o más de sus objetos receptores. Los objetos transmisores implementan la interfaz Transmisor y los receptores implementan la interfaz Receptor.
    Cada transmisor se puede conectar a un solo receptor a la vez, y viceversa

Componentes esenciales de un sistema Midi

  • Sintetizador: Este es el dispositivo que reproduce la banda sonora midi. Puede ser un sintetizador de software o un instrumento real compatible con midi.
  • Secuenciador: un secuenciador toma datos Midi (a través de una secuencia) y ordena diferentes instrumentos para tocar las notas. Organiza los eventos según la hora de inicio, la duración y el canal en el que se reproducirá.
  • Canal: Midi admite hasta 16 canales diferentes. Podemos enviar un evento midi a cualquiera de esos canales que luego son sincronizados por el secuenciador.
  • Pista: Es una secuencia de eventos Midi.
  • Secuencia: es una estructura de datos que contiene múltiples pistas e información de tiempo. El secuenciador toma una secuencia y la reproduce.

Clases y métodos importantes

  • MidiSystem : esta clase proporciona acceso a recursos MIDI instalados como secuenciadores, sintetizadores, puertos de E/S. Todos los métodos son estáticos y esta clase no se puede instanciar.
  • MidiSystem.getSequencer() : devuelve una instancia de la interfaz del secuenciador que está conectada a un sintetizador/receptor.
  • secuenciar.open() : abre el secuenciador para que pueda adquirir recursos del sistema.
  • secuenciador.setSequence(secuencia de secuencia) – Establece la secuencia actual en la que opera el secuenciador.
  • secuenciar.setTempoInBPM(float bpm) – Establece el tempo de reproducción en pulsaciones por minuto.
  • secuenciar.start() : inicia la reproducción de los datos MIDI en la secuencia cargada actualmente.
  • secuenciar.isRunning() : indica si el secuenciador se está ejecutando actualmente.
  • Secuencia : la instancia de la clase Secuencia contiene una estructura de datos que representa una o más pistas e información de tiempo.
  • Sequence.PPQ : tipo de temporización basado en tempo, para el cual la resolución se expresa en pulsos (ticks) por negra.
  • Sequence.createTrack() – Crea una pista vacía
  • Pista : clase que contiene eventos midi ordenados cronológicamente.
  • Track.add (evento MidiEvent) : agrega un nuevo evento a la pista.
  • MidiEvent (mensaje MidiMessage, marca larga) : un objeto de evento midi que contiene un mensaje midi con marca de tiempo.
  • ShortMessage() : un objeto ShortMessage con dos bytes de datos como máximo (extendido de MidiMessage).
  • ShortMessage.setMessage(int command, int channel, int data1, int data2) : establece un objeto ShortMessage que tiene como máximo dos bytes de datos (data1 y data2).

Comandos MIDI

Código Dominio
144 Nota sobre el evento
128 Evento de nota desactivada
192 Cambio de programa para cambiar el instrumento predeterminado, etc.
176 Cambio de control para el envío de eventos
224 Inflexión de tono

Los siguientes programas ilustran el uso de MIDI en Java: 
Programa 1: Ilustra la implementación de un registro simple.
 

Java

// Java program showing the implementation of a simple record
import javax.sound.midi.*;
import java.util.*;
 
public class MyMidiPlayer {
 
    public static void main(String[] args)
    {
 
        System.out.println("Enter the number of notes to be played: ");
        Scanner in = new Scanner(System.in);
        int numOfNotes = in.nextInt();
 
        MyMidiPlayer player = new MyMidiPlayer();
        player.setUpPlayer(numOfNotes);
    }
 
    public void setUpPlayer(int numOfNotes)
    {
 
        try {
 
            // A static method of MidiSystem that returns
            // a sequencer instance.
            Sequencer sequencer = MidiSystem.getSequencer();
            sequencer.open();
 
            // Creating a sequence.
            Sequence sequence = new Sequence(Sequence.PPQ, 4);
 
            // PPQ(Pulse per ticks) is used to specify timing
            // type and 4 is the timing resolution.
 
            // Creating a track on our sequence upon which
            // MIDI events would be placed
            Track track = sequence.createTrack();
            .
 
                // Adding some events to the track
                for (int i = 5; i < (4 * numOfNotes) + 5; i += 4)
            {
 
                // Add Note On event
                track.add(makeEvent(144, 1, i, 100, i));
 
                // Add Note Off event
                track.add(makeEvent(128, 1, i, 100, i + 2));
            }
 
            // Setting our sequence so that the sequencer can
            // run it on synthesizer
            sequencer.setSequence(sequence);
 
            // Specifies the beat rate in beats per minute.
            sequencer.setTempoInBPM(220);
 
            // Sequencer starts to play notes
            sequencer.start();
 
            while (true) {
 
                // Exit the program when sequencer has stopped playing.
                if (!sequencer.isRunning()) {
                    sequencer.close();
                    System.exit(1);
                }
            }
        }
        catch (Exception ex) {
 
            ex.printStackTrace();
        }
    }
 
    public MidiEvent makeEvent(int command, int channel,
                               int note, int velocity, int tick)
    {
 
        MidiEvent event = null;
 
        try {
 
            // ShortMessage stores a note as command type, channel,
            // instrument it has to be played on and its speed.
            ShortMessage a = new ShortMessage();
            a.setMessage(command, channel, note, velocity);
 
            // A midi event is comprised of a short message(representing
            // a note) and the tick at which that note has to be played
            event = new MidiEvent(a, tick);
        }
        catch (Exception ex) {
 
            ex.printStackTrace();
        }
        return event;
    }
}
Input: Enter the number of notes to be played: 
       15 
Output: 15 sound notes with increasing pitch are played

Input: Enter the number of notes to be played: 
       25
Output: 25 sound notes with increasing pitch are played

(Note: Number of notes should not exceed 31 for reasons cited later)

¿Por qué el número de billetes está limitado a 31?  
Dado que los campos data1 y data2 de ShortMessage son de tipo byte, al usar setMessage(int command, int channel, int note, int speed), la nota y la velocidad no deben exceder 127.
Programa 2: Usar el código de comando 192 para cambiar el tipo de instrumento 
 

Java

// Java program showing how to change the instrument type
import javax.sound.midi.*;
import java.util.*;
 
public class MyMidiPlayer1 {
 
    public static void main(String[] args)
    {
 
        MyMidiPlayer1 player = new MyMidiPlayer1();
 
        Scanner in = new Scanner(System.in);
        System.out.println("Enter the instrument to be played");
        int instrument = in.nextInt();
        System.out.println("Enter the note to be played");
        int note = in.nextInt();
 
        player.setUpPlayer(instrument, note);
    }
 
    public void setUpPlayer(int instrument, int note)
    {
 
        try {
 
            Sequencer sequencer = MidiSystem.getSequencer();
            sequencer.open();
            Sequence sequence = new Sequence(Sequence.PPQ, 4);
            Track track = sequence.createTrack();
 
            // Set the instrument type
            track.add(makeEvent(192, 1, instrument, 0, 1));
 
            // Add a note on event with specified note
            track.add(makeEvent(144, 1, note, 100, 1));
 
            // Add a note off event with specified note
            track.add(makeEvent(128, 1, note, 100, 4));
 
            sequencer.setSequence(sequence);
            sequencer.start();
 
            while (true) {
 
                if (!sequencer.isRunning()) {
                    sequencer.close();
                    System.exit(1);
                }
            }
        }
        catch (Exception ex) {
 
            ex.printStackTrace();
        }
    }
 
    public MidiEvent makeEvent(int command, int channel,
                               int note, int velocity, int tick)
    {
 
        MidiEvent event = null;
 
        try {
 
            ShortMessage a = new ShortMessage();
            a.setMessage(command, channel, note, velocity);
 
            event = new MidiEvent(a, tick);
        }
        catch (Exception ex) {
 
            ex.printStackTrace();
        }
        return event;
    }
}
Input : Enter the instrument to be played
        102
        Enter the note to be played
        110

Output : Sound note is played

Input : Enter the instrument to be played
        40
        Enter the note to be played
        100

Output : Sound note is played

NOTA: El código no se ejecutará en el IDE en línea, ya que el código requiere unos segundos de tiempo de ejecución para la reproducción que el IDE no permite.
 

Publicación traducida automáticamente

Artículo escrito por green_dot y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *