Java 中的 MIDI - 尝试从多个 CC 获取连续的控制器数据,但只能获取 1 个

发布于 2025-01-16 11:05:02 字数 3411 浏览 2 评论 0原文

我有一个 Moog Theremini,它输出两组连续控制器数据。 “俯仰”天线在 CC 20 上输出,“音量”天线在 CC2 上输出。

我可以毫无问题地提取 CC20 的轨道数据,但在阅读了一天的 MIDI 文档和文章后,似乎找不到任何方法来获取同一轨道上的其他 CC 数据。有没有对此很熟悉的人来帮助我?

下面的输出代码是我想要弄清楚的。我的目的是

  1. 将轨道(只有 1 个轨道)上的最后一条(或倒数第二条)消息转换为短消息
  2. 打印命令、状态、控制器# 和控制器值
  3. 这是在循环中完成的,因此它会无限期地继续打印曲目的最新部分。

下面的代码成功地实现了 CC 20 的上述目标,但我似乎不知道如何获取 CC 2 的数据。老实说,我什至不确定它为什么要打印 CC20。


  try {
            ShortMessage sm = (ShortMessage) sequencePass.getTracks()[0].get(sequencePass.getTracks()[0].size()-2).getMessage();
            System.out.println("| comm " + sm.getCommand() + "| status " + sm.getStatus()  + "| d1 (Controller#) " + sm.getData1() + "| d2 (Controller value) " + sm.getData2());
            


        } catch (Exception e) {
            System.out.println("blah blah" + e);
        }

**此处编辑 1 是 MIDI 类:**


public MidiJunk() {
        try {
            MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); //looking through all of my MIDI devices
            for(int i=0;i<infos.length;i++)
            {
                System.out.println(infos[i].getName() + " - " + infos[i].getDescription());
            }
            System.out.println();

            MidiDevice INSTRUMENTO = MidiSystem.getMidiDevice(infos[5]); //the plugged in Theremini is here, so assigning it as a  MidiDevice
            INSTRUMENTO.open(); //opening midi device
            Sequencer sequencero = MidiSystem.getSequencer(); //default sequencer transmitter and receiver
            sequencero.open(); //open sequencer
            Transmitter transmittero = INSTRUMENTO.getTransmitter(); //linking transmitter to instrument?
            Receiver receivero = sequencero.getReceiver(); //get reciever from sequencer
            transmittero.setReceiver(receivero);
            Sequence testseq; //test sequence


            try {
                testseq = new Sequence(Sequence.PPQ,24);
                sequencero.setSequence(testseq);
                sequencero.recordEnable(testseq.createTrack(),0);
                sequencero.setTickPosition(0);
                sequencero.startRecording();
                Timer timeo = new Timer();
                TimerTask timeoTaskeo = new displayMidiEventsOnTimer(testseq);
                timeo.schedule(timeoTaskeo,400,400);
                Scanno.nextLine();

                sequencero.stopRecording();
                MidiSystem.write(testseq,1,new File("miditest.mid"));
                System.out.println("it's done");

            } catch (Exception ene) {
                System.out.println(ene);
            }

        } catch (Exception E) {
            System.out.println(E);

        }
    }

这里是显示事件类

public class displayMidiEventsOnTimer extends TimerTask {
    Sequence sequencePass;

    public displayMidiEventsOnTimer(Sequence thisguy) {
        sequencePass = thisguy;
    }

    @Override
    public void run() {
        try {
            ShortMessage sm = (ShortMessage) sequencePass.getTracks()[0].get(sequencePass.getTracks()[0].size()-2).getMessage();
            System.out.println("| comm " + sm.getCommand() + "| status " + sm.getStatus()  + "| d1 (Controller#) " + sm.getData1() + "| d2 (Controller value) " + sm.getData2());

        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

I have a Moog Theremini that outputs two sets of continuous controller data. The "pitch" antenna outputs on CC 20 and the "volume" antenna outputs on CC2.

I have no problem pulling up the track data for CC20, but after a day of reading MIDI docs and articles, can't seem to find any way to grab this other CC data on the same track. Is anyone familiar enough with this to help me out?

The output code below is what I'm trying to figure out. My intention with it is

  1. Convert the last (or second to last) message on the track (there's only 1 track) to a Short Message
  2. Print out the Command, Status, Controller # and Controller value
  3. This is done in a loop so it continues indefinitely printing out the latest part of the track.

The below code successfully achieves the above for CC 20, but I can't seem to figure out how to grab the data for CC 2. I'm not even sure why it's printing CC20 to be honest.


  try {
            ShortMessage sm = (ShortMessage) sequencePass.getTracks()[0].get(sequencePass.getTracks()[0].size()-2).getMessage();
            System.out.println("| comm " + sm.getCommand() + "| status " + sm.getStatus()  + "| d1 (Controller#) " + sm.getData1() + "| d2 (Controller value) " + sm.getData2());
            


        } catch (Exception e) {
            System.out.println("blah blah" + e);
        }

**Edit 1 here is the MIDI class: **


public MidiJunk() {
        try {
            MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); //looking through all of my MIDI devices
            for(int i=0;i<infos.length;i++)
            {
                System.out.println(infos[i].getName() + " - " + infos[i].getDescription());
            }
            System.out.println();

            MidiDevice INSTRUMENTO = MidiSystem.getMidiDevice(infos[5]); //the plugged in Theremini is here, so assigning it as a  MidiDevice
            INSTRUMENTO.open(); //opening midi device
            Sequencer sequencero = MidiSystem.getSequencer(); //default sequencer transmitter and receiver
            sequencero.open(); //open sequencer
            Transmitter transmittero = INSTRUMENTO.getTransmitter(); //linking transmitter to instrument?
            Receiver receivero = sequencero.getReceiver(); //get reciever from sequencer
            transmittero.setReceiver(receivero);
            Sequence testseq; //test sequence


            try {
                testseq = new Sequence(Sequence.PPQ,24);
                sequencero.setSequence(testseq);
                sequencero.recordEnable(testseq.createTrack(),0);
                sequencero.setTickPosition(0);
                sequencero.startRecording();
                Timer timeo = new Timer();
                TimerTask timeoTaskeo = new displayMidiEventsOnTimer(testseq);
                timeo.schedule(timeoTaskeo,400,400);
                Scanno.nextLine();

                sequencero.stopRecording();
                MidiSystem.write(testseq,1,new File("miditest.mid"));
                System.out.println("it's done");

            } catch (Exception ene) {
                System.out.println(ene);
            }

        } catch (Exception E) {
            System.out.println(E);

        }
    }

And here is the display events class

public class displayMidiEventsOnTimer extends TimerTask {
    Sequence sequencePass;

    public displayMidiEventsOnTimer(Sequence thisguy) {
        sequencePass = thisguy;
    }

    @Override
    public void run() {
        try {
            ShortMessage sm = (ShortMessage) sequencePass.getTracks()[0].get(sequencePass.getTracks()[0].size()-2).getMessage();
            System.out.println("| comm " + sm.getCommand() + "| status " + sm.getStatus()  + "| d1 (Controller#) " + sm.getData1() + "| d2 (Controller value) " + sm.getData2());

        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橘寄 2025-01-23 11:05:02

这里不需要定序器,除非您想记录接收到的事件之间的相对时间。

以下是如何直接在自定义接收器中显示所有传入 CC 消息的示例。

...
Transmitter transmittero = INSTRUMENTO.getTransmitter(); 
Receiver receivero = new MyReceiver();   // Connect to your custom receiver
transmittero.setReceiver(receivero);
...

class MyReceiver implements Receiver
{

    @Override
    public void send(MidiMessage mm, long timeStamp)
    {
        if (mm instanceof ShortMessage)
        {
            ShortMessage sm = (ShortMessage) mm;
            if (sm.getCommand() == ShortMessage.CONTROL_CHANGE)
            {
                int cc = sm.getData1();
                // Do something quick, filter ignored CCs etc.
                System.out.println("cc=" + cc);    
            }
        }
    }

    @Override
    public void close()
    {
    }

}

You don't need a sequencer here, unless you want to record the relative timings between the received events.

Here is an example how to display all incoming CC messages directly in a custom Receiver.

...
Transmitter transmittero = INSTRUMENTO.getTransmitter(); 
Receiver receivero = new MyReceiver();   // Connect to your custom receiver
transmittero.setReceiver(receivero);
...

class MyReceiver implements Receiver
{

    @Override
    public void send(MidiMessage mm, long timeStamp)
    {
        if (mm instanceof ShortMessage)
        {
            ShortMessage sm = (ShortMessage) mm;
            if (sm.getCommand() == ShortMessage.CONTROL_CHANGE)
            {
                int cc = sm.getData1();
                // Do something quick, filter ignored CCs etc.
                System.out.println("cc=" + cc);    
            }
        }
    }

    @Override
    public void close()
    {
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文