/*
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package xiyou.wangbo;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.sound.midi.*;
import java.util.Vector;
import java.io.File;
import java.io.IOException;
/**
* Illustrates general MIDI melody instruments and MIDI controllers.
*
* @version @(#)MidiSynth.java 1.16 02/02/06
* @author Brian Lichtenwalter
*/
public class JavaProject1 extends JPanel implements ControlContext {
final int PROGRAM = 192;
final int NOTEON = 144;
final int NOTEOFF = 128;
final int SUSTAIN = 64;
final int REVERB = 91;
final int ON = 0, OFF = 1;
final Color jfcBlue = new Color(204, 204, 255);
final Color pink = new Color(255, 175, 175);
Sequencer sequencer;
Sequence sequence;
Synthesizer synthesizer;
Instrument instruments[];
ChannelData channels[];
ChannelData cc; // current channel
JCheckBox mouseOverCB = new JCheckBox("mouseOver", true);
JSlider veloS, presS, bendS, revbS;
JCheckBox soloCB, monoCB, muteCB, sustCB;
Vector keys = new Vector();
Vector whiteKeys = new Vector();
JTable table;
Piano piano;
boolean record;
Track track;
long startTime;
RecordFrame recordFrame;
Controls controls;
public JavaProject1() {
setLayout(new BorderLayout());
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
EmptyBorder eb = new EmptyBorder(5,5,5,5);
BevelBorder bb = new BevelBorder(BevelBorder.LOWERED);
CompoundBorder cb = new CompoundBorder(eb,bb);
p.setBorder(new CompoundBorder(cb,eb));
JPanel pp = new JPanel(new BorderLayout());
pp.setBorder(new EmptyBorder(10,20,10,5));
pp.add(piano = new Piano());
p.add(pp);
p.add(controls = new Controls());
p.add(new InstrumentsTable());
add(p);
}
public void open() {
try {
if (synthesizer == null) {
if ((synthesizer = MidiSystem.getSynthesizer()) == null) {
System.out.println("getSynthesizer() failed!");
return;
}
}
synthesizer.open();
sequencer = MidiSystem.getSequencer();
sequence = new Sequence(Sequence.PPQ, 10);
} catch (Exception ex) { ex.printStackTrace(); return; }
Soundbank sb = synthesizer.getDefaultSoundbank();
if (sb != null) {
instruments = synthesizer.getDefaultSoundbank().getInstruments();
synthesizer.loadInstrument(instruments[0]);
}
MidiChannel midiChannels[] = synthesizer.getChannels();
channels = new ChannelData[midiChannels.length];
for (int i = 0; i < channels.length; i++) {
channels[i] = new ChannelData(midiChannels[i], i);
}
cc = channels[0];
ListSelectionModel lsm = table.getSelectionModel();
lsm.setSelectionInterval(0,0);
lsm = table.getColumnModel().getSelectionModel();
lsm.setSelectionInterval(0,0);
}
public void close() {
if (synthesizer != null) {
synthesizer.close();
}
if (sequencer != null) {
sequencer.close();
}
sequencer = null;
synthesizer = null;
instruments = null;
channels = null;
if (recordFrame != null) {
recordFrame.dispose();
recordFrame = null;
}
}
/**
* given 120 bpm:
* (120 bpm) / (60 seconds per minute) = 2 beats per second
* 2 / 1000 beats per millisecond
* (2 * resolution) ticks per second
* (2 * resolution)/1000 ticks per millisecond, or
* (resolution / 500) ticks per millisecond
* ticks = milliseconds * resolution / 500
*/
public void createShortEvent(int type, int num) {
ShortMessage message = new ShortMessage();
try {
long millis = System.currentTimeMillis() - startTime;
long tick = millis * sequence.getResolution() / 500;
message.setMessage(type+cc.num, num, cc.velocity);
MidiEvent event = new MidiEvent(message, tick);
track.add(event);
} catch (Exception ex) { ex.printStackTrace(); }
}
/**
* Black and white keys or notes on the piano.
*/
class Key extends Rectangle {
int noteState = OFF;
int kNum;
public Key(int x, int y, int width, int height, int num) {
super(x, y, width, height);
kNum = num;
}
public boolean isNoteOn() {
return noteState == ON;
}
public void on() {
setNoteState(ON);
cc.channel.noteOn(kNum, cc.velocity);
if (record) {
createShortEvent(NOTEON, kNum);
}
}
public void off() {
setNoteState(OFF);
cc.channel.noteOff(kNum, cc.velocity);
if (record) {
createShortEvent(NOTEOFF, kNum);
}
}
public void setNoteState(int state) {
noteState = state;
}
} // End class Key
/**
* Piano renders black & white keys and plays the notes for a MIDI
* channel.
*/
class Piano extends JPanel implements MouseListener {
Vector blackKeys = new Vector();
Key prevKey;
final int kw = 16, kh = 80;
public Piano() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(42*kw, kh+1));
int transpose = 24;
int whiteIDs[] = { 0, 2, 4, 5, 7, 9, 11 };
for (int i = 0, x = 0; i < 6; i++) {
for (int j = 0; j < 7; j++, x += kw) {
int keyNum = i * 12 + whiteIDs[j] + transpose;
whiteKeys.add(new Key(x, 0, kw, kh, keyNum));
}
}
for (int i = 0, x = 0; i < 6; i++, x += kw) {
int keyNum = i * 12 + transpose;
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+1));
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+3));
x += kw;
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+6));
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+8));
blackKeys.add(new Key((x += kw)-4, 0, kw/2, kh/2, keyNum+10));
}
keys.addAll(blackKeys);
keys.addAll(whiteKeys);
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseMoved(MouseEvent e) {
if (mouseOverCB.isSelected()) {
Key key = getKey(e.getPoint());
if (prevKey != null && prevKey != key) {
prevKey.off();
}
if (key != null && prevKey != key) {
key.on();
}
prevKey = key;
repaint();
}
}
});
addMouseListener(this);
}
public void mousePressed(MouseEvent e) {
prevKey = getKey(e.getPoint());
if (prevKey != null) {
prevKey.on();
repaint();
}
}
public void mouseReleased(MouseEvent e) {
if (prevKey != null) {
prevKey.off();
repaint();
}
}
public void mouseExited(MouseEvent e) {
if (prevKey != null) {
prevKey.off();
repaint();
prevKey = null;
}