无法在 Java MIDI 程序中更改乐器,InvalidMidiDataException:channel out of range

Posted

技术标签:

【中文标题】无法在 Java MIDI 程序中更改乐器,InvalidMidiDataException:channel out of range【英文标题】:Can't change instrument in Java MIDI program, InvalidMidiDataException:channel out of range 【发布时间】:2020-03-05 08:40:37 【问题描述】:

我无法使用 javax.sound.midi.ShortMessage.setMessage() 方法更改乐器。通道 0-15 为钢琴,不包括 9 为鼓。但是8-15应该是Chromatic Percussion。当我将频道设置为 16 或更多(范围从 0 到 127)时,我得到 javax.sound.midi.InvalidMidiDataException: channel out of range: 16. 请问,我该如何解决这个问题?

    import javax.sound.midi.*;

public class TestMidi

    public void play()
        try
            Sequencer player = MidiSystem.getSequencer();
            System.out.println("Sequencer created succesfully.");

            player.open();

            Sequence s = new Sequence(Sequence.PPQ, 4);

            Track track = s.createTrack();

            addShortMessage(track,1,192,1,102,0);
            addShortMessage(track,1,144,1,44,100);
            addShortMessage(track,16,128,1,44,100);

            player.setSequence(s);

            player.start();

         catch(Exception e)
            System.out.println("Fail.");
            e.printStackTrace();
        
    

    public static void main(String[] args)  
        TestMidi tm = new TestMidi();
        tm.play();
    

    void addShortMessage(Track track, long tick, int command, int channel, int data1, int data2) throws Exception 
        ShortMessage msg = new ShortMessage(command, channel, data1, data2);
        MidiEvent event = new MidiEvent(msg, tick);
        track.add(event);
    

【问题讨论】:

一个 MIDI 端口有 16 个通道,0…15。为什么你认为还有更多? 好吧,我在 Head First Java(第二版)一书中读到了一个示例。例如,有 102、80、40 之类的数字。此外,在 link 这个网站上,我发现了一个名为 General MIDI Level 1 Instrument Families 的表格。 我发现通道代表一种乐器,对吧? 有16个频道。每个通道都可以有自己的乐器(通过发送 Program Change 消息)。通常,每个通道可以同时播放多个音符。 @CL 我添加了 'a.setMessage(192,1,102,0);'在代码中。为什么它还在弹钢琴? 【参考方案1】:

频道编号从 0 到 15。每个频道都可以拥有自己的乐器(通过发送程序更改消息)。

此代码将两条消息添加到轨道。如果要添加第三条消息,则必须使用第三个对象调用track.add()

使用这样的辅助函数会更容易添加事件:

void addShortMessage(Track track, long tick,
                     int command, int channel, int data1, int data2) 
    ShortMessage msg = new ShortMessage(command, channel, data1, data2);
    MidiEvent event = new MidiEvent(msg, tick); //edited here
    track.add(event);

【讨论】:

我知道为什么,但它开始工作了,可能是我的软件出了问题,或者它太安静了。无论如何谢谢你

以上是关于无法在 Java MIDI 程序中更改乐器,InvalidMidiDataException:channel out of range的主要内容,如果未能解决你的问题,请参考以下文章

在音轨播放期间更改乐器 - MIDI/Java

Java MIDI - ControllerEventListener(如何更改乐器)

MIDI - 使用来自不同银行的乐器更改 MidiMessage 程序

我无法更改 JSR-135 上的 MIDI 频道程序

如何读取 MIDI 文件、更改其乐器并将其写回?

播放多乐器 MIDI 文件