欢迎访问三波知识百科

gridbagconstraints布局(gridbaglayout布局管理器的用法)

频道:生活百科 日期: 浏览:
前几次博客中也是用java实现录音机的各种功能,这次是比先前有了一点优化,将录音的功能单独提取出来,这个程序的实现用到了编码器LAME.exe这个的作用是将录音得到的wav文件编码成MP3文件,这样的结果是容量大大减少,因为LAME编码器经测试在编码过程中路径中带有空格问题未能解决,所以只能找了一个笨的方法,为了将其放到指定的文件夹下(这个文件夹路径是带有空格的),所以只能先存放到D盘,然后利用文件操作将其复制到指定的路径下,然后再删除,程序中还用到了图片,修改了java的图标,所以在运行时可将其注释掉,写的很烂,相互学习哈!

/*

* 实现录音机的功能

* 1.在原来的基础上界面更加精简,字体变大使用户更加方便

* 2.在停止录音后便直接保存为.mp3文件

* 3.对停止录音进行改进,将录音按钮设计成类似微信的形式,按下时进行录音,松开即停止录音并保存即可

* 4.在录音的时候在面板上显示音频波,表示正在录音

*/

package com.liuyun.MyRecord6;

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;

import java.io.*;

import javax.sound.sampled.*;

import java.lang.*;

public class MyRecord6 extends JFrame implements MouseListener{

//定义录音格式

AudioFormat af = null;

//定义目标数据行,可以从中读取音频数据,该 TargetDataLine 接口提供从目标数据行的缓冲区读取所捕获数据的方法。

TargetDataLine td = null;

//定义源数据行,源数据行是可以写入数据的数据行。它充当其混频器的源。应用程序将音频字节写入源数据行,这样可处理字节缓冲并将它们传递给混频器。

SourceDataLine sd = null;

//定义字节数组输入输出流

ByteArrayInputStream bais = null;

ByteArrayOutputStream baos = null;

//定义音频输入流

AudioInputStream ais = null;

//定义停止录音的标志,来控制录音线程的运行

Boolean stopflag = false;

//记录开始录音的时间

long startPlay;

//设置一个播放的标志

Boolean playflag;

//每次保存的最后的文件名

File tarFile = null;

//定义音频波形每次显示的字节数

int intBytes = 0;

//定义每次录音的时候每次提取字节来画音频波

byte audioDataBuffer[] = null;

//定义所需要的组件

JPanel jp1,jp2,jp3;

JLabel jl1=null;

JButton captureBtn;

//设置画波形线程的终止的标志

boolean flag = true;

//定义播放录音时的一个计数值

int cnt;

//定义播放录音时一个缓冲数组

byte btsPlay[] = null;

int gridx, gridy, gridwidth, gridheight, anchor, fill, ipadx, ipady;

double weightx, weighty;

Insets inset;

GridBagConstraints c;

public static void main(String[] args) {

//创造一个实例

MyRecord6 mr = new MyRecord6();

}

//构造函数

public MyRecord6()

{

//组件初始化

jp1 = new JPanel();

jp2 = new JPanel();

jp3 = new JPanel();

//定义jp1的字体

Font jpFont = new Font(“华文新魏”,Font.BOLD,40);

jl1 = new JLabel(“请留下您想说的话”);

jl1.setFont(jpFont);

jl1.setForeground(Color.red);

jp1.add(jl1);

//定义按钮上面的字体

Font btFont = new Font(“华文新魏”,Font.BOLD,40);

captureBtn = new JButton(“按住 说话”);

//setForeground可以设置按钮上面字体的颜色

captureBtn.setForeground(Color.RED);

captureBtn.setFont(btFont);

//对开始录音按钮进行鼠标监听

captureBtn.addMouseListener(this);

this.add(jp1,BorderLayout.NORTH);

this.add(jp2,BorderLayout.CENTER);

this.add(jp3,BorderLayout.SOUTH);

GridBagLayout gridbag = null;

jp3.setLayout(gridbag = new GridBagLayout());

gridx=1;

gridy=2;

gridwidth=1;

gridheight=1;

weightx=1;

weighty=1;

anchor=GridBagConstraints.CENTER;

fill=GridBagConstraints.HORIZONTAL;

inset=new Insets(1,1,1,1);

ipadx=0;

ipady=30;

c = new GridBagConstraints(gridx, gridy, gridwidth, gridheight,

weightx, weighty, anchor, fill, inset, ipadx, ipady);

gridbag.setConstraints(captureBtn, c);

jp3.add(captureBtn);

//设置窗口的属性

this.setSize(800,500);

this.setTitle(“录音机”);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//设置窗口居中

this.setLocationRelativeTo(null);

//将窗口的边框去掉

this.setUndecorated(true);

this.setVisible(true);

//设置窗口上的图标

Image img = this.getToolkit().getImage(getClass().getResource(“/image/Recorder.jpg”));

this.setIconImage(img);

//设置窗口在最前端显示

this.setAlwaysOnTop(true);

}

public void mouseClicked(MouseEvent e) {

}

public void mousePressed(MouseEvent e) {

//当开始录音按钮被按下时就开始录音

if(e.getSource().equals(captureBtn))

{

//改变按钮上面的字的内容

captureBtn.setText(“松开 结束”);

//调用录音的方法

capture();

//记录开始录音的时间

startPlay = System.currentTimeMillis();

}

}

public void mouseReleased(MouseEvent e) {

//当松开录音按钮时停止录音并保存录音的文件

if(e.getSource().equals(captureBtn))

{

//调用停止录音的方法

stop();

//当松开按钮后对显示波形的面板进行清空

jp2.repaint();

//改变按钮上面的字的内容

captureBtn.setText(“按住 说话”);

//调用保存录音的方法

save();

//将其放到指定的路径下

//定义最终要存放的文件路径

String destPath = “D:/Program Files/apache-tomcat-6.0.35/webapps/XWZ/tempFile/”;

copyFile(“D:/”+tarFile.getName(), destPath);

System.exit(0);

}

}

public void mouseEntered(MouseEvent e) {

}

public void mouseExited(MouseEvent e) {

}

//开始录音

public void capture()

{

try {

//af为AudioFormat也就是音频格式

af = getAudioFormat();

DataLine.Info info = new DataLine.Info(TargetDataLine.class,af);

td = (TargetDataLine)(AudioSystem.getLine(info));

//打开具有指定格式的行,这样可使行获得所有所需的系统资源并变得可操作。

td.open(af);

//允许某一数据行执行数据 I/O

td.start();

//启动显示波形的进程

RecordWave aw = new RecordWave();

Thread t2 = new Thread(aw);

t2.start();

//把显示波形的进程标志设为true

flag = true;

Record record = new Record();

Thread t1 = new Thread(record);

t1.start();

} catch (Exception ex) {

ex.printStackTrace();

return;

}

}

//停止录音

public void stop()

{

stopflag = true;

//将画波形的进程终止

flag = false;

}

//保存录音

public void save()

{

af = getAudioFormat();

byte audioData[] = baos.toByteArray();

bais = new ByteArrayInputStream(audioData);

ais = new AudioInputStream(bais,af, audioData.length / af.getFrameSize());

//定义最终保存的文件名

File file = null;

//写入文件

try {

//以当前的时间命名录音的名字

//将录音的文件存放到F盘下语音文件夹下

File filePath = new File(“D:/AudioFile”);

String tarPath = “D:/”;

if(!filePath.exists())

{//如果文件不存在,则创建该目录

filePath.mkdirs();

}

long time = System.currentTimeMillis();

file = new File(filePath+”/”+time+”.wav”);

AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);

//将录音产生的wav文件转换为容量较小的mp3格式

//定义产生后文件名

tarFile = new File(tarPath+time+”.mp3″);

Runtime run = null;

//测试当前的路径

try {

run = Runtime.getRuntime();

//调用编码器来将wav文件转换为mp3文件

//把编码得到的mp3文件先存放到D盘下,然后利用文件拷贝函数将它放到指定的文件夹下同时将D盘下的文件删除

Process p=run.exec(filePath+”/”+”lame -b 16 “+filePath+”/”+file.getName()+” “+tarPath+tarFile.getName()); //16为码率,可自行修改

//释放进程

p.getOutputStream().close();

p.getInputStream().close();

p.getErrorStream().close();

//等待

p.waitFor();

// //删除之前保存的的wav文件

// if(file.exists())

// {

// file.delete();

// }

// //定义最终要存放的文件路径

// String destPath = “D:/Program Files/apache-tomcat-6.0.35/webapps/XWZ/tempFile/”;

// copyFile(tarPath+tarFile.getName(), destPath);

} catch (Exception e) {

e.printStackTrace();

}finally{

//最后都要执行的语句

//run调用lame解码器最后释放内存

run.freeMemory();

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//关闭流

try {

if(bais != null)

{

bais.close();

}

if(ais != null)

{

ais.close();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

//文件拷贝方法

public void copyFile(String srcPath , String destPath)

{

File srcFile = new File(srcPath);

//如果目的文件夹没有则创建目的文件夹

(new File(destPath)).mkdirs();

//在目的文件夹下创建要复制的文件

File destFile = new File(destPath+”/”+srcFile.getName());

if(srcFile.isFile() && srcFile.exists())

{

InputStream in = null;

OutputStream out = null;

try {

in = new FileInputStream(srcFile);

out = new FileOutputStream(destFile);

//设置缓冲数组

byte[] buff = new byte[1024*5];

int len = 0;

while ((len = in.read(buff)) != -1)

{

out.write(buff, 0, len);

}

// //测试该函数是否执行

// System.out.println(“ok1”);

} catch(Exception e) {

e.printStackTrace();

}finally{

//关闭流,先开的后关闭

try {

if(out != null)

{

out.close();

}

if(in != null)

{

in.close();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

//复制过后删除源文件夹中的的文件

if(srcFile.exists())

{

srcFile.delete();

}

}

//设置AudioFormat的参数

public AudioFormat getAudioFormat()

{

//下面注释部分是另外一种音频格式,两者都可以

AudioFormat.Encoding encoding = AudioFormat.Encoding.

PCM_SIGNED ;

float rate = 8000f;

int sampleSize = 16;

String signedString = “signed”;

boolean bigEndian = true;

int channels = 1;

return new AudioFormat(encoding, rate, sampleSize, channels,

(sampleSize / 8) * channels, rate, bigEndian);

// //采样率是每秒播放和录制的样本数

// float sampleRate = 16000.0F;

// // 采样率8000,11025,16000,22050,44100

// //sampleSizeInBits表示每个具有此格式的声音样本中的位数

// int sampleSizeInBits = 16;

// // 8,16

// int channels = 1;

// // 单声道为1,立体声为2

// boolean signed = true;

// // true,false

// boolean bigEndian = true;

// // true,false

// return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,bigEndian);

}

//录音类,因为要用到MyRecord类中的变量,所以将其做成内部类

class Record implements Runnable

{

//定义存放录音的字节数组,作为缓冲区

byte bts[] = new byte[10000];

//将字节数组包装到流里,最终存入到baos中

//重写run函数

public void run() {

baos = new ByteArrayOutputStream();

try {

stopflag = false;

while(stopflag != true)

{

//当停止录音没按下时,该线程一直执行

//从数据行的输入缓冲区读取音频数据。

//要读取bts.length长度的字节,cnt 是实际读取的字节数

int cnt = td.read(bts, 0, bts.length);

if(cnt > 0)

{

baos.write(bts, 0, cnt);

}

//开始从音频流中读取字节数

byte copyBts[] = bts;

bais = new ByteArrayInputStream(copyBts);

ais = new AudioInputStream(bais, af, copyBts.length/af.getFrameSize());

try{

DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, af);

sd = (SourceDataLine) AudioSystem.getLine(dataLineInfo);

sd.open(af);

sd.start();

//从音频流中读取

int Buffer_Size = 10000;

audioDataBuffer = new byte[Buffer_Size];

int outBytes;

intBytes = ais.read(audioDataBuffer, 0,audioDataBuffer.length);

// 不写到混频器中这样就不会播放

// if (intBytes >= 0) {

// outBytes = sd.write(audioDataBuffer, 0,audioDataBuffer.length);

// }

}catch (Exception e) {

e.printStackTrace();

}

}

} catch (Exception e) {

e.printStackTrace();

}finally{

try {

//intBytes = -1;

//关闭打开的字节数组流

if(baos != null)

{

baos.close();

}

} catch (Exception e) {

e.printStackTrace();

}finally{

//下面这句td.drain()不能要,这样如果不播放数据就阻塞再次录音会出现其他程序访问错误

//td.drain();

td.close();

//刷新显示波形的面板

jp2.repaint();

}

}

}

}

//画波形的类

//因为要使用一些主函数中的数据,所以做成内部类

class RecordWave extends JPanel implements Runnable

{

//用画笔画出波形

public void paint(Graphics g)

{

super.paint(g);

g.fillRect(jp2.getX(),jp2.getY() , 800, 380);

if( audioDataBuffer != null)

{

g.drawLine(jp2.getWidth() / 256, 700, jp2.getWidth() / 256, 700);

for(int i=0; i

{

g.setColor(Color.RED);

g.drawLine(i * jp2.getWidth() / 256, (int)audioDataBuffer[i]+200 , (i + 1)

* jp2.getWidth() / 256, (int)audioDataBuffer[i+1]+200);

}

}

}

public void run()

{

//刷新波形

while(true)

{

//System.out.println(“ok”);

try {

synchronized (this) {

//隔多长时间获取

Thread.sleep(300);

}

} catch (Exception e) {

e.printStackTrace();

}

this.paint(jp2.getGraphics());

//终止线程

if(flag == false)

{

break;

}

}

}

}

}

0 留言

评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。
验证码