jm.gui.sketch.SketchScoreArea Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmusic Show documentation
Show all versions of jmusic Show documentation
JMusic - Java Music Library
The newest version!
/*
:42 2001
Copyright (C) 2000 Andrew Sorensen & Andrew Brown
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or any
later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package jm.gui.sketch;
import jm.JMC;
import jm.music.data.Note;
import jm.music.data.Part;
import jm.music.data.Phrase;
import jm.music.data.Score;
import jm.music.tools.Mod;
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
import java.util.Vector;
public class SketchScoreArea extends Canvas implements JMC, KeyListener, MouseListener, MouseMotionListener {
//attributes
private Score score;
private int scoreChannels;
private int currentChannel;
private int oldY = 0;
private Color[] theColors = new Color[10];
private int maxWidth;
//private int maxParts;
private double beatWidth;
private int x, y;
private int newWidth = 650;
private Vector drawPoints = new Vector();
private int myHeight = 127;
private SketchScore sc;
public SketchScoreArea(Score score, int maxWidth, double beatWidth) {
super();
this.score = score;
scoreChannels = score.size();
currentChannel = scoreChannels;
this.maxWidth = maxWidth;
this.beatWidth = beatWidth;
//this.maxParts = score.size();
this.setSize(maxWidth, myHeight);
this.score = score;
this.maxWidth = maxWidth;
//register the keyboard listener
this.addKeyListener(this);
this.addMouseListener(this);
this.addMouseMotionListener(this);
this.setBackground(new Color(250, 250, 250));
//set up a set of colours to use
for (int i = 0; i < 10; i++) {
Color colour = new Color((int) (Math.random() * 256),
(int) (Math.random() * 256),
(int) (Math.random() * 256));
theColors[i] = colour;
}
}
static void swap(double[][] storer, int i, int j) {
double temp;
for (int a = 0; a < 3; a++) {
temp = storer[i][a];
storer[i][a] = storer[j][a];
storer[j][a] = temp;
}
}
/**
* Update the beatWidth of the panel
*/
public void setBeatWidth(double beatWidth) {
this.beatWidth = beatWidth;
}
/**
* Update the score of this panel
*/
public void setScore(Score score) {
this.score = score;
}
/**
* Report on the set height of this panel
*/
public int getHeight() {
return myHeight;
}
/**
* Register a sketch frame.
*/
public void setSketchScore(SketchScore sc) {
this.sc = sc;
}
/*
* Returns the starting and then maximum panel width
*/
public int getNewWidth() {
return newWidth;
}
/**
* Draw the panel
*/
public void paint(Graphics g) {
score.clean(); // erase any empty data elements
//Paint each phrase in turn
Enumeration enum1 = score.getPartList().elements();
int i = 0;
// resize
//if( score.getEndTime() > 0.0 && newWidth < (int)(score.getEndTime()* beatWidth)) {
// this.setSize((int)(score.getEndTime()* beatWidth), myHeight);
//} else {
// this.setSize(newWidth, myHeight);
//}
while (enum1.hasMoreElements()) {
Part part = (Part) enum1.nextElement();
//Make each part a different colour
g.setColor(theColors[i % 10]);
i++;
Enumeration enum2 = part.getPhraseList().elements();
while (enum2.hasMoreElements()) {
Phrase phrase = (Phrase) enum2.nextElement();
Enumeration enum3 = phrase.getNoteList().elements();
double oldStartTime = phrase.getStartTime();
while (enum3.hasMoreElements()) {
Note aNote = (Note) enum3.nextElement();
// avoid rests and draw notes
int currNote = -1;
if (aNote.getPitchType() == Note.MIDI_PITCH) currNote = aNote.getPitch();
else currNote = Note.freqToMidiPitch(aNote.getFrequency());
if (currNote != REST) {
int x = 127 - currNote;
int y = (int) Math.round(aNote.getDuration() * beatWidth);
int oldY = (int) Math.round(oldStartTime * beatWidth);
g.drawLine(oldY, x, oldY + y, x);
}
oldStartTime += aNote.getRhythmValue();
}
}
}
// draw new arc
g.setColor(Color.black);
Enumeration drawEnum = drawPoints.elements();
while (drawEnum.hasMoreElements()) {
int x1 = ((Integer) (drawEnum.nextElement())).intValue();
int y1 = ((Integer) (drawEnum.nextElement())).intValue();
int x2 = ((Integer) (drawEnum.nextElement())).intValue();
int y2 = ((Integer) (drawEnum.nextElement())).intValue();
//System.out.println("Values are "+x1+" "+y1+" "+x2+" "+y2);
g.drawLine(x1, y1, x2, y2);
}
}
// key listener stubs
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == '\b') {
if (score.getPart(0).size() < 1) return;
Vector v = score.getPartList();
v.removeElementAt(v.size() - 1); // last part
if (sc == null) {
repaint();
} else sc.update();
newWidth = 50;
}
}
// Mouse Listener stubs
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
//mouseMotionListener stubs
public void mouseMoved(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
x = e.getX();
y = e.getY();
}
public void mouseDragged(MouseEvent e) {
// start loc
drawPoints.addElement(new Integer(x));
drawPoints.addElement(new Integer(y));
// current loc
drawPoints.addElement(new Integer(e.getX()));
drawPoints.addElement(new Integer(e.getY()));
// update old locations
x = e.getX();
y = e.getY();
// check if off the canvas
if (e.getX() > (int) (score.getEndTime() * beatWidth) && e.getX() > newWidth) newWidth = e.getX();
// paint
repaint();
}
public void mouseReleased(MouseEvent e) {
//System.out.println(e.getModifiers());
// convert line to phrase then add to the score
if (drawPoints.size() > 0) {
if (e.getModifiers() == 24) {
convertLineToPhrase(true);
} // option key held down?
else convertLineToPhrase(false);
}
drawPoints.removeAllElements();
newWidth = 50;
repaint();
}
private void convertLineToPhrase(boolean hiRes) {
Phrase phr = null;
double[][] storer = new double[drawPoints.size() / 4][3];
Enumeration drawEnum = drawPoints.elements();
int counter = 0;
while (drawEnum.hasMoreElements()) {
int x1 = ((Integer) (drawEnum.nextElement())).intValue();
int y1 = ((Integer) (drawEnum.nextElement())).intValue();
int x2 = ((Integer) (drawEnum.nextElement())).intValue();
int y2 = ((Integer) (drawEnum.nextElement())).intValue();
//System.out.println("Values are "+x1/beatWidth+" "+y1 /beatWidth+" "+x2 /beatWidth+" "+y2 /beatWidth);
if (hiRes) { // was the option key held down
// fine grade
for (int i = 0; i < Math.abs(y1 - y2); i++) {
storer[counter][0] = (double) (((Integer) drawPoints.elementAt(counter * 4)).
intValue()) / beatWidth +
((double) Math.abs(x2 - x1) / beatWidth / (double) (Math.abs(y1 - y2)) + 1.0) /
(Math.abs(y1 - y2) + 1); //onset time
if ((int) ((Integer) drawPoints.elementAt(counter * 4)).intValue() >
(int) ((Integer) drawPoints.elementAt(counter * 4 + 2)).intValue()) {
//revised onset time for drawing backwards
storer[counter][0] = (double) (((Integer) drawPoints.elementAt(counter * 4 + 2)).
intValue()) / beatWidth / (double) (Math.abs(y1 - y2)) + 1.0;
}
//pitch
storer[counter][1] = (double) (127 - y1 + i);
//duration
storer[counter][2] = (double) Math.abs(x2 - x1) / beatWidth /
(double) (Math.abs(y1 - y2)) + 1.0;
}
} else {
// course grade
storer[counter][0] = (double) (((Integer) drawPoints.elementAt(counter * 4)).
intValue()) / beatWidth; //onset time
if ((int) ((Integer) drawPoints.elementAt(counter * 4)).intValue() >
(int) ((Integer) drawPoints.elementAt(counter * 4 + 2)).intValue()) {
//revised onset time for drawing backwards
storer[counter][0] = (double) (((Integer) drawPoints.elementAt(counter * 4 + 2)).
intValue()) / beatWidth;
}
storer[counter][1] = (double) (127 - y1); //pitch
storer[counter][2] = (double) Math.abs(x2 - x1) / beatWidth; //duration
}
counter++;
}
// sort notes into onset order
quickSort(storer, 0, storer.length - 1);
// put notes into a phrase
if (drawPoints.size() > 0) phr = new Phrase(storer[0][0]);
for (int i = 0; i < storer.length - 1; i++) {
// prevent out of range notes being generated at the edges
if (storer[i][1] < 0) storer[i][1] = 0;
if (storer[i][1] > 127) storer[i][1] = 127;
Note n = new Note((int) storer[i][1], storer[i + 1][0] - storer[i][0]);
// avoid unnecessary repeat notes
if (i > 0 && n.getPitchType() == Note.MIDI_PITCH &&
((Note) (phr.getNoteList().lastElement())).getPitchType() == Note.MIDI_PITCH) {
if (phr.size() > 0 && n.getPitch() ==
((Note) (phr.getNoteList().lastElement())).getPitch()) {
Mod.append(((Note) (phr.getNoteList().lastElement())), n);
} else {
phr.addNote(n);
}
} else phr.addNote(n);
}
// last note
if (storer[storer.length - 1][1] < 0) storer[storer.length - 1][1] = 0;
if (storer[storer.length - 1][1] > 127) storer[storer.length - 1][1] = 127;
Note n = new Note((int) storer[storer.length - 1][1], storer[storer.length - 1][2]);
n.setDuration(storer[storer.length - 1][2]);
phr.addNote(n);
// add phrase to the score as a new part
if (phr != null) {
currentChannel++;
if (currentChannel > 15) currentChannel = scoreChannels;
Part p = new Part("Sketch Part", 0, currentChannel);
p.addPhrase(phr);
score.addPart(p);
}
}
private void quickSort(double[][] storer, int left, int right) {
int i, last;
if (left >= right) return; // already sorted
swap(storer, left, (int) (Math.random() * (right - left)) + left); // choose new pivot point
last = left;
for (i = left + 1; i <= right; i++) {
if (storer[i][0] <= storer[left][0]) swap(storer, ++last, i);
}
swap(storer, left, last); // restore pivot
quickSort(storer, left, last - 1);
quickSort(storer, last + 1, right);
}
}