We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › RWMidi - Midi Chords
Page Index Toggle Pages: 1
RWMidi - Midi Chords (Read 1195 times)
RWMidi - Midi Chords
Jul 19th, 2009, 8:19am
 
Hello,

I'm a processing novice, however over the past few weeks I've been playing around with the Ruin & Wesen midi library and I've had some good results.

In the past couple of days something has come up that I believe is down to my understanding of how the code is ordered overall, as opposed to something linked with the R&W library, in fact, I'm sure of it.

That's why I'm posting this under 'Syntax Questions.'

In the code below I'm using a midi controller keyboard to draw two squares, simple enough.

However, it seems to be the case that it's either the red square or the green square that gets drawn at any one time, and if I play both notes together on the keyboard the code only selects one.

I've tried using various 'for,' 'if,' and 'while' combinations, but no luck.

It would be great if anyone could point out my lack of understanding!

Many thanks.




import rwmidi.*;

MidiOutput midiOutput;
MidiInput midiInput;

static final int defaultInputDevice  = 1;
static final int defaultOutputDevice = 0;

int pit;
int vel;

int xPos = 0;
int yPos = 0;

int AColor = color(255, 0, 0);
int DColor = color(0, 255, 0);

void setup(){
 
 size(400, 400);
 background(0);
 frameRate(24);
 
 MidiInputDevice inDevices[] = RWMidi.getInputDevices();
 for (int i = 0; i < inDevices.length; i++) {
   println("In " + i + ": " + inDevices[i].getName());
 }
 MidiOutputDevice outDevices[] = RWMidi.getOutputDevices();
 for (int i = 0; i < outDevices.length; i++) {
   println("Out " + i + ": " + outDevices[i].getName());
 }
 midiInput = inDevices[defaultInputDevice].createInput(this);
 midiOutput = outDevices[defaultOutputDevice].createOutput();

}

void noteOnReceived(Note note){
   
   vel = note.getVelocity();
   pit = note.getPitch();
   println("noteOn, Velocity: " + vel + ", Pitch: " + pit);
   
}

void redSquare(int xPos, int yPos, int squareWidth, int squareHeight){
 
 fill(AColor);
 noStroke();
 rectMode(CENTER);
 translate(width/2, height/2);
 rect(xPos, yPos, squareWidth, squareWidth);
 
}

void greenSquare(int xPos, int yPos, int squareWidth, int squareHeight){
 
 fill(DColor);
 noStroke();
 rectMode(CENTER);
 translate(width/2, height/2);
 rect(xPos, yPos, squareWidth, squareWidth);
 
}

void noteChoice(){
 
 int[] ANoteArray = {9, 21, 33, 45, 57, 69, 81, 93, 105, 117};
 int[] DNoteArray = {2, 14, 26, 38, 50, 62, 74, 86, 98, 110, 122};
 
 for(int i=0; i < ANoteArray.length; i++) {
     if(pit == ANoteArray[i] && vel > 0){
       redSquare(xPos, yPos-50, vel, vel);
     }
 }
 
 for(int i=0; i < DNoteArray.length; i++) {
     if(pit == DNoteArray[i] && vel > 0){
       greenSquare(xPos, yPos+50, vel, vel);
     }
 }
}

void draw(){
 
 noStroke();
 fill(0, 10);
 rectMode(CORNER);
 rect(0, 0, width, height);
 
 noteChoice();
 
 smooth();
 
}
Re: RWMidi - Midi Chords
Reply #1 - Jul 19th, 2009, 9:57am
 
> if I play both notes together on the keyboard

print out the value of pit in your loop. i think it'll always be set to the last note you've pressed with no way of telling you that two keys are being played at the same time.

btw, rather than have an array of possible values of the A and D notes and having to iterate through them to find a match it looks like all you need to do is to look at (pit % 12) (ie the remainder of pit modulo 12) which will be 9 for A and 2 for D.
Re: RWMidi - Midi Chords
Reply #2 - Jul 19th, 2009, 10:27am
 
Hey koogy,

Many thanks, I adjusted the 'noteChoice' function as you suggested, so something like this:

void noteChoice(){

 if(pit%12 == 9 && vel > 0){
    redSquare(xPos, yPos-50, vel, vel);
 }
 
 if(pit%12 == 2 && vel > 0){
   greenSquare(xPos, yPos+50, vel, vel);
 }
}

And sure enough, it does work.

I have been looking at what the 'printIn' is showing and of course you get the Velocity and Pitch when the key is first struck, and a zero value for the Velocity when the key is released. It will 'print' more than one pitch if more than one key is struck, but it seems to choose only one of these?

Perhaps like you were suggesting, the last one only?

I think the way around this is to somehow keep checking if a particular key, or key group is being held, continue drawing the shape, then when it's released, stop.

I've tried using 'while' with the Velocity, but this only seems to send it all a bit silly, shapes all over sketch area and whatnot?

I'm sure there's a way to do this, i just cant see it yet.

Re: RWMidi - Midi Chords
Reply #3 - Jul 20th, 2009, 2:23am
 
am guessing it's printing both values when pressed or released (asynchronously) but the draw loop (which is synchronous) can only see the last value.

maybe you need a list (or a hashmap, probably) - add key presses to the list when you see them, remove them when you see key released then draw everything in the list within draw().

unfortunately i don't have any midi hardware so i can't reproduce this behaviour.

(it's println by the way, with a small L, not a big i. short for printLine)
Re: RWMidi - Midi Chords
Reply #4 - Jul 26th, 2009, 3:21pm
 
Hey koogy,

(And anyone else who can help), I've been playing around this a bit and I've managed to get a clear noteOn/noteOff variable coming from the noteOnReceived() function.

In the printLine (thanks for correcting that) everything looks fine, a clear noteOn and noteOff for each key.

After this point I thought the most precise, unambiguous way to check this would be with a String, so I have the AMessage and DMessage variable, the rest is self-explanatory.

However the results are not what I expected, sometimes the only the redSquare draws, or the greenSquare with an offset red etc.

What I'm aiming for is that when the note is pressed the coloured square stays on screen until the note is released.

I may be missing a bigger point regarding either the handling of midi signals, or just general proficiency with the language, but I'm kinda stumped.

Even hints would be appreciated!

I've ordered Processing: A Programming Handbook for Visual Designers and Artists, by Fry and Reas to help get me up to speed with all this.

I probably should have mentioned, I've come from Flash and Actionscript.

Many thanks!


import rwmidi.*;

MidiInput midiInput;
MidiOutput midiOutput;

static final int defaultInputDevice  = 1;
static final int defaultOutputDevice = 0;

int pit;
int vel;

int[] ANoteArray = {9, 21, 33, 45, 57, 69, 81, 93, 105, 117};
int[] DNoteArray = {2, 14, 26, 38, 50, 62, 74, 86, 98, 110, 122};

int xPos = 0;
int yPos = 0;

int AColor;
int DColor;

String AMessage = ("noteAOff");
String DMessage = ("noteDOff");
 
void setup(){
 
 size(400, 400);
 background(0);
 frameRate(24);
 
 MidiInputDevice inDevices[] = RWMidi.getInputDevices();
 for (int i = 0; i < inDevices.length; i++) {
   println("In " + i + ": " + inDevices[i].getName());
 }
 MidiOutputDevice outDevices[] = RWMidi.getOutputDevices();
 for (int i = 0; i < outDevices.length; i++) {
   println("Out " + i + ": " + outDevices[i].getName());
 }
 midiInput = inDevices[defaultInputDevice].createInput(this);
 midiOutput = outDevices[defaultOutputDevice].createOutput();

}

void draw(){
 backGroundRedraw();
 noteChoice();
}  

void backGroundRedraw(){
 
 noStroke();
 fill(0, 10);
 rectMode(CENTER);
 rect(width/2, height/2, width, height);
 
}
 
void noteChoice(){
 
 if(AMessage.contains("noteAOn")){
   redSquare();
 }
 if(DMessage.contains("noteDOn")){
   greenSquare();
 }
 
}

void noteOnReceived(Note note){

   pit = note.getPitch();
   vel = note.getVelocity();

   for(int i = 0; i < ANoteArray.length; i++){
     if(pit == ANoteArray[i] && vel > 0){
       AMessage = ("noteAOn, Pitch A: " + pit + ", Velocity A: " + vel);
       println(AMessage);
     }else if(pit == ANoteArray[i] && vel == 0){
       AMessage = ("noteAOff, Pitch A: " + pit + ", Velocity A: " + vel);
       println(AMessage);
     }
   }

   for(int i = 0; i < DNoteArray.length; i++){
     if(pit == DNoteArray[i] && vel > 1){
       DMessage = ("noteDOn, Pitch D: " + pit + ", Velocity D: " + vel);
       println(DMessage);
     }else if(pit == DNoteArray[i] && vel == 0){
       DMessage = ("noteDOff, Pitch D: " + pit + ", Velocity D: " + vel);
       println(DMessage);
     }
   }
   
}


void redSquare(){

   AColor = color(255, 0, 0, vel);
   fill(AColor);
   noStroke();
   rectMode(CENTER);
   translate(width/2, height/2);
   rect(xPos, yPos-50, vel, vel);

}

void greenSquare(){
 
   DColor = color(0, 255, 0, vel);
   fill(DColor);
   noStroke();
   rectMode(CENTER);
   translate(width/2, height/2);
   rect(xPos, yPos+50, vel, vel);
 
}




 
Re: RWMidi - Midi Chords
Reply #5 - Jul 27th, 2009, 8:39am
 
well, as i said, i can't test this as i don't have the hardware so i'm just going on inspection.

but what i did notice is that you're translating the squares. and translation is cumulative. put a pushMatrix() and popMatrix() around your redSquare() and greenSquare(), see if that helps. (would explain the offset red square you mention)

and if you're going to use a loop to check against the possible values of pitch then at least break out of it when you've found something, anything else is just a waste of cycles. 8)

Re: RWMidi - Midi Chords
Reply #6 - Jul 27th, 2009, 10:54am
 
Mr koogy,

Ecstatic would not be an overstatement, your pushMatrix(); popMatrix(); idea sorted it in one go!

Now both keys can be pressed and held for as long as you like, showing the correct representations, wonderful!

In regard to the use of loops, cycles and checking, I take your point, but not your meaning perhaps. I've still got much to absorb.

No need to be specific, I'm enjoying figuring this out, but would you be referring to the 'noteChoice()' function, or the 'noteOnReceived()' function? Or Both?

Many thanks again, and the help has been much appreciated!

Re: RWMidi - Midi Chords
Reply #7 - Jul 27th, 2009, 2:04pm
 
int[] ANoteArray = {9, 21, 33, 45, 57, 69, 81, 93, 105, 117};

you check to see if it's a 9. if it is then it's an A.

but even if it is you continue to check all the other values too, every time. same with D. you had some code that used (pitch % 12)...
Page Index Toggle Pages: 1