package main; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import javax.swing.JPanel; import java.awt.geom.Rectangle2D; public class Note extends JPanel{ int noTimesClicked = 0; double x; double y; int n; int d; int v; int p; double pitch; int clefChoice; int octavaAndBassoChoice; int spellingChoice; int ratioChoice; int noteHeadChoice = 0; String[] clefs = {"\uf03f", "\uf042", "\uf042", "\uf026"}; String[] octavasAndBassos = {"15", "8", " ", "8", "15"}; String[] acc = {"\uf062","\uf06e", "\uf023"}; float clickAndPlayX1; float clickAndPlayX2; Color color = Color.BLACK; boolean isListening = false; public Note(double x, double y, double p, int v, int pP){ this.x = x; this.y = y; n = (int) (Rise.FIRST_NUM+v-pP); d = (int) (Rise.FIRST_NUM-pP); this.pitch = p + Rise.TRANSPOSE_SCORE * 100.; this.v = v; this.p = pP; this.setOpaque(false); this.setBackground(Color.WHITE); this.setBounds((int) 0, (int) 0,(int) (Rise.PAGE_WIDTH*Rise.ZOOM), (int) (Rise.PAGE_HEIGHT*Rise.ZOOM)); initializeChoices(); } public void paint(Graphics g){ g.setColor(color); Graphics2D g2 = (Graphics2D) g; this.setBounds((int) 0, (int) 0,(int) (Rise.PAGE_WIDTH*Rise.ZOOM), (int) (Rise.PAGE_HEIGHT*Rise.ZOOM)); g2.translate(Rise.PAGE_MARGIN*Rise.ZOOM, Rise.PAGE_MARGIN*Rise.ZOOM); g2.scale(Rise.ZOOM, Rise.ZOOM); FontRenderContext frc = g2.getFontRenderContext(); Font fontMusic = new Font("Maestro", Font.PLAIN, (int) Rise.FONT); fontMusic.deriveFont(Rise.FONT); Font fontNumbers = new Font("Liberation Serif", Font.PLAIN, (int) Math.round(Rise.FONT/1.714)); Font fontOBSigns = new Font("Liberation Serif", Font.PLAIN, (int) Math.round(Rise.FONT/2.4)); TextLayout note = new TextLayout("\uf0cf", fontMusic, frc); TextLayout staff = new TextLayout("\uf03d\uf03d", fontMusic, frc); TextLayout ledgerLine = new TextLayout("\uf02d", fontMusic, frc); g2.setFont(fontMusic); FontMetrics fontMetrics = g2.getFontMetrics(); double noteWidth = fontMetrics.stringWidth("\uf0cf"); double staffWidth = fontMetrics.stringWidth("\uf03d"); double ledgerWidth = fontMetrics.stringWidth("\uf02d"); double staffSpace = Rise.FONT/8.; float noteX = (float) (x*Rise.IMAGE_WIDTH - noteWidth/2. /*- ((1./(Rise.VOICES-1))*(p-v)/p)*Rise.IMAGE_WIDTH*Rise.X_DIV*/); float noteY = (float) y*Rise.IMAGE_HEIGHT; float toneX1 = (float) (x*Rise.IMAGE_WIDTH - ((1./(Rise.VOICES-1))*(p-v)/p)*Rise.IMAGE_WIDTH*Rise.X_DIV); float toneX2; if (p != Rise.VOICES-1) { toneX2 = (float) (x*Rise.IMAGE_WIDTH + ((1./(Rise.VOICES-1))*v/(p+1))*Rise.IMAGE_WIDTH*Rise.X_DIV); } else { toneX2 = (float) (x*Rise.IMAGE_WIDTH + ((1./(Rise.VOICES-1))*.25)*Rise.IMAGE_WIDTH*Rise.X_DIV); } float toneY1 = (float) (noteY - note.getBounds().getMaxY()/3); float toneY2 = (float) (noteY - note.getBounds().getMinY()/3); //System.out.println("notes " + ((1./(Rise.VOICES-1))*(p-v)/p) + " " + ((1./(Rise.VOICES-1))*v/(p+1))); g2.setColor(new Color(200, 200, 200)); g2.fill(new Rectangle2D.Float(toneX1, toneY1, toneX2-toneX1, toneY2-toneY1)); g2.setColor(color); clickAndPlayX1 = toneX1; clickAndPlayX2 = toneX2; note.draw(g2,noteX,noteY); double accWidth = fontMetrics.stringWidth(acc[getAcc((int) (Math.round(pitch/100.)%12))]); TextLayout accidental = new TextLayout(acc[getAcc((int) (Math.round(pitch/100.)%12))], fontMusic, frc); accidental.draw(g2,(float) (noteX-accWidth-2),(float) y*Rise.IMAGE_HEIGHT); int notePosition = getNotePosition((int) (Math.round(pitch/100.)%12)); int centDeviation = (int) Math.round((pitch/100. - Math.round(pitch/100.))*100.); TextLayout centDeviationText; if (centDeviation >= 0) { centDeviationText = new TextLayout("+" + String.valueOf(centDeviation), fontNumbers, frc); } else { centDeviationText = new TextLayout(String.valueOf(centDeviation), fontNumbers, frc); } for (int i = d; i > 0; i--) { if (Math.round((float) d/i) == (float) d/i && Math.round((float) n/i) == (float) n/i) { n = n/i; d = d/i; } } TextLayout ratioText = new TextLayout(String.valueOf(n) + "/" + String.valueOf(d), fontNumbers, frc); int stepsToLowestC = 0; int addOctaves = 0; int stepsToClef = 0; if (clefChoice == 0){ stepsToLowestC = -11; stepsToClef = 6; } else if (clefChoice == 1){ stepsToLowestC = -15; stepsToClef = 6; } else if (clefChoice == 2){ stepsToLowestC = -17; stepsToClef = 4; } else if (clefChoice == 3){ stepsToLowestC = -23; stepsToClef = 2; } if (octavaAndBassoChoice == 0){ stepsToLowestC = stepsToLowestC+14; } else if (octavaAndBassoChoice == 1){ stepsToLowestC = stepsToLowestC+7; } else if (octavaAndBassoChoice == 2){ } else if (octavaAndBassoChoice == 3){ stepsToLowestC = stepsToLowestC-7; } else if (octavaAndBassoChoice == 4){ stepsToLowestC = stepsToLowestC-14; } addOctaves = (int) (Math.round(pitch/100.)/12)*7; float staffX = (float) (x*Rise.IMAGE_WIDTH - 1.5*staffWidth /*- ((1./(Rise.VOICES-1))*(p-v)/p)*Rise.IMAGE_WIDTH*Rise.X_DIV*noteHeadChoice*/); float staffY = (float) (y*Rise.IMAGE_HEIGHT+(stepsToLowestC+notePosition+addOctaves)*staffSpace); staff.draw(g2, staffX, staffY); float clefX = (float) (x*Rise.IMAGE_WIDTH - 1.5*staffWidth /*- ((1./(Rise.VOICES-1))*(p-v)/p)*Rise.IMAGE_WIDTH*Rise.X_DIV*noteHeadChoice*/); float clefY = (float) (y*Rise.IMAGE_HEIGHT+((stepsToLowestC-stepsToClef)+notePosition+addOctaves)*staffSpace); TextLayout clef = new TextLayout(clefs[clefChoice], fontMusic, frc); clef.draw(g2, clefX, clefY); TextLayout octavaAndBasso = new TextLayout(octavasAndBassos[octavaAndBassoChoice], fontOBSigns, frc); if (octavaAndBassoChoice < 2){ octavaAndBasso.draw(g2,(float) (clefX+clef.getVisibleAdvance()/2.-octavaAndBasso.getAdvance()/2),(float) (clefY+clef.getBounds().getMaxY()-octavaAndBasso.getBounds().getMinY())); } else if (octavaAndBassoChoice < 3){ } else if(octavaAndBassoChoice < 5){ if (clefChoice == 3 && octavaAndBassoChoice == 3) { octavaAndBasso.draw(g2,(float) (clefX+clef.getVisibleAdvance()/2.-octavaAndBasso.getAdvance()/16.),(float) (clefY+clef.getBounds().getMinY())); } else if (clefChoice == 3 && octavaAndBassoChoice == 4) { octavaAndBasso.draw(g2,(float) (clefX+clef.getVisibleAdvance()/2.-octavaAndBasso.getAdvance()/4.),(float) (clefY+clef.getBounds().getMinY())); } else { octavaAndBasso.draw(g2,(float) (clefX+clef.getVisibleAdvance()/2.-octavaAndBasso.getAdvance()/2),(float) (clefY+clef.getBounds().getMinY())); } } if (noteY-staffY >= staffSpace*2){ float ledgerLineX = (float) (x*Rise.IMAGE_WIDTH - ledgerWidth/2.); float ledgerLineY = (float) (staffY+staffSpace*2); while (ledgerLineY <= noteY){ ledgerLine.draw(g2, ledgerLineX, ledgerLineY); ledgerLineY = (float) (ledgerLineY+staffSpace*2); } } if (staffY-noteY >= staffSpace*10){ float ledgerLineX = (float) (x*Rise.IMAGE_WIDTH - ledgerWidth/2.); float ledgerLineY = (float) (staffY-staffSpace*10); while (ledgerLineY >= noteY){ ledgerLine.draw(g2, ledgerLineX, ledgerLineY); ledgerLineY = (float) (ledgerLineY-staffSpace*2); } } if (noteY >= staffY-staffSpace*6){ centDeviationText.draw(g2, (float) (noteX-centDeviationText.getAdvance()/4.), (float) (staffY-staffSpace*9)); } else { centDeviationText.draw(g2, (float) (noteX-centDeviationText.getAdvance()/4.), (float) (noteY-staffSpace*3)); } if (ratioChoice == 0) { if (noteY <= staffY-staffSpace*2){ ratioText.draw(g2, (float) (noteX-ratioText.getAdvance()/4.), (float) (staffY+staffSpace*1+ratioText.getAscent())); } else { ratioText.draw(g2, (float) (noteX-ratioText.getAdvance()/4.), (float) (noteY+staffSpace*3+ratioText.getAscent())); } } } public int getNotePosition(int mN) { int notePosition = 0; if (spellingChoice == 0) { int modNote = mN; switch(modNote) { case 0 : notePosition = 0; break; case 1 : notePosition = 0; break; case 2 : notePosition = 1; break; case 3 : notePosition = 1; break; case 4 : notePosition = 2; break; case 5 : notePosition = 3; break; case 6 : notePosition = 3; break; case 7 : notePosition = 4; break; case 8 : notePosition = 4; break; case 9 : notePosition = 5; break; case 10 : notePosition = 5; break; case 11: notePosition = 6; break; case 12: notePosition = 7; break; } } else if (spellingChoice == 1){ int modNote = mN; switch(modNote) { case 0 : notePosition = 0; break; case 1 : notePosition = 1; break; case 2 : notePosition = 1; break; case 3 : notePosition = 2; break; case 4 : notePosition = 2; break; case 5 : notePosition = 3; break; case 6 : notePosition = 4; break; case 7 : notePosition = 4; break; case 8 : notePosition = 5; break; case 9 : notePosition = 5; break; case 10 : notePosition = 6; break; case 11: notePosition = 6; break; case 12: notePosition = 7; break; } } return notePosition; } public int getAcc(int mN) { int accidental = 1; if (spellingChoice == 0){ int modNote = mN; switch(modNote) { case 0 : accidental = 1; break; case 1 : accidental = 2; break; case 2 : accidental = 1; break; case 3 : accidental = 2; break; case 4 : accidental = 1; break; case 5 : accidental = 1; break; case 6 : accidental = 2; break; case 7 : accidental = 1; break; case 8 : accidental = 2; break; case 9 : accidental = 1; break; case 10 : accidental = 2; break; case 11: accidental = 1; break; case 12: accidental = 1; break; } } if (spellingChoice == 1){ int modNote = mN; switch(modNote) { case 0 : accidental = 1; break; case 1 : accidental = 0; break; case 2 : accidental = 1; break; case 3 : accidental = 0; break; case 4 : accidental = 1; break; case 5 : accidental = 1; break; case 6 : accidental = 0; break; case 7 : accidental = 1; break; case 8 : accidental = 0; break; case 9 : accidental = 1; break; case 10 : accidental = 0; break; case 11: accidental = 1; break; case 12: accidental = 1; break; } } return accidental; } public void initializeChoices(){ spellingChoice = 1; ratioChoice = 0; int stepsToLowestC = 0; int addOctaves = 0; double staffSpace = Rise.FONT/8.; float noteY = (float) y*Rise.IMAGE_HEIGHT; int notePosition = getNotePosition((int) (Math.round(pitch/100.)%12)); float min = 500000; for (int c = 0; c < 4; c++){ int oBStart = 0; int oBMax = 0; if (c == 0) { oBStart = 0; oBMax = 3; } else if (c < 3) { oBStart = 2; oBMax = 3; } else if (c < 4) { oBStart = 2; oBMax = 5; } for (int oB = oBStart; oB < oBMax; oB++){ if (c == 0){ stepsToLowestC = -11; } else if (c == 1){ stepsToLowestC = -15; } else if (c == 2){ stepsToLowestC = -17; } else if (c == 3){ stepsToLowestC = -23; } if (oB == 0){ stepsToLowestC = stepsToLowestC+14; } else if (oB == 1){ stepsToLowestC = stepsToLowestC+7; } else if (oB == 2){ } else if (oB == 3){ stepsToLowestC = stepsToLowestC-7; } else if (oB == 4){ stepsToLowestC = stepsToLowestC-14; } addOctaves = (int) (Math.round(pitch/100.)/12)*7; float staffY = (float) (y*Rise.IMAGE_HEIGHT+(stepsToLowestC+notePosition+addOctaves)*staffSpace); if (Math.abs((staffY-4*staffSpace)-noteY) < min){ clefChoice = c; octavaAndBassoChoice = oB; min = (float) Math.abs((staffY-4*staffSpace)-noteY); } } } } public int testSelect(float x1, float y1, float x2, float y2){ if ((float) (Rise.PAGE_MARGIN*Rise.ZOOM+x*Rise.IMAGE_WIDTH*Rise.ZOOM) > x1 && (float) (Rise.PAGE_MARGIN*Rise.ZOOM+x*Rise.IMAGE_WIDTH*Rise.ZOOM) < x2 && (float) (Rise.PAGE_MARGIN*Rise.ZOOM+y*Rise.IMAGE_HEIGHT*Rise.ZOOM) > y1 && (float) (Rise.PAGE_MARGIN*Rise.ZOOM+y*Rise.IMAGE_HEIGHT*Rise.ZOOM) < y2){ color = Color.BLUE; isListening = true; return 1; } else { color = Color.BLACK; isListening = false; return 0; } } public int testSelectClickAndPlay(float xMouse, float yMouse){ if ((Rise.PAGE_MARGIN*Rise.ZOOM + clickAndPlayX1*Rise.ZOOM) < xMouse && (Rise.PAGE_MARGIN*Rise.ZOOM + clickAndPlayX2*Rise.ZOOM) > xMouse && (float) (Rise.PAGE_MARGIN*Rise.ZOOM+(y)*Rise.IMAGE_HEIGHT*Rise.ZOOM + 10*Rise.ZOOM) > yMouse && (float) (Rise.PAGE_MARGIN*Rise.ZOOM+(y)*Rise.IMAGE_HEIGHT*Rise.ZOOM - 10*Rise.ZOOM) < yMouse){ color = Color.BLUE; isListening = true; //double toReturn = (xMouse - Rise.PAGE_MARGIN*Rise.ZOOM)/(Rise.IMAGE_WIDTH*Rise.ZOOM); //System.out.println((xMouse) + " " + (clickAndPlayX1*Rise.ZOOM) + " " + (clickAndPlayX2*Rise.ZOOM) + " " + yMouse + " " + (Rise.PAGE_MARGIN*Rise.ZOOM+y*Rise.IMAGE_HEIGHT*Rise.ZOOM)); //System.out.println(toReturn); return 1; } else { color = Color.BLACK; isListening = false; return 0; } } }