Java 中的 MIDI - 尝试从多个 CC 获取连续的控制器数据但只能获取 1 个
MIDI in Java - Trying to get continuous controller data from multiple CCs but only able to get 1
我有一个输出两组连续控制器数据的 Moog Theremini。 “音高”天线在 CC 20 上输出,“音量”天线在 CC2 上输出。
我可以毫无问题地提取 CC20 的轨道数据,但是在阅读了 MIDI 文档和文章一天之后,似乎无法找到任何方法来获取同一轨道上的其他 CC 数据。有没有人对此足够熟悉来帮助我?
下面的输出代码是我想要弄清楚的。我的意图是
- 将轨道(只有 1 个轨道)上的最后一条(或倒数第二条)消息转换为短消息
- 打印命令、状态、控制器#和控制器值
- 这是在循环中完成的,因此它会无限期地打印出曲目的最新部分。
下面的代码成功地实现了 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 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);
}
}
这里是显示事件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);
}
}
}
这里不需要音序器,除非你想记录接收到的事件之间的相对时间。
下面是一个示例,说明如何在自定义接收器中直接显示所有传入的 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()
{
}
}
我有一个输出两组连续控制器数据的 Moog Theremini。 “音高”天线在 CC 20 上输出,“音量”天线在 CC2 上输出。
我可以毫无问题地提取 CC20 的轨道数据,但是在阅读了 MIDI 文档和文章一天之后,似乎无法找到任何方法来获取同一轨道上的其他 CC 数据。有没有人对此足够熟悉来帮助我?
下面的输出代码是我想要弄清楚的。我的意图是
- 将轨道(只有 1 个轨道)上的最后一条(或倒数第二条)消息转换为短消息
- 打印命令、状态、控制器#和控制器值
- 这是在循环中完成的,因此它会无限期地打印出曲目的最新部分。
下面的代码成功地实现了 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 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);
}
}
这里是显示事件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);
}
}
}
这里不需要音序器,除非你想记录接收到的事件之间的相对时间。
下面是一个示例,说明如何在自定义接收器中直接显示所有传入的 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()
{
}
}