java实现录音

网上找了一些java实现录音,Android比较多,还有一些不能使用,本人对音频知识一概不知,在github上找了一个案例进行修改,使用没有问题。

代码有些乱。


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

import org.junit.Test;

public class TestRecord {

	byte bts[] = new byte[10000];
	ByteArrayOutputStream baos = null;
	boolean stopflag;
	TargetDataLine td = null;
	ByteArrayInputStream bais = null;
	// 定义音频输入流
	AudioInputStream ais = null;
	// 设置一个播放的标志
	Boolean playflag;

	// 每次保存的最后的文件名
	File tarFile = null;
	AudioFormat af = null;
	// 定义源数据行,源数据行是可以写入数据的数据行。它充当其混频器的源。应用程序将音频字节写入源数据行,这样可处理字节缓冲并将它们传递给混频器。
	SourceDataLine sd = null;

	@Test
	public void play() throws LineUnavailableException {
		af = getAudioFormat();
		DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
		td = (TargetDataLine) (AudioSystem.getLine(info));
		td.open(af);
		td.start();
		Record record = new Record();
		Thread t1 = new Thread(record);
		t1.start();
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		stop();
		save();
	}

	// 停止录音
	public void stop() {
		stopflag = true;
	}

	private static AudioFormat getAudioFormat() {
		// 下面注释部分是另外一种音频格式,两者都可以
		AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;
		float rate = 8000f;
		int sampleSize = 16;
		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();
					} 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();
					// 刷新显示波形的面板
				}
			}
		}

	}

	// 保存录音
	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 {
			// 以当前的时间命名录音的名字
			// 将录音的文件存放到D盘下
			File filePath = new File("D:/");
			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("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();
			}
		}
	}
}

 

你可能感兴趣的:(java)