该程序将采用指定的MIDI INPUT设备,并根据同时发送的信号数量,在指定的MIDI OUTPUT设备的通道1-4之间分割其信号(无论通道如何)。
这意味着如果您使用MIDI键盘作为INPUT设备,并按键盘上的任意一个键,该数据将被发送到OUTPUT设备上的通道1。但是,如果您同时按下(或永远按下)键盘上的任意2个键,您按下的第一个键将被发送到通道1,而您按下的第二个键将被发送到通道2.程序将使用相同的过程最多4个同时音符(因此4个输出通道)。
这样做不需要MIDI键盘,只需下载像VMPK(http://vmpk.sourceforge.net)这样的虚拟键盘,并创建一个类似loopMIDI(https://www.tobias-erichsen.de/software/loopmidi.html)的虚拟端口,将虚拟键盘连接到脚本。如果使用这两个程序,请使用loopMIDI创建虚拟端口,然后打开VMPK并将其输出设置为刚刚创建的虚拟端口。
唯一的问题是,如果您一次玩多个键,只释放其中一个键(并继续保持其余键),然后尝试再次按下您释放的键。它不会将消息发送到空闲频道,而是尝试将消息发送到已经忙碌的频道。
EX:如果按一个键并按住它,如果notesPlayed = 0
程序将音符ON信号发送到通道1并设置notesPlayed = notesPlayed + 1
,然后等待你放开键,然后将音符OFF信号发送到同一通道通过设置notesPlayed = notesPlayed - 1
。
所以,如果你没有碰到键盘(notesPlayed = 0
),然后你开始拿着一把钥匙(notesPlayed = 1
)并开始拿着另一把钥匙(现在是notesPlayed = 2
),然后放开第一把钥匙(现在又来了notesPlayed = 1
),然后试试按一个键,它会尝试将它发送到通道2,因为notesPlayed = 1
,但因为通道2仍在播放音符而失败。我正在绞尽脑汁解决这个问题!
我认为需要有类似的东西
if (notesPlayed == 1) { // if 1 note is currently being played
if (stat2 = 1) { // if channel 2 is already busy
"send note to the last available channel"
}
}
这是程序。
import controlP5.*;
import themidibus.*;
import at.mukprojects.console.*;
Console console;
ControlP5 cp5;
MidiBus myBus;
PFont sans;
final int MODE_1 = 1;
final int MODE_2 = 2;
int notesPlayed,ch1,ch2,ch3,ch4,stat1,stat2,stat3,stat4,mode,r,g,b;
String input = "NOT CONNECTED";
String output = "NOT CONNECTED";
String reset,devicesConnected;
boolean showConsole;
void setup() {
size(300, 550);
smooth();
notesPlayed = 0;
cp5 = new ControlP5(this);
cp5.addTextfield("input").setPosition(10, 365).setSize(80, 20).setAutoClear(false);
cp5.addTextfield("output").setPosition(100, 365).setSize(80, 20).setAutoClear(false);
cp5.addBang("submit").setPosition(190, 365).setSize(20, 20);
cp5.addBang("reset").setPosition(270, 365).setSize(20, 20);
console = new Console(this);
console.start();
showConsole = true;
mode = MODE_1;
sans = loadFont("SansSerif.plain-18.vlw");
reset = "yes";
devicesConnected = "no";
r = 255;
g = 0;
b = 0;
}
void draw(){
background(0);
switch(mode) {
case MODE_1:
// (x, y, width, height, preferredTextSize, minTextSize, linespace, padding, strokeColor, backgroundColor, textColor)
console.draw(2, 0, 295, 360, 13, 13, 1, 1);
break;
case MODE_2:
// (x, y, width, height, preferredTextSize, minTextSize, linespace, padding, strokeColor, backgroundColor, textColor)
console.draw(2, 0, 295, 360, 13, 13, 1, 1, color(220), color(0), color(0, 255, 0));
break;
}
textSize(12);
fill(200, 200, 200);
text("INPUT:", 10, 420);
text("OUTPUT:", 10, 435);
fill(r, g, b);
text(input, 70, 420);
text(output, 70, 435);
fill(255, 255, 0);
textSize(28);
text("Channel Activity", 15, 450);
textSize(60);
if (stat1 == 0) {
fill(90, 90, 90);
text("1", 20, 485);
}
if (stat2 == 0) {
fill(90, 90, 90);
text("2", 95, 485);
}
if (stat3 == 0) {
fill(90, 90, 90);
text("3", 170, 485);
}
if (stat4 == 0) {
fill(90, 90, 90);
text("4", 245, 485);
}
if (stat1 == 1) {
fill(0, 255, 0);
text("1", 20, 485);
}
if (stat2 == 1) {
fill(0, 255, 0);
text("2", 95, 485);
}
if (stat3 == 1) {
fill(0, 255, 0);
text("3", 170, 485);
}
if (stat4 == 1) {
fill(0, 255, 0);
text("4", 245, 485);
}
textFont(sans);
fill(r, g, b);
textSize(14);
text("- Active Devices -", 10, 405);
if (reset == "yes") {
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
MidiBus.findMidiDevices();
MidiBus.list();
println("------------------------------------");
println(" Input device names below");
println(" (case sensitive)");
input = "NOT CONNECTED";
output = "NOT CONNECTED";
r = 255;
g = 0;
b = 0;
reset = "no";
} else {}
}
void noteOn(int channel, int pitch, int velocity) {
if (notesPlayed == 0) {
myBus.sendNoteOn(0, pitch, velocity);
ch1 = pitch;
stat1 = 1;
println("CH1 - ON - ", pitch, " ", velocity);
}
if (notesPlayed == 1) {
myBus.sendNoteOn(1, pitch, velocity);
ch2 = pitch;
stat2 = 1;
println("CH2 - ON - ", pitch, " ", velocity);
}
if (notesPlayed == 2) {
myBus.sendNoteOn(2, pitch, velocity);
ch3 = pitch;
stat3 = 1;
println("CH3 - ON - ", pitch, " ", velocity);
}
if (notesPlayed == 3) {
myBus.sendNoteOn(3, pitch, velocity);
ch4 = pitch;
stat4 = 1;
println("CH4 - ON - ", pitch, " ", velocity);
}
notesPlayed = notesPlayed + 1;
}
void noteOff(int channel, int pitch, int velocity) {
if (ch1 == pitch) {
myBus.sendNoteOff(0, pitch, velocity);
stat1 = 0;
println("CH1 - OFF - ", pitch, " ", velocity);
}
if (ch2 == pitch) {
myBus.sendNoteOff(1, pitch, velocity);
stat2 = 0;
println("CH2 - OFF - ", pitch, " ", velocity);
}
if (ch3 == pitch) {
myBus.sendNoteOff(2, pitch, velocity);
stat3 = 0;
println("CH3 - OFF - ", pitch, " ", velocity);
}
if (ch4 == pitch) {
myBus.sendNoteOff(3, pitch, velocity);
stat4 = 0;
println("CH3 - OFF - ", pitch, " ", velocity);
}
notesPlayed = notesPlayed - 1;
}
void submit() {
if (devicesConnected == "yes") {
println("There are already devices connected! Please reset first and try again.");
} else {
r = 0;
g = 255;
b = 0;
input = cp5.get(Textfield.class,"input").getText();
output = cp5.get(Textfield.class,"output").getText();
myBus = new MidiBus(this, input, output);
devicesConnected = "yes";
mode = MODE_2;
}
}
void reset() {
if (devicesConnected == "yes") {
myBus.close();
devicesConnected = "no";
mode = MODE_1;
} else {}
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
println(" ");
MidiBus.findMidiDevices();
MidiBus.list();
println("------------------------------------");
println(" Input device names below");
println(" (case sensitive)");
input = "NOT CONNECTED";
output = "NOT CONNECTED";
r = 255;
g = 0;
b = 0;
mode = MODE_1;
}
你的问题是系统的当前状态是由一个计数器(notesPlayed
)决定的;这不允许您确定当前活动的四个输出中的哪一个。
您需要为四个输出提供四个独立状态。换句话说,创建一个包含四个条目的数组;收到音符开消息时,搜索数组中的第一个空闲条目;收到音符关闭消息时,搜索数组中具有相同音符的匹配条目。