【问题标题】:Java Midi - How to get notes from midi whilst it's playingJava Midi - 如何在播放时从 midi 获取音符
【发布时间】:2014-10-08 21:03:50
【问题描述】:

我已经搜索了一段时间,但找不到我想做的事情的答案。

我想播放一个 MIDI 文件,并在播放时在屏幕上显示音符。当音符停止播放时,它应该会从屏幕上消失。

我可以使用音序器演奏 MIDI,但不知道如何让音符开始播放,或者何时停止播放音符。

我已经研究过 ControllerEventListeners 和 MetaEventListeners,但仍然不知道该怎么做。

任何帮助将不胜感激。

【问题讨论】:

  • 是否有一个解决方案是读取 MIDI 文件,获取所有音符及其持续时间,然后运行另一个线程来显示音符?如果有一些延迟,这不会变得不同步吗?

标签: java midi javax.sound.midi


【解决方案1】:

这是你应该做的:

你必须实现Receiver然后

sequencer = MidiSystem.getSequencer();
sequencer.open();
transmitter = sequencer.getTransmitter();
transmitter.setReceiver(this);

之后,每次有事件发生都会触发下一个方法:

@Override
public void send(MidiMessage message, long timeStamp) {
    if(message instanceof ShortMessage) {
        ShortMessage sm = (ShortMessage) message;
        int channel = sm.getChannel();

        if (sm.getCommand() == NOTE_ON) {

            int key = sm.getData1();
            int velocity = sm.getData2();
            Note note = new Note(key);
            System.out.println(note);

        } else if (sm.getCommand() == NOTE_OFF) {

            int key = sm.getData1();
            int velocity = sm.getData2();
            Note note = new Note(key);
            System.out.println(note);
        } else {
            System.out.println("Command:" + sm.getCommand());
        }
    }
}

如果你愿意,你也可以使用这个类:

public class Note {

    private static final String[] NOTE_NAMES = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};

    private String name;
    private int key;
    private int octave;

    public Note(int key) {
        this.key = key;
        this.octave = (key / 12)-1;
        int note = key % 12;
        this.name = NOTE_NAMES[note];
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof Note && this.key == ((Note) obj).key;
    }

    @Override
    public String toString() {
        return "Note -> " + this.name + this.octave + " key=" + this.key;
    }
}

【讨论】:

    【解决方案2】:

    这是FAQ
    将您自己的 Receiver 连接到音序器的 Transmitter。

    有关示例,请参阅 MidiPlayer 中的 DumpReceiver。

    【讨论】:

    • 事实证明这非常有用,但是您知道如何获取音符的持续时间吗?我想做一个基本的 midi 可视化工具,当音符淡出时会淡出一个正方形。
    • 当您收到 note off 事件时,便笺停止。
    • 我不确定我的观点是否明确。目前,当播放音符时,我正在显示一个彩色方块。当我收到一个便笺事件时,我已经让它消失了。我想让彩色方块随着音符的淡出慢慢淡出。我假设接收器不知道一个音符会播放多长时间是正确的吗?如果是这样,我想我必须在播放之前以某种方式读取 MIDI 文件,并用它来计算时间。感谢您的所有帮助,您真的很有帮助。
    • 有些乐器会淡出,有些则不会。该淡出不受音符关闭事件时间的影响(除了由于音符关闭而导致的快得多的衰落)。
    • 我现在明白了,因为 MIDI 需要一个音库,所以无法知道音符是否正在淡出。我想我仍然可以淡出颜色,如果我找到一种具有良好淡出时间的乐器。谢谢你的帮助。现在我有了修改程序的乐趣,也许还可以添加更多东西,这样我就可以了解更多关于 java 的知识。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多