?? midisynth.java
字號:
/* * @(#)MidiSynth.java 1.15 99/12/03 * * Copyright (c) 1999 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */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.15 99/12/03 * @author Brian Lichtenwalter */public class MidiSynth 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 MidiSynth() { 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; } } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public Key getKey(Point point) { for (int i = 0; i < keys.size(); i++) { if (((Key) keys.get(i)).contains(point)) { return (Key) keys.get(i); } } return null; } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; Dimension d = getSize(); g2.setBackground(getBackground()); g2.clearRect(0, 0, d.width, d.height); g2.setColor(Color.white); g2.fillRect(0, 0, 42*kw, kh); for (int i = 0; i < whiteKeys.size(); i++) { Key key = (Key) whiteKeys.get(i); if (key.isNoteOn()) { g2.setColor(record ? pink : jfcBlue); g2.fill(key); } g2.setColor(Color.black); g2.draw(key); } for (int i = 0; i < blackKeys.size(); i++) { Key key = (Key) blackKeys.get(i); if (key.isNoteOn()) { g2.setColor(record ? pink : jfcBlue); g2.fill(key); g2.setColor(Color.black); g2.draw(key); } else { g2.setColor(Color.black); g2.fill(key); } } } } // End class Piano /** * Stores MidiChannel information. */ class ChannelData { MidiChannel channel; boolean solo, mono, mute, sustain; int velocity, pressure, bend, reverb; int row, col, num; public ChannelData(MidiChannel channel, int num) { this.channel = channel; this.num = num; velocity = pressure = bend = reverb = 64; } public void setComponentStates() { table.setRowSelectionInterval(row, row); table.setColumnSelectionInterval(col, col); soloCB.setSelected(solo); monoCB.setSelected(mono); muteCB.setSelected(mute); //sustCB.setSelected(sustain); JSlider slider[] = { veloS, presS, bendS, revbS }; int v[] = { velocity, pressure, bend, reverb }; for (int i = 0; i < slider.length; i++) { TitledBorder tb = (TitledBorder) slider[i].getBorder(); String s = tb.getTitle(); tb.setTitle(s.substring(0, s.indexOf('=')+1)+s.valueOf(v[i])); slider[i].repaint(); } } } // End class ChannelData /** * Table for 128 general MIDI melody instuments. */ class InstrumentsTable extends JPanel { private String names[] = { "Piano", "Chromatic Perc.", "Organ", "Guitar", "Bass", "Strings", "Ensemble", "Brass", "Reed", "Pipe", "Synth Lead", "Synth Pad", "Synth Effects", "Ethnic", "Percussive", "Sound Effects" }; private int nRows = 8; private int nCols = names.length; // just show 128 instruments public InstrumentsTable() { setLayout(new BorderLayout()); TableModel dataModel = new AbstractTableModel() { public int getColumnCount() { return nCols; } public int getRowCount() { return nRows;} public Object getValueAt(int r, int c) { if (instruments != null) { return instruments[c*nRows+r].getName(); } else { return Integer.toString(c*nRows+r); } } public String getColumnName(int c) { return names[c]; } public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } public boolean isCellEditable(int r, int c) {return false;} public void setValueAt(Object obj, int r, int c) {} }; table = new JTable(dataModel); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // Listener for row changes ListSelectionModel lsm = table.getSelectionModel(); lsm.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { ListSelectionModel sm = (ListSelectionModel) e.getSource(); if (!sm.isSelectionEmpty()) { cc.row = sm.getMinSelectionIndex(); } programChange(cc.col*nRows+cc.row); } });
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -