Hello,
I´ve been coding some objects lately and after a fair amount of sweating I´ve come to the conclusion that you can´t change the value of an outlet inside a FOR function. Is this right?
What I´m doing is an object for controlling the leds of a nanokontrol 2.
I´ve got 30 bool inlets (one for each button) and four outlets connected to a midi/out/cc any object:
-Value (frac32.positive)
-CC (int32.positive)
-Channel (int32.positive)
-Trigger (bool32)
In the K-Rate code section I write all the inlet states into an array, and then I use a FOR function for comparing these values with another array with old values. If they have changed the outlets are supposed to change to the corresponding value, cc, channel and send a trigger to let the midi/out/cc any object know it should send a cc message.
It should be pretty straight forward, but it doesn´t work. It seems that I have to have another array for storing if any inlet has changed, and then concatenate 30 IFs for sending messages if there has been any change in the inputs.
This seems to work, but it feels like very sloppy programming.
So, is this right, or am I doing something wrong and it should work inside the FOR function?
[SOLVED]Can you not change outlet values inside a FOR function?
This was my original code. It did work just fine, but then making another object that simultaneously toggles one boolean output on and another boolean output off I realised that this code can´t deal with simultaneous changes:
states[0] = inlet_S1;
states[1] = inlet_S2;
states[2] = inlet_S3;
states[3] = inlet_S4;
states[4] = inlet_S5;
states[5] = inlet_S6;
states[6] = inlet_S7;
states[7] = inlet_S8;
states[8] = inlet_M1;
states[9] = inlet_M2;
states[10] = inlet_M3;
states[11] = inlet_M4;
states[12] = inlet_M5;
states[13] = inlet_M6;
states[14] = inlet_M7;
states[15] = inlet_M8;
states[16] = inlet_R1;
states[17] = inlet_R2;
states[18] = inlet_R3;
states[19] = inlet_R4;
states[20] = inlet_R5;
states[21] = inlet_R6;
states[22] = inlet_R7;
states[23] = inlet_R8;
states[24] = inlet_REW;
states[25] = inlet_FF;
states[26] = inlet_STOP;
states[27] = inlet_PLAY;
states[28] = inlet_REC;
states[29] = inlet_CYCLE;for (int i=0; i<30; i++){
if (states[i] != prevstates[i]){
value = states[i]*0x7FFFFFFF;
cc = i+37;
channel = attr_MidiChannel;
trig = 1;
prevstates[i] = states[i];
}
}outlet_Value = value;
outlet_CC = cc;
outlet_Channel = channel;
outlet_Trigger = trig;trig = 0;
Then I tried doing this:
for (int i=0; i<30; i++){
if (states[i] != prevstates[i]){
change[i] = 1;
prevstates[i] = states[i];
}for (int i=0; i<30; i++){
if (change[i]){
outlet_Value = states[i]*0x7FFFFFFF;
outlet_CC = i+37;
outlet_Channel = attr_MidiChannel;
outlet_Trigger = 1;
}
outlet_Trigger = 0;
}
But then it doesn´t send anything anymore
Ok I finally got it.
Instead of having outlets for sending to a midi/out/cc any object I inserted the midi sending code into my object, and now it works flawlessly, even when receiving simultaneous toggles.
states[0] = inlet_S1;
states[1] = inlet_S2;
states[2] = inlet_S3;
states[3] = inlet_S4;
states[4] = inlet_S5;
states[5] = inlet_S6;
states[6] = inlet_S7;
states[7] = inlet_S8;
states[8] = inlet_M1;
states[9] = inlet_M2;
states[10] = inlet_M3;
states[11] = inlet_M4;
states[12] = inlet_M5;
states[13] = inlet_M6;
states[14] = inlet_M7;
states[15] = inlet_M8;
states[16] = inlet_R1;
states[17] = inlet_R2;
states[18] = inlet_R3;
states[19] = inlet_R4;
states[20] = inlet_R5;
states[21] = inlet_R6;
states[22] = inlet_R7;
states[23] = inlet_R8;
states[24] = inlet_REW;
states[25] = inlet_FF;
states[26] = inlet_STOP;
states[27] = inlet_PLAY;
states[28] = inlet_REC;
states[29] = inlet_CYCLE;for (int i=0; i<30; i++){
if (states[i] != prevstates[i]){
MidiSend3((midi_device_t) attr_device, MIDI_CONTROL_CHANGE + (channel-1), (i+37), __USAT((states[i]*0x07FFFFFF)>>20,7));
prevstates[i] = states[i];
}
}
holy christ the feeling of relief you get when you solve a problem you´ve been fighting for days...
I know the feeling well! Glad you got it sorted.
To kind of answer your questions (I'm no code expert):
No, the outlets won't work in a loop like that, you'd end up with the last calculated values at the end of the loop. But when you put the midi code in, it's sending each message to the midi output buffer, so they all get queued up and sent out.
You could also use this for the controller input - recieve the midi and store it in an array.
For this kind of stuff (controllers/buttons/leds) check out rbrts midi table store and table send,. Using the table for the array is useful because you can save them to the sd card for templates or whatever.
That was what was happening. When receiving simultaneous changes only the last one got sent.
I´ll check out rbrts objects, even though I´m pretty happy with mine right now, it does exactly what I want
Thanks!!!
Another alternative is to code the loop so that once it finds one state change, it outputs that CC value, saves its current state (i.e. the i variable), and exits, thus continuing at the next k-rate interval. You won't be able to grab more than one state change per k-rate interval, but on the other hand, with the k-rate being 3 kHz, and consequently the k-rate interval being 1/3000 = 333 µs, you're not going to loose much, since it takes 320 µs to send a MIDI byte anyway (at least over DIN MIDI).