Java swing实现支持录音等功能的钢琴程序
程序员文章站
2023-12-21 10:11:31
今天给大家介绍一下java实现钢琴的小程序,程序虽小,功能挺多,支持循环播放,录音等功能,首先简单介绍下源码结构:
先看看钢琴界面实现,添加相应滴监听事件:...
今天给大家介绍一下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); } }); // listener for column changes lsm = table.getcolumnmodel().getselectionmodel(); lsm.addlistselectionlistener(new listselectionlistener() { public void valuechanged(listselectionevent e) { listselectionmodel sm = (listselectionmodel) e.getsource(); if (!sm.isselectionempty()) { cc.col = sm.getminselectionindex(); } programchange(cc.col*nrows+cc.row); } }); table.setpreferredscrollableviewportsize(new dimension(ncols*110, 200)); table.setcellselectionenabled(true); table.setcolumnselectionallowed(true); for (int i = 0; i < names.length; i++) { tablecolumn column = table.getcolumn(names[i]); column.setpreferredwidth(110); } table.setautoresizemode(table.auto_resize_off); jscrollpane sp = new jscrollpane(table); sp.setverticalscrollbarpolicy(sp.vertical_scrollbar_never); sp.sethorizontalscrollbarpolicy(sp.horizontal_scrollbar_always); add(sp); } public dimension getpreferredsize() { return new dimension(800,170); } public dimension getmaximumsize() { return new dimension(800,170); } private void programchange(int program) { if (instruments != null) { synthesizer.loadinstrument(instruments[program]); } cc.channel.programchange(program); if (record) { createshortevent(program, program); } } } /** * a collection of midi controllers. */ class controls extends jpanel implements actionlistener, changelistener, itemlistener { public jbutton recordb; jmenu menu; int filenum = 0; public controls() { setlayout(new boxlayout(this, boxlayout.y_axis)); setborder(new emptyborder(5,10,5,10)); jpanel p = new jpanel(); p.setlayout(new boxlayout(p, boxlayout.x_axis)); velos = createslider("velocity", p); press = createslider("pressure", p); revbs = createslider("reverb", p); // create a slider with a 14-bit range of values for pitch-bend bends = create14bitslider("bend", p); p.add(box.createhorizontalstrut(10)); add(p); p = new jpanel(); p.setborder(new emptyborder(10,0,10,0)); p.setlayout(new boxlayout(p, boxlayout.x_axis)); jcombobox combo = new jcombobox(); combo.setpreferredsize(new dimension(120,25)); combo.setmaximumsize(new dimension(120,25)); for (int i = 1; i <= 16; i++) { combo.additem("channel " + string.valueof(i)); } combo.additemlistener(this); p.add(combo); p.add(box.createhorizontalstrut(20)); mutecb = createcheckbox("mute", p); solocb = createcheckbox("solo", p); monocb = createcheckbox("mono", p); //sustcb = createcheckbox("sustain", p); createbutton("all notes off", p); p.add(box.createhorizontalstrut(10)); p.add(mouseovercb); p.add(box.createhorizontalstrut(10)); recordb = createbutton("record...", p); add(p); } public jbutton createbutton(string name, jpanel p) { jbutton b = new jbutton(name); b.addactionlistener(this); p.add(b); return b; } private jcheckbox createcheckbox(string name, jpanel p) { jcheckbox cb = new jcheckbox(name); cb.additemlistener(this); p.add(cb); return cb; } private jslider createslider(string name, jpanel p) { jslider slider = new jslider(jslider.horizontal, 0, 127, 64); slider.addchangelistener(this); titledborder tb = new titledborder(new etchedborder()); tb.settitle(name + " = 64"); slider.setborder(tb); p.add(slider); p.add(box.createhorizontalstrut(5)); return slider; } private jslider create14bitslider(string name, jpanel p) { jslider slider = new jslider(jslider.horizontal, 0, 16383, 8192); slider.addchangelistener(this); titledborder tb = new titledborder(new etchedborder()); tb.settitle(name + " = 8192"); slider.setborder(tb); p.add(slider); p.add(box.createhorizontalstrut(5)); return slider; } public void statechanged(changeevent e) { jslider slider = (jslider) e.getsource(); int value = slider.getvalue(); titledborder tb = (titledborder) slider.getborder(); string s = tb.gettitle(); tb.settitle(s.substring(0, s.indexof('=')+1) + s.valueof(value)); if (s.startswith("velocity")) { cc.velocity = value; } else if (s.startswith("pressure")) { cc.channel.setchannelpressure(cc.pressure = value); } else if (s.startswith("bend")) { cc.channel.setpitchbend(cc.bend = value); } else if (s.startswith("reverb")) { cc.channel.controlchange(reverb, cc.reverb = value); } slider.repaint(); } public void itemstatechanged(itemevent e) { if (e.getsource() instanceof jcombobox) { jcombobox combo = (jcombobox) e.getsource(); cc = channels[combo.getselectedindex()]; cc.setcomponentstates(); } else { jcheckbox cb = (jcheckbox) e.getsource(); string name = cb.gettext(); if (name.startswith("mute")) { cc.channel.setmute(cc.mute = cb.isselected()); } else if (name.startswith("solo")) { cc.channel.setsolo(cc.solo = cb.isselected()); } else if (name.startswith("mono")) { cc.channel.setmono(cc.mono = cb.isselected()); } else if (name.startswith("sustain")) { cc.sustain = cb.isselected(); cc.channel.controlchange(sustain, cc.sustain ? 127 : 0); } } } public void actionperformed(actionevent e) { jbutton button = (jbutton) e.getsource(); if (button.gettext().startswith("all")) { for (int i = 0; i < channels.length; i++) { channels[i].channel.allnotesoff(); } for (int i = 0; i < keys.size(); i++) { ((key) keys.get(i)).setnotestate(off); } } else if (button.gettext().startswith("record")) { if (recordframe != null) { recordframe.tofront(); } else { recordframe = new recordframe(); } } } } // end class controls /** * a frame that allows for midi capture & saving the captured data. */ class recordframe extends jframe implements actionlistener, metaeventlistener { public jbutton recordb, playb, saveb; vector tracks = new vector(); defaultlistmodel listmodel = new defaultlistmodel(); tablemodel datamodel; jtable table; public recordframe() { super("midi capture"); addwindowlistener(new windowadapter() { public void windowclosing(windowevent e) {recordframe = null;} }); sequencer.addmetaeventlistener(this); try { sequence = new sequence(sequence.ppq, 10); } catch (exception ex) { ex.printstacktrace(); } jpanel p1 = new jpanel(new borderlayout()); jpanel p2 = new jpanel(); p2.setborder(new emptyborder(5,5,5,5)); p2.setlayout(new boxlayout(p2, boxlayout.x_axis)); recordb = createbutton("record", p2, true); playb = createbutton("play", p2, false); saveb = createbutton("save...", p2, false); getcontentpane().add("north", p2); final string[] names = { "channel #", "instrument" }; datamodel = new abstracttablemodel() { public int getcolumncount() { return names.length; } public int getrowcount() { return tracks.size();} public object getvalueat(int row, int col) { if (col == 0) { return ((trackdata) tracks.get(row)).channum; } else if (col == 1) { return ((trackdata) tracks.get(row)).name; } return null; } public string getcolumnname(int col) {return names[col]; } public class getcolumnclass(int c) { return getvalueat(0, c).getclass(); } public boolean iscelleditable(int row, int col) { return false; } public void setvalueat(object val, int row, int col) { if (col == 0) { ((trackdata) tracks.get(row)).channum = (integer) val; } else if (col == 1) { ((trackdata) tracks.get(row)).name = (string) val; } } }; table = new jtable(datamodel); tablecolumn col = table.getcolumn("channel #"); col.setmaxwidth(65); table.sizecolumnstofit(0); jscrollpane scrollpane = new jscrollpane(table); emptyborder eb = new emptyborder(0,5,5,5); scrollpane.setborder(new compoundborder(eb,new etchedborder())); getcontentpane().add("center", scrollpane); pack(); dimension d = toolkit.getdefaulttoolkit().getscreensize(); int w = 210; int h = 160; setlocation(d.width/2 - w/2, d.height/2 - h/2); setsize(w, h); setvisible(true); } public jbutton createbutton(string name, jpanel p, boolean state) { jbutton b = new jbutton(name); b.setfont(new font("serif", font.plain, 10)); b.setenabled(state); b.addactionlistener(this); p.add(b); return b; } public void actionperformed(actionevent e) { jbutton button = (jbutton) e.getsource(); if (button.equals(recordb)) { record = recordb.gettext().startswith("record"); if (record) { track = sequence.createtrack(); starttime = system.currenttimemillis(); // add a program change right at the beginning of // the track for the current instrument createshortevent(program,cc.col*8+cc.row); recordb.settext("stop"); playb.setenabled(false); saveb.setenabled(false); } else { string name = null; if (instruments != null) { name = instruments[cc.col*8+cc.row].getname(); } else { name = integer.tostring(cc.col*8+cc.row); } tracks.add(new trackdata(cc.num+1, name, track)); table.tablechanged(new tablemodelevent(datamodel)); recordb.settext("record"); playb.setenabled(true); saveb.setenabled(true); } } else if (button.equals(playb)) { if (playb.gettext().startswith("play")) { try { sequencer.open(); sequencer.setsequence(sequence); } catch (exception ex) { ex.printstacktrace(); } sequencer.start(); playb.settext("stop"); recordb.setenabled(false); } else { sequencer.stop(); playb.settext("play"); recordb.setenabled(true); } } else if (button.equals(saveb)) { try { file file = new file(system.getproperty("user.dir")); jfilechooser fc = new jfilechooser(file); fc.setfilefilter(new javax.swing.filechooser.filefilter() { public boolean accept(file f) { if (f.isdirectory()) { return true; } return false; } public string getdescription() { return "save as .mid file."; } }); if (fc.showsavedialog(null) == jfilechooser.approve_option) { savemidifile(fc.getselectedfile()); } } catch (securityexception ex) { javasound.showinfodialog(); ex.printstacktrace(); } catch (exception ex) { ex.printstacktrace(); } } } public void meta(metamessage message) { if (message.gettype() == 47) { // 47 is end of track playb.settext("play"); recordb.setenabled(true); } } public void savemidifile(file file) { try { int[] filetypes = midisystem.getmidifiletypes(sequence); if (filetypes.length == 0) { system.out.println("can't save sequence"); } else { if (midisystem.write(sequence, filetypes[0], file) == -1) { throw new ioexception("problems writing to file"); } } } catch (securityexception ex) { javasound.showinfodialog(); } catch (exception ex) { ex.printstacktrace(); } } class trackdata extends object { integer channum; string name; track track; public trackdata(int channum, string name, track track) { this.channum = new integer(channum); this.name = name; this.track = track; } } // end class trackdata } // end class recordframe public static void main(string args[]) { final midisynth midisynth = new midisynth(); midisynth.open(); jframe f = new jframe("midi synthesizer"); f.addwindowlistener(new windowadapter() { public void windowclosing(windowevent e) {system.exit(0);} }); f.getcontentpane().add("center", midisynth); f.pack(); dimension screensize = toolkit.getdefaulttoolkit().getscreensize(); int w = 760; int h = 470; f.setlocation(screensize.width/2 - w/2, screensize.height/2 - h/2); f.setsize(w, h); f.setvisible(true); } }
程序有点长,不全部贴出来了,最下面附上下载地址,可以打包下载,下面来看看运行结果:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。