📄 sound.java
字号:
import java.io.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import sun.audio.*;
import java.awt.*;
import javax.sound.sampled.*;
class Sound
{
public static void main(String args[])
{
new ReadFile();
}
}
class ReadFile extends JFrame implements ActionListener//读取文件的头信息
{
int chanels=0,size=0,bitspersample=0,samplespersec=0,avgbytespersec=0;
int tail=0,end=0;
FileInputStream fis=null;
boolean on=true;
JButton b=null;
PlaySound playSound=new PlaySound();//此类用来播放声音
ReadFile()
{
super("WAVE");
byte buf1[]=new byte[4];
byte buf2[]=new byte[2];
File directory=new File("");
boolean hasem=false;
boolean hasfactchunk=true;
String temp=null;
int steps=0;
String s=null;
try
{
s=directory.getCanonicalPath();//获取标准的路径
}
catch(IOException e)
{
}
File f=null;
f=new File(s,"ldh.wav"); //生成文件流
try
{
fis=new FileInputStream(f);//生成文件输入流
}
catch(FileNotFoundException e)//抛出文件找不到的异常
{
System.out.println("Cann't find file!");
System.exit(0);
}
System.out.println("RIFF WAVE Chunk");
try
{
fis.read(buf1);//读出RIFF WAVE CHUNK通道里面的信息
}
catch(IOException e)
{
}
System.out.println("ID="+new String(buf1,0));
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
int size=bytetoint(buf1,4);
System.out.println("SIZE="+size+"bytes");
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
System.out.println("TYPE="+new String(buf1,0));
System.out.println("FORMAT Chunk"); //读出FORMAT CHUNK里面的信息
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
System.out.println("ID="+new String(buf1,0));
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
size=bytetoint(buf1,4);
System.out.println("SIZE="+size+"bytes");
if(size>16)
{
hasem=true;
steps=size-16;
}
try
{
fis.read(buf2);
}
catch(IOException e)
{
}
System.out.println("FORMATTAG="+bytetoint(buf2,2));
try
{
fis.read(buf2);
}
catch(IOException e)
{
}
chanels=bytetoint(buf2,2);
System.out.println("CHANNELS="+chanels);
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
samplespersec=bytetoint(buf1,4);
System.out.println("SAMPLESPERSEC="+samplespersec);
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
avgbytespersec=bytetoint(buf1,4);
System.out.println("AVGBYTESPERSEC="+avgbytespersec);
try
{
fis.read(buf2);
}
catch(IOException e)
{
}
System.out.println("BLOCKALIGN ="+bytetoint(buf2,2));
try
{
fis.read(buf2);
}
catch(IOException e)
{
}
bitspersample=bytetoint(buf2,2);
System.out.println("BITSPERSAMPLE ="+bitspersample);
try
{
if(hasem)
fis.skip(steps);
}
catch(IOException e)
{
}
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
temp=new String(buf1,0);
if(temp.equals("data"))//判断是否有FACT CHUNK这个通道
hasfactchunk=false;
if(hasfactchunk)//如果有FACT CHUNK 这个通道则读出里面的信息
{
System.out.println("FACT CHUNK");
System.out.println("ID="+temp);
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
size=bytetoint(buf1,4);
System.out.println("SIZE ="+size);
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
System.out.println("DATA ="+bytetoint(buf1,4));
}
System.out.println("DATA CHUNK");
if(!hasfactchunk)//如果没有FACT CHUNK 那么就读出DATA CHUNK里面的信息
{
System.out.println("ID="+temp);
}
else
{
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
System.out.println("ID ="+new String(buf1,0));
}
try
{
fis.read(buf1);
}
catch(IOException e)
{
}
end=bytetoint(buf1,4);
System.out.println("SIZE ="+end);
InputStream in=null;
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //在非法关闭的情况下面执行的操作
setSize(512,400); ;
Container contentPane=getContentPane();
contentPane.setLayout(null);//自定义布局管理器
ImageIcon music=new ImageIcon("music.jpg");//定义Jbutton类型的图标按钮
b=new JButton(music);
b.setSize(25,25);//设置按钮的大小 下同
b.setLocation(240,330);//设置按钮在pane中的位置 下同
b.addActionListener(this);//注册监听器
contentPane.add(b);//将按加入到pane中去
show();
byte sound[]=new byte[4];
Robot robot=null;
new PlaySound().run();//播放声音
try
{
robot=new Robot();//一个用与延时的类
}
catch(Exception e)
{
}
while(tail<end)//如果声音没有结束,那么就继续画出波形
{
update();//更新画板中的内容
robot.delay(250);//延时250ms 一秒钟显示4桢画面
}
}
public void paint(Graphics g)//画出波形的程序
{
g.clearRect(0,0,512,330);
if(chanels==1)//是单声道的情况
{
if(bitspersample==4)//判断这个声音的采样位数
{
}
else if(bitspersample==8)
{
}
else if(bitspersample==16)//采样位数是16位
{
byte sound[]=new byte[512];
try
{
fis.read(sound);//从声音数据里面读出512个字节的数据
fis.skip(avgbytespersec/4-512);//向后跳转一段距离,avgbytespersec是美妙采样的字节数
}
catch(IOException e)
{
}
int data[]=new int[128];
data[0]=sound[0];
data[0]=data[0]&0X000000FF;
for(int i=1;i<128;i++)
{
data[i]=sound[4*i-1];
data[i]=data[i]&0X000000FF;
}//从512个字节中取出128个作为节点,并将这128个字节转换为int类型
for(int i=0;i<127;i++)
{
g.drawLine(4*i,328-data[i],4*i+4,328-data[i+1]);
}//根据这128个节点画出相应的波形
tail+=avgbytespersec/4;
}
}
else if(chanels==2)//在双声道的情况下
{
if(bitspersample==4)
{
}
else if(bitspersample==8)
{
}
else if(bitspersample==16)//采样为是16位的情况
{
byte sound[]=new byte[1024];
try
{
fis.read(sound);//读出1024位字节的数据
fis.skip(avgbytespersec/4-1024);//向后跳转一段距离,avgbytespersec是美妙采样的字节数
}
catch(IOException e)
{
}
int data1[]=new int[128];//因为是双声道 所以画出其左声道和右声道的波形
int data2[]=new int[128];
data1[0]=sound[0];
data1[0]=data1[0]&0X000000FF;
data2[0]=sound[1];
data2[0]=data2[0]&0X000000FF;
for(int i=1;i<128;i++)
{
data1[i]=sound[8*i];
data2[i]=sound[8*i+2];
data1[i]=data1[i]&0X000000FF;
data2[i]=data2[i]&0X000000FF;
}//将采样出的byte类型全部转换为int类型
for(int i=0;i<127;i++)
{
g.drawLine(4*i,200-data1[i]/2,4*i+4,200-data1[i+1]/2);
g.drawLine(4*i,200+data2[i]/2,4*i+4,200+data2[i+1]/2);
}//根据采样的int数据画出相应的波形
tail+=avgbytespersec/4;
}
}
}
public void update()
{
repaint();
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b)
{
new Add();
}
}
int bytetoint(byte buf[],int n)//byte类型到int类型的转换
{
int a[]=new int[4],size=0;
for(int i=0;i<n;i++)
{
a[i]=buf[i];
}
if(n==4)//对于是四位字节到int类型的转换
size=(a[3]<<24)&0XFF000000|(a[2]<<16)&0X00FF0000|(a[1]<<8)&0X0000FF00|a[0]&0X000000FF;
else if(n==2)//对于两位字节到int类型的转换
size=(a[1]<<8)&0XFF00|a[0]&0X00FF;
return size;
}
}
class PlaySound extends Thread
{
AudioStream astime=null;
public void run()
{
File directory=new File("");
FileInputStream in=null;
String s=null;
try
{
s=directory.getCanonicalPath();//获取标准的路径
}
catch(IOException e)
{
}
try
{
File f=null;
f=new File(s,"ldh.wav");
in=new FileInputStream(f);//建立声音数据流
astime=new AudioStream(in);
AudioPlayer.player.start(astime);
}
catch(Exception e)
{}
}
}
class Add extends JFrame implements ActionListener
{ JComboBox chooseSound=null;//创建一个下拉菜单
JButton add=null,save=null;//创建一个按钮,当点击该按钮的时候就可以将当前选中的音乐将到文本域里面
JTextField tf=new JTextField();//创建一个文本框,里面可以输入自己编辑的音乐的名字
JTextArea ta=null; //创建一个文本域 里面显示当前组合的音乐的名字
JLabel lb=new JLabel();//标签
String choices[]={"1.wav","2.wav","3.wav","4.wav","5.wav","6.wav"};//里面是可以组合的音乐的名字
int index=0;
String s[]=new String[10];
Add()
{
super("File");
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);//意外关闭的情况下进行的操作
setSize(400,400); ;
Container contentPane=getContentPane();
contentPane.setLayout(null);//设子布局格式为自定义
chooseSound=new JComboBox(choices);//生成下拉菜单
add=new JButton("ADD");//生成添加按钮
save=new JButton("SAVE");//生成保存按钮
tf.setText("New File");//生成文件的默认名字为
ta=new JTextArea("ADDED FILES");//生成文本域
ta.setEditable(false);//文本域属性设置为不可编辑
lb.setText("FileName");//文本域里面的初始内容为"FileName"
chooseSound.setSize(70,30);//下面都是设置控制件的大小以及位置
chooseSound.setLocation(100,20);
add.setSize(70,30);
add.setLocation(200,20);
ta.setSize(250,150);
ta.setLocation(60,100);
lb.setSize(70,30);
lb.setLocation(70,300);
tf.setSize(70,30);
tf.setLocation(150,300);
save.setSize(70,30);
save.setLocation(250,300);
add.addActionListener(this);//给按钮添加监听器
save.addActionListener(this);
contentPane.add(chooseSound);//将相应的按钮添加到pane中去
contentPane.add(add);
contentPane.add(ta);
contentPane.add(lb);
contentPane.add(tf);
contentPane.add(save);
show();
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==add)//如果当前的指令是添加文件
{
s[index++]=choices[chooseSound.getSelectedIndex()];//获得当前下拉菜单中被选中音乐的序号 然后根据序号查出这个音乐对应的名字
String text="ADDED FILES\n";
for(int i=0;i<index;i++)
{
text=text+s[i]+"\n";
}
ta.setText(text);//刷新文本域里面的内容
}
else if(e.getSource()==save)//当前的指令是保存文件
{
int saveFileLength=0,addFileLength[]=new int[10];
File f=new File(tf.getText()+".wav");
if(f.exists())
{
System.out.println("文件已经存在,无法创建文件");
}//查看是否能够创建新的文件(若有同名或磁盘空间不足的情况无法创建)
else
{
System.out.println("文件创建成功");
}
if(!f.exists())//若没有同名的情况下创建文件
{
FileOutputStream fou=null;
FileInputStream fis=null;
for(int j=0;j<index;j++)//将每个文件的长度读出来
{
try
{
fis=new FileInputStream(s[j]);
fis.skip(40);//因为音乐用的都是统一的格式,而每个音乐的长度都是存放在文件第40个bytes 位置的连续4个bytes
}
catch(Exception g)
{
}
byte length[]=new byte[4];
try
{
fis.read(length);
}
catch(Exception k)
{
}
int a[]=new int[4]; a[3]=length[3];a[2]=length[2];a[1]=length[1];a[0]=length[0];
addFileLength[j]=(a[3]<<24)&0XFF000000|(a[2]<<16)&0X00FF0000|(a[1]<<8)&0X0000FF00|a[0]&0X000000FF;//读出的数据是4个长度的bytes所以需要将这4字节bytes转换为int
saveFileLength+=addFileLength[j];//将转换后的数值加到saveFileLength中去saveFileLength是生成文件的长度
try
{
fis.close();
}
catch(Exception mn)
{
}//在读完文件长度后将文件关闭
}
try
{
fou=new FileOutputStream(f);
fis=new FileInputStream("standard.wav");//从标注声音文件中读出基本的头信息 其中standard是已经生成的头文件信息 只需要将其读出然后写入生成文件中就可以了
}
catch(FileNotFoundException fnf)
{
System.out.println("文件不存在");
}
byte message[]=new byte[44];
try
{
fis.read(message);//将文件总长度saveFileLength转化为bytes类型并且写入到生成文件头信息中去
message[4]=(byte)(saveFileLength>>0); //将int转化为bytes
message[5]=(byte)(saveFileLength>>8);
message[6]=(byte)(saveFileLength>>16);
message[7]=(byte)(saveFileLength>>24);
message[40]=message[4];
message[41]=message[5];
message[42]=message[6];
message[43]=message[7];
fou.write(message);//
}
catch(Exception m)
{
}
for(int i=0;i<index;i++)
{
try
{
fis=new FileInputStream(s[i]);
}
catch(Exception x)
{
}
try
{
fis.skip(44);
byte b[]=new byte[1];
for(int j=0;j<addFileLength[i];j++)
{
fis.read(b);//将各个文件中的信息读出来并且将它们写入到生成文件中去
fou.write(b);
}
}
catch(Exception m)
{
System.out.println("无法读取源文件");
}
try
{
fis.close();
}
catch(Exception n)
{
}
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -