📄 midikeyboard.java
字号:
/*
* MidiKeyboard.java
*
* Simple keyboard user interface class.
*
*/
import java.awt.*;
import java.applet.Applet;
import java.net.*;
import java.util.*;
import java.lang.*;
import midi.*;
/**
* A MIDI keyboard applet.
*
* Supported parameters:
*
* Label Range Meaning
*
* device MIDI device ID* Select MIDI Out device
* numkeys 1 to 128 Number of keys to display
* startkey 0 to 127 MIDI note # of leftmost key
* velocity 1 to 127 Velocity in Note On messages
* channel 0 to 15 MIDI channel for output
* program 0 to 127 Program (patch) number
*
* * Note: the MIDI device ID can vary from 0 up to the number
* of MIDI out deveices installed in the system minus 1
*
*/
public class MidiKeyboard extends java.applet.Applet {
/** default constants */
final int DEFAULT_NUMKEYS = 48; // number of keys (4 octaves)
final int DEFAULT_STARTKEY = 48; // C below middle C
final int DEFAULT_VELOCITY = 64;
final int DEFAULT_CHANNEL = 0;
final int DEFAULT_PROGRAM = 0;
/** the MIDI device this keyboard sends output to */
MidiOutDevice midiOut;
/** number of MIDI out devices detected */
int numDevices = -1;
/** index of MIDI device to open */
int deviceId = 0;
/** number of keys on this keyboard */
int numKeys = DEFAULT_NUMKEYS;
/** number of non-accidental keys */
int numNormals = 0;
/** lowest key */
int startKey = DEFAULT_STARTKEY; // startKey + numKeys <= 128
/** velocity */
int velocity = DEFAULT_VELOCITY;
/** MIDI channel */
int channel = DEFAULT_CHANNEL;
/** MIDI program (i.e. patch) */
int program = DEFAULT_PROGRAM;
/** dimensions of entire keyboard */
int dxKeyboard = 0; // includes right border
int dyKeyboard = 0;
/** dimensions of each type of key */
int dxNormal, dyNormal; // does not include right border
int dxAccidental, dyAccidental; // includes right border
/** flags for keyState array
*/
final int KEY_INDEX_BY_TYPE = 0xFF; // mask to get the index by type (accidental vs. normal)
final int KEY_ACCIDENTAL = 0x100;
final int KEY_DOWN = 0x200;
/** useful information about each key packed into an int
*/
int keyState[];
/** key currently being clicked on by the mouse (one at a time for now) */
int keyDown = -1; // index into keyState or -1 if no key is down
/** standard applet initialization */
public void init() {
// read in the parameters. They are already initialized to default values,
// so don't do anything if they are not specified.
String att;
att = getParameter("device");
if (att != null) {
deviceId = Integer.parseInt(att);
}
att = getParameter("numkeys");
if (att != null) {
numKeys = Integer.parseInt(att);
}
att = getParameter("startkey");
if (att != null) {
startKey = Integer.parseInt(att);
}
att = getParameter("velocity");
if (att != null) {
velocity = Integer.parseInt(att);
}
att = getParameter("channel");
if (att != null) {
channel = Integer.parseInt(att);
}
att = getParameter("program");
if (att != null) {
program = Integer.parseInt(att);
}
// attempt to instantiate the requested MIDI device
numDevices = MidiOutDevice.GetNumDevices();
if (numDevices <= 0) {
System.err.println("No MIDI device available for output");
midiOut = null;
} else if (deviceId < 0 || deviceId >= numDevices) {
System.err.println("Specified MIDI device does not exist");
midiOut = null;
} else {
try {
midiOut = new MidiOutDevice(deviceId);
} catch (MidiException e) {
System.err.println("Error initializing MIDI device");
midiOut = null;
// go ahead just for show...
}
}
// validate the attributess
if (velocity < 0 || velocity > 127) {
System.err.println("Invalid velocity specified; correcting");
velocity = 64;
}
if (channel < 0 || channel > 15) {
System.err.println("Invalid channel specified; correcting");
channel = 0;
}
if (program < 0 || program > 127) {
System.err.println("Invalid program specified; correcting");
program = 0;
}
// there has to be at least one key
if (numKeys <= 0) {
numKeys = 1;
}
// make sure the keyboard starts and ends with a normal key
// so that the display looks reasonably nice
if (IsAccidental(startKey)) {
startKey--; // don't worry, key 0 isn't an accidental
numKeys++; // preserve the original highest key
}
// now check the last key
if (IsAccidental(startKey + numKeys - 1)) {
numKeys++; // don't worry, key 127 isn't an accidental
}
// validate the key numbers
startKey %= 128;
if (startKey + numKeys > 128) {
numKeys = 128 - startKey;
}
// allocate the keyboard state array
keyState = new int[numKeys];
// per key initialization; also, initialize numNormals while we're at it
numNormals = 0;
int numAccidentals = 0;
for (int i = 0; i < numKeys; i++) {
keyState[i] = 0;
if (IsAccidental(startKey + i)) {
keyState[i] |= (KEY_ACCIDENTAL | numAccidentals);
numAccidentals++;
} else {
keyState[i] |= numNormals; // index of normal keys
numNormals++;
}
}
// THIS DOESN'T SEEM TO WORK, so I took it out
// check and adjust the size so there isn't any extra space on the side
//Dimension d = size();
//calcDimensions(d.width, d.height);
//resize(dxKeyboard, dyKeyboard);
}
/** standard applet start method */
public void start() {
if (midiOut != null) {
try {
midiOut.Open();
System.out.println("MIDI device opened");
// set the patch for the channel we'll be using
int message = MidiDevice.MidiProgramChange | channel | (program << 8);
midiOut.Out(message);
} catch (MidiException e) {
System.err.println("Error opening MIDI out");
}
}
}
/** standard applet stop method */
public void stop() {
if (midiOut != null) {
try {
midiOut.Close();
System.out.println("MIDI device closed");
} catch (MidiException e) {
System.err.println("Error closing MIDI out");
}
}
}
/** called when repainting is needed
public void update(Graphics g) {
// no need to erase the background, just call paint
paint(g);
}
/** draw the keyboard */
public void paint(Graphics g) {
// draw the bounding rectangle of the keyboard
g.setColor(Color.black);
g.drawRect(0, 0, dxKeyboard - 1, dyKeyboard - 1);
// Draw all keys in a single loop. This logic paints the keys seamlessly, i.e.,
// no overlapping draw operations
int xn = 0; // x coordinate of normal keys
int xa = -(dxAccidental / 2); // x coordinate of accidentals
int xp = 0; // right x coordinate of preceding key
int dxSkinny; // width of skinny part of normal key
int dyFat = dyNormal - dyAccidental - 1; // height of fat part of normal keys
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -