[英]Issues with midi file in Java
我正在阅读一本Java编程书,并且显示了以下示例:
// chapter 14
import java.awt.*;
import javax.swing.*;
import java.io.*;
import javax.sound.midi.*;
import java.util.*;
import java.awt.event.*;
public class BeatBox { // implements MetaEventListener
JPanel mainPanel;
ArrayList<JCheckBox> checkboxList;
// int bpm = 120;
Sequencer sequencer;
Sequence sequence;
Sequence mySequence = null;
Track track;
JFrame theFrame;
String[] instrumentNames = {"Bass Drum", "Closed Hi-Hat",
"Open Hi-Hat","Acoustic Snare", "Crash Cymbal", "Hand Clap",
"High Tom", "Hi Bongo", "Maracas", "Whistle", "Low Conga",
"Cowbell", "Vibraslap", "Low-mid Tom", "High Agogo",
"Open Hi Conga"};
int[] instruments = {35,42,46,38,49,39,50,60,70,72,64,56,58,47,67,63};
public static void main (String[] args) {
new BeatBox().buildGUI();
}
public void buildGUI() {
theFrame = new JFrame("Cyber BeatBox");
theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BorderLayout layout = new BorderLayout();
JPanel background = new JPanel(layout);
background.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
checkboxList = new ArrayList<JCheckBox>();
Box buttonBox = new Box(BoxLayout.Y_AXIS);
JButton start = new JButton("Start");
start.addActionListener(new MyStartListener());
buttonBox.add(start);
JButton stop = new JButton("Stop");
stop.addActionListener(new MyStopListener());
buttonBox.add(stop);
JButton upTempo = new JButton("Tempo Up");
upTempo.addActionListener(new MyUpTempoListener());
buttonBox.add(upTempo);
JButton downTempo = new JButton("Tempo Down");
downTempo.addActionListener(new MyDownTempoListener());
buttonBox.add(downTempo);
JButton saveIt = new JButton("Serialize It"); // new button
saveIt.addActionListener(new MySendListener());
buttonBox.add(saveIt);
JButton restore = new JButton("Restore"); // new button
restore.addActionListener(new MyReadInListener());
buttonBox.add(restore);
Box nameBox = new Box(BoxLayout.Y_AXIS);
for (int i = 0; i < 16; i++) {
nameBox.add(new Label(instrumentNames[i]));
}
background.add(BorderLayout.EAST, buttonBox);
background.add(BorderLayout.WEST, nameBox);
theFrame.getContentPane().add(background);
GridLayout grid = new GridLayout(16,16);
grid.setVgap(1);
grid.setHgap(2);
mainPanel = new JPanel(grid);
background.add(BorderLayout.CENTER, mainPanel);
for (int i = 0; i < 256; i++) {
JCheckBox c = new JCheckBox();
c.setSelected(false);
checkboxList.add(c);
mainPanel.add(c);
} // end loop
setUpMidi();
theFrame.setBounds(50,50,300,300);
theFrame.pack();
theFrame.setVisible(true);
} // close method
public void setUpMidi() {
try {
sequencer = MidiSystem.getSequencer();
sequencer.open();
// sequencer.addMetaEventListener(this);
sequence = new Sequence(Sequence.PPQ,4);
track = sequence.createTrack();
sequencer.setTempoInBPM(120);
} catch(Exception e) {e.printStackTrace();}
} // close method
/*
public class MyCheckBoxListener implements ItemListener {
public void itemStateChanged(ItemEvent ev) {
// might add real-time removal or addition, probably not because of timing
}
} // close inner class
*/
public void buildTrackAndStart() {
// this will hold the instruments for each vertical column,
// in other words, each tick (may have multiple instruments)
int[] trackList = null;
sequence.deleteTrack(track);
track = sequence.createTrack();
for (int i = 0; i < 16; i++) {
trackList = new int[16];
int key = instruments[i];
for (int j = 0; j < 16; j++ ) {
JCheckBox jc = (JCheckBox) checkboxList.get(j + (16*i));
if ( jc.isSelected()) {
trackList[j] = key;
} else {
trackList[j] = 0;
}
} // close inner
makeTracks(trackList);
} // close outer
track.add(makeEvent(192,9,1,0,15)); // - so we always go to full 16 beats
try {
sequencer.setSequence(sequence);
sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);
sequencer.start();
sequencer.setTempoInBPM(120);
} catch(Exception e) {e.printStackTrace();}
} // close method
//============================================================== inner class listeners
public class MyStartListener implements ActionListener {
public void actionPerformed(ActionEvent a) {
buildTrackAndStart();
}
}
public class MyStopListener implements ActionListener {
public void actionPerformed(ActionEvent a) {
sequencer.stop();
}
}
public class MyUpTempoListener implements ActionListener {
public void actionPerformed(ActionEvent a) {
float tempoFactor = sequencer.getTempoFactor();
sequencer.setTempoFactor((float)(tempoFactor * 1.03));
}
}
public class MyDownTempoListener implements ActionListener {
public void actionPerformed(ActionEvent a) {
float tempoFactor = sequencer.getTempoFactor();
sequencer.setTempoFactor((float)(tempoFactor * .97));
}
}
public class MySendListener implements ActionListener { // new - save
public void actionPerformed(ActionEvent a) {
// make an arraylist of just the STATE of the checkboxes
boolean[] checkboxState = new boolean[256];
for (int i = 0; i < 256; i++) {
JCheckBox check = (JCheckBox) checkboxList.get(i);
if (check.isSelected()) {
checkboxState[i] = true;
}
}
try {
FileOutputStream fileStream = new FileOutputStream(
new File("Checkbox.ser"));
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(checkboxState);
} catch(Exception ex) {
ex.printStackTrace();
}
} // close method
} // close inner class
public class MyReadInListener implements ActionListener { // new - restore
public void actionPerformed(ActionEvent a) {
// read in the thing
boolean[] checkboxState = null;
try {
FileInputStream fileIn = new FileInputStream(
new File("Checkbox.ser"));
ObjectInputStream is = new ObjectInputStream(fileIn);
checkboxState = (boolean[]) is.readObject();
} catch(Exception ex) {ex.printStackTrace();}
// now reset the sequence to be this
for (int i = 0; i < 256; i++) {
JCheckBox check = (JCheckBox) checkboxList.get(i);
if (checkboxState[i]) {
check.setSelected(true);
} else {
check.setSelected(false);
}
}
// now stop sequence and restart
sequencer.stop();
buildTrackAndStart();
} // close method
} // close inner class
//==============================================================
public void makeTracks(int[] list) {
for (int i = 0; i < 16; i++) {
int key = list[i];
if (key != 0) {
track.add(makeEvent(144,9,key, 100, i));
track.add(makeEvent(128,9,key, 100, i + 1));
}
}
}
public MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) {
MidiEvent event = null;
try {
ShortMessage a = new ShortMessage();
a.setMessage(comd, chan, one, two);
event = new MidiEvent(a, tick);
}catch(Exception e) { }
return event;
}
/*
public void meta(MetaMessage message) {
if (message.getType() == 47) {
sequencer.start();
sequencer.setTempoInBPM(bpm);
}
}
*/
} // close class
这是一台简单的beatboc机器,但我不知道为什么我的电脑上似乎坏了。 如果我尝试编译代码,则前3/4行会正常工作,但其他行会发出相同的声音....尤其是马拉卡斯,嗨邦戈,吹口哨...
对于其他在线用户来说,它似乎还可以正常工作,可能是什么问题? 我还在/ lib / audio中安装了豪华声库,但没有任何改变。
我一直在研究同一本书(从Java入手),涵盖了Java 5.0。
如果您使用Java 7, 则已经实现了新的软件合成器 。 该代码不支持通用MIDI音库。
通过将遵循GM准则的音库加载到新的合成器实例中并将其链接到未连接的音序器,可以解决此问题。 这是一个合适的音库 。 但是网络上有一些不同的说法。
这是setupMidi()方法中的代码:
public void setUpMidi() {
try {
sequencer = MidiSystem.getSequencer(false); // returns unconnected sequencer
sequencer.open();
synth = MidiSystem.getSynthesizer(); // return new synth
synth.open();
soundbank = MidiSystem.getSoundbank(new File("32MbGMStereo.sf2"));
synth.loadAllInstruments(soundbank); // load GM soundbank
Receiver synthReceiver = synth.getReceiver();
Transmitter seqTransmitter = sequencer.getTransmitter();
seqTransmitter.setReceiver(synthReceiver); // connect sequencer to synth
sequence = new Sequence(Sequence.PPQ,4);
track = sequence.createTrack();
sequencer.setTempoInBPM(120);
} catch(Exception e) {e.printStackTrace();}
我已经尝试过您的代码。 似乎我的笔记本电脑(HP EliteBook)上的所有设备都可以正常工作。起初我遇到了一个错误,但是发现这是因为我需要以Admin身份运行Eclipse。 但是,我想是在您的书随附的论坛上找到了该解决方案。 参见: http : //forums.oreilly.com/topic/88039-windows-regcreatekeyex-returned-error-code-5/
我唯一注意到的是,如果循环正在运行,并且我检查了其他声音,则通常直到再次单击“开始”按钮时,它们才会播放这些声音。 但是,仅此而已。
我发现了一个类似的话题。 也许对您有用吗? Mac OSX中的Java Midi损坏了吗?
为了刷新模式,在每次选择之后,我建议对您的代码进行更改,如下所示:
public void buildTrack() {
// this will hold the instruments for each vertical column,
// in other words, each tick (may have multiple instruments)
int[] trackList = null;
sequence.deleteTrack(track);
track = sequence.createTrack();
for (int i = 0; i < 16; i++) {
trackList = new int[16];
int key = instruments[i];
for (int j = 0; j < 16; j++ ) {
JCheckBox jc = (JCheckBox) checkboxList.get(j + (16*i));
if ( jc.isSelected()) {
trackList[j] = key;
} else {
trackList[j] = 0;
}
} // close inner
makeTracks(trackList);
} // close outer
track.add(makeEvent(192,9,1,0,15)); // - so we always go to full 16 beats
try {
sequencer.setSequence(sequence);
} catch(Exception e) {e.printStackTrace();}
} // close method
public void buildTrackAndStart() {
try {
buildTrack();
sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);
sequencer.start();
sequencer.setTempoInBPM(120);
} catch(Exception e) {e.printStackTrace();}
} // close method
然后您需要创建一个CheckBoxListener:
public class MyCheckboxListener implements ActionListener {
public void actionPerformed(ActionEvent a) {
buildTrack();
}
}
通过添加以下行,将其添加到您的复选框:
c.addActionListener(new MyCheckboxListener());
对于您的“ for”块,就在“ setupMidi()”之前,如下所示:
for (int i = 0; i < 256; i++) {
JCheckBox c = new JCheckBox();
c.setSelected(false);
c.addActionListener(new MyCheckboxListener());
checkboxList.add(c);
mainPanel.add(c);
} // end loop
那应该可以解决问题!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.