// Class Note manages the display and NOTE_ON/NOTE_OFF of a constant-pitch, // constant-velocity note on the visual "keyboard". class Note { int pitch ; // first argument for NOTE_ON and NOTE OFF int velocity ; // second argument for NOTE_ON and NOTE OFF int x, y ; // x,y coordinates relative to 0,0 in center of display int wide, high ; // width, height of this shape int Hue, Sat, Brt ; // Hue, Saturation, Brightness of this Note object. float shearDegrees = 0, shearDegreesSpeed = 0 ; Map isSounding = new HashMap(); // Map channel to whether it is sounding or not on each channel, initially not. Note(int pitch, int velocity, int x, int y, int wide, int high, int Hue, int Sat, int Brt) { // Copy parameters into data fields. this.pitch = pitch ; this.velocity = velocity ; this.x = x ; // Prefix class data field with "this." when function parameter or this.y = y ; // local variable has the same variable name. "this." is this object. this.wide = wide ; this.high = high ; this.Hue = Hue ; this.Sat = Sat ; this.Brt = Brt ; for (int c = 0 ; c < 16 ; c++) { // There are up to 16 channels (instruments) in MIDI. isSounding.put(c, false); // Each channel is NOT sounding at the start. } } // Display the Note, NOTE_ON when isBeingPressed on channel, NOTE_OFF when not. void display(boolean isHighlighted, boolean isBeingPressed, int channel) { if (channel < 0 && channel > 15) { return ; } pushMatrix(); pushStyle(); translate(x, y); shearX(radians(shearDegrees)); shearDegrees += shearDegreesSpeed ; while (shearDegrees >= 360) { shearDegrees -= 360 ; } while (shearDegrees < 0) { shearDegrees += 360 ; } //try { if (isHighlighted || isBeingPressed) { fill(Hue, 99, 99); if (isBeingPressed) { stroke(0, 0, 0); } else { stroke(Hue,99,99); } ellipse(0, 0, wide, high); } else { fill(Hue, 99, Brt); // Brt is dimmer for lower-velocity notes. stroke(Hue,99,99); rect(0, 0, wide, high); } // rect(0, 0, wide, high); if (isBeingPressed) { /* NO 3D IN assn4 on Android. pushMatrix(); stroke(0,0,0); // black fill(Hue, 99, 99); // STUDENT: You must replace box() with some other 3D graphic here. // You must also add a 2D PShape or PImage on top of your 3D graphic. // If you use a PImage, tint() it the same color as fill is here. // The 3D height of your 3D object must be based on Note's velocity. // Mine is the ratio of velocity / 128, scaled by max(wide, high), // with the 25 multiplier found via visual trial and error. box(wide, high, 25 * max(wide, high) * velocity / 128); popMatrix(); */ if (! isSounding.get(channel)) { sendOSCMessage("noteon", channel, pitch, velocity); /* ShortMessage newMessage = new ShortMessage() ; newMessage.setMessage(ShortMessage.NOTE_ON, channel, pitch, velocity); //receiver.send(newMessage, -1L); // send it now */ isSounding.put(channel, true); } } else { if (isSounding.get(channel)) { sendOSCMessage("noteoff", channel, pitch, velocity); /* ShortMessage newMessage = new ShortMessage() ; newMessage.setMessage(ShortMessage.NOTE_OFF, channel, pitch, velocity); //receiver.send(newMessage, -1L); // send it now */ isSounding.put(channel, false); } } //} catch (InvalidMidiDataException dx) { //System.err.println("MIDI ERROR: " + dx.getMessage()); // Error messages go here. //} popStyle(); popMatrix(); } // STUDENT: Add data fields to this class to implement 2D shearX // amount and speed in degrees, place the 2D shearX() call in the // appropriate place within Note.display(), and implement the following function. void setShearXSpeed(float speedInDegrees) { // STUDENT right this function so it sets constant-rate shearX changes, // in degrees, as used in display(). Update the shearX amount variable within display. // When speedInDegrees is 0, shearX speed and shearX amount must both return to 0. shearDegreesSpeed = speedInDegrees ; if (speedInDegrees == 0) { shearDegrees = 0 ; } } // We will need this only if we get to moving Note objects in assn4. // Note that my rotateBB function is available if we do 2D rotation. int [] get2DBoundingBox() { int [] result = new int [4]; result[0] = x - wide/2 ; result[1] = y - high/2 ; result[2] = x + wide/2 ; result[3] = y + high/2 ; return result; } }