Одновременные события if/else в обработке
Эта программа возьмет указанное устройство MIDI INPUT и разделит его сигналы (независимо от канала) между каналами 1-4 указанного устройства MIDI OUTPUT в зависимости от того, сколько сигналов отправляется одновременно.
Это означает, что если вы используете MIDI-клавиатуру в качестве устройства INPUT и нажимаете любую отдельную клавишу на клавиатуре, эти данные будут отправлены на канал 1 на устройстве OUTPUT. НО, если вы нажмете (или НИКОГДА не нажимаете) любые 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
, а затем ждет, пока вы отпустите клавишу, прежде чем отправить сигнал ОТКЛ нот на тот же канал, после чего установите 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;
}
1 ответ
Ваша проблема в том, что текущее состояние системы определяется одним счетчиком (notesPlayed
); это не позволяет вам определить, какой из четырех выходов активен в данный момент.
Вам нужно иметь четыре независимых состояния для четырех выходов. Другими словами, создайте массив с четырьмя записями; при получении заметки о сообщении ищите первую свободную запись в массиве; когда получено сообщение об отключении, найдите соответствующую запись с той же записью в массиве.