存贮beatbox

import java.awt.*;
import javax.swing.*;
import javax.sound.midi.*;
import java.util.*;
import java.awt.event.*;
import java.io.*;
public class BeatBox
{
	JPanel mainPanel;
	ArrayList<JCheckBox> checkboxList;//把checkbox存贮在ArrayList中
	Sequencer sequencer;
	Sequence sequence;
	Track track;
	JFrame theFrame;
	//乐器的名称,以String的array维护
	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"};
	//实际的乐器关键字,例如说35是bass,42是Closed Hi-Hat
	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 serializeltButton=new JButton("serializelt");
		serializeltButton.addActionListener(new MySendListener());
		buttonBox.add(serializeltButton);
		JButton restoreButton=new JButton("restore");
		restoreButton.addActionListener(new MyReadInListener());
		buttonBox.add(restoreButton);
		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);
		//创建checkbox组,设定为未勾选的为false并加到ArrayList和面板上
		for(int i=0;i<256;i++)
		{
			JCheckBox c=new JCheckBox();
			c.setSelected(false);
			checkboxList.add(c);
			mainPanel.add(c);
		}
		setUpMidi();
		theFrame.setBounds(50,50,300,300);
		theFrame.pack();
		theFrame.setVisible(true);
	}
	public void setUpMidi()
	{
		try{
			sequencer=MidiSystem.getSequencer();
			sequencer.open();
			sequence=new Sequence(Sequence.PPQ,4);
			track=sequence.createTrack();
			sequencer.setTempoInBPM(120);
		}catch(Exception e){e.printStackTrace();}
	}
	//重在这里,此处会将复选框状态转化为MIDI事件并加到track上
	public void buildTrackAndStart()
	{
		int [] trackList=null;//创建出16个元素的数组来存贮一项乐器的值。如果该节奏应该要演奏,其值会是关键字值,否则值为0
		sequence.deleteTrack(track);//除掉旧的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;
			}
			makeTracks(trackList);//创建此乐器的事件并加到track上
			track.add(makeEvent(176,1,127,0,16));//创建次乐器的事件并加到track上
		}
		track.add(makeEvent(192,9,1,0,15));//确保第16拍有事件,都则beatbox不会重复播放
		try
		{
			sequencer.setSequence(sequence);
			sequencer.setLoopCount(sequencer.LOOP_CONTINUOUSLY);//指定无穷的播放次数
			sequencer.start();
			sequencer.setTempoInBPM(120);
		}catch(Exception e){e.printStackTrace();}
	}
	public class MySendListener implements ActionListener
	{
		public void actionPerformed(ActionEvent a)
		{
			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{
				JFileChooser fileOpen=new JFileChooser();
				fileOpen.showOpenDialog(theFrame);
				FileOutputStream fileStream=new FileOutputStream(fileOpen.getSelectedFile());
				ObjectOutputStream os=new ObjectOutputStream(fileStream);
				os.writeObject(checkboxState);
			}catch(Exception ex)
			{
				ex.printStackTrace();
			}
		}
	}
	public class MyReadInListener implements ActionListener
	{
		public void actionPerformed(ActionEvent a)
		{
			boolean[] checkboxState=null;
			try{
				JFileChooser fileOpen=new JFileChooser();
				fileOpen.showOpenDialog(theFrame);
				FileInputStream fileIn=new FileInputStream(fileOpen.getSelectedFile());
				ObjectInputStream is=new ObjectInputStream(fileIn);
				checkboxState=(boolean[])is.readObject();
			}catch(Exception ex){ex.printStackTrace();}
			for(int i=0;i<256;i++)
			{
				JCheckBox check=(JCheckBox)checkboxList.get(i);
				if(checkboxState[i])
				{
					check.setSelected(true);		
				}else
					check.setSelected(false);
			}
			sequencer.stop();
			buildTrackAndStart();
		}
	}
	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();//节奏因子预设为1.0,每次调整3%
			sequencer.setTempoFactor((float)(tempoFactor*1.03));
		}
	}
	public class MyDownTempoListener implements ActionListener
	{
		public void actionPerformed(ActionEvent a)
		{
			float tempoFactor=sequencer.getTempoFactor();	
			sequencer.setTempoFactor((float)(tempoFactor*0.97));
		}
	}
	//创建某项乐器的所有事件
	public void makeTracks(int [] list)
	{
		for(int i=0;i<16;i++)
		{
			int key=list[i];
			if(key!=0)
			{
				//创建NOTE ON和NOTE OFF事件并加入到track上
				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)
		{e.printStackTrace();}
		return event;
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值