繁体   English   中英

在 Java 中使用 MIDI

[英]Using MIDI in Java

我正在尝试编写一个使用 MIDI 的 Java 程序,因此该程序必须排列:音符(包含我想要播放的所有音符)和另一个数组时间(指定何时播放音符)音符和时间一次分组三个,所以我可以有多个和弦,问题是程序只播放一个非常简短的音符然后停止,我做错了什么? 波纹管是代码,我使用的是 Java 16。

package application;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.ShortMessage;

public class App {

    public static void main(String[] args)
            throws MidiUnavailableException, InvalidMidiDataException, InterruptedException {

        var receiver = MidiSystem.getReceiver();

        int[] notes = { 60, 64, 67, 60, 65, 67, 55, 59, 62, 55, 60, 62, 53, 57, 60, 53, 58, 60 };
        int[] times = { 0, 0, 0, 1000, 1000, 1000, 2000, 2000, 2000, 3000, 3000, 3000, 4000, 4000, 4000, 5000, 5000,
                5000 };

        for (int i = 0; i < notes.length; i++) {

            int note = notes[i];
            int time = times[i];
            System.out.println(note + ":" + time);
            receiver.send(new ShortMessage(ShortMessage.NOTE_ON, 0, note, 127), time * 1000);
            receiver.send(new ShortMessage(ShortMessage.NOTE_OFF, 0, note, 127), (time + 1000) * 1000);
        }

        Thread.sleep(7000);
    }

}

我认为它与 ShortMessage.NOTE_OFF 有关,但我不确定,我无法弄清楚。

问题很可能与您的times数组有关。

取自关于序列器的 oracle java 文档

如前所述,该程序可以在它发送到设备接收器的每条 MIDI 消息中包含一个时间戳。 但是,此类时间戳仅用于微调时序,以校正处理延迟。 调用者一般不能设置任意时间戳; 传递给 Receiver.send 的时间值必须接近当前时间,否则接收设备可能无法正确安排消息。 这意味着如果应用程序想要提前为整首音乐创建一个 MIDI 消息队列(而不是创建每个消息以响应实时事件),则必须非常小心地安排每个消息在几乎正确的时间调用 Receiver.send。

幸运的是,大多数应用程序不必关心这样的调度。 程序可以使用 Sequencer 对象来管理 MIDI 消息队列,而不是调用 Receiver.send 本身。

您盲目地假设数字(1000、2000、3000 等)是毫秒,但在 api 中定义为ticks

就像在任何音乐中一样,您需要定义细分和每滴答脉冲 (PPQ),例如四分音符、16 分音符等。

在 java 中,这通常是通过定义一个音序器和这些设置来完成的,然后在所述音序器上创建一个音轨,然后在该音轨上播放音符。

这是我在互联网上找到的一个例子。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM