Java 录音与文件保存

该博客主要展示了如何使用Java Sound API进行声音录制,将录制的音频数据存储到缓冲区,并通过线程处理生成WAV文件。博客内容涉及到Mixer的获取、TargetDataLine的使用以及音频数据的读取和写入操作。
摘要由CSDN通过智能技术生成
package cn.lixirong.audiotest;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Mixer;

public class AudioTest {

	public static void main(String[] args) {

		Mixer.Info[] info= AudioSystem.getMixerInfo();
		for(int i=0;i<info.length;i++){

			System.out.println(String.valueOf(i)+info[i].getName()+","+info[i].getVendor()+
					","+info[i].getVersion()+","+info[i].getDescription());
			
		}
		(new RecordThread()).start();
	}
}

package cn.lixirong.audiotest;

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

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.TargetDataLine;

public class RecordThread extends Thread{
	AudioFormat audioFormat;
	TargetDataLine targetDataLine;
	AudioInputStream ais;
	
	//byte[] wavbuf=new byte[4800*2];
	static int BaosBufCNT=20;
	byte[][] baosBuf=new byte[BaosBufCNT][48000*10];
	static boolean[] isUseBaosBuf=new boolean[BaosBufCNT];
	
	ByteArrayInputStream bais;
	ByteArrayOutputStream baos;
	
	int totalCNT=5;
	
	public static void setIsUseBaosBuf(int arg0,boolean arg1){
		isUseBaosBuf[arg0]=arg1;
	}
	
	public RecordThread(){
		for(int i=0;i<BaosBufCNT;i++){
			isUseBaosBuf[i]=false;
		}

	}
	
	private AudioFormat getAudioFormat() {
		// 8000,11025,16000,22050,44100 采样率
		float sampleRate = 48000.000000f;
		// 8,16 每个样本中的位数
		int sampleSizeInBits = 16;
		// 1,2 信道数(单声道为 1,立体声为 2,等等)
		int channels = 1;
		// true,false
		boolean signed = true;
		// true,false 指示是以 big-endian 顺序还是以 little-endian 顺序存储音频数据。
		boolean bigEndian = false;
		// 构造具有线性 PCM 编码和给定参数的 AudioFormat。
		return new AudioFormat(sampleRate, sampleSizeInBits, channels, signed,bigEndian);
	}
	
	public void run(){
		baos=new ByteArrayOutputStream();
		try {
			// 构造具有线性 PCM 编码和给定参数的 AudioFormat。
			audioFormat = getAudioFormat();
			// 根据指定信息构造数据行的信息对象,这些信息包括单个音频格式。此构造方法通常由应用程序用于描述所需的行。
			// lineClass - 该信息对象所描述的数据行的类
			// format - 所需的格式
			DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
			targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
			targetDataLine.open(audioFormat);
			targetDataLine.start();
			boolean isLoop=true;
			byte[] tempbuf=new byte[4800*2];
			int i=0;
			int totalLen=0;
			System.out.println("time1="+System.currentTimeMillis());
			int wavCNT=0;
			while(isLoop){
				int len=targetDataLine.read(tempbuf, 0, 4800*2);
				if(len!=-1){
					baos.write(tempbuf, 0,len);
					i++;
					totalLen+=len;
					if(totalLen>=48000*2){
						for(int j=0;j<BaosBufCNT;j++){
							if(!isUseBaosBuf[j]){
								isUseBaosBuf[j]=true;
								int len2=baos.size();
								baos.flush();//清空
								baosBuf[j]=baos.toByteArray();
								baos.close();
								baos=null;
								baos=new ByteArrayOutputStream();
								baos.write(baosBuf[j], 4800*2, len2-4800*2);//把剩下的写回去
								(new FileThread(baosBuf[j],System.currentTimeMillis(),j)).start();
								wavCNT++;
								System.out.println("totalLen="+String.valueOf(totalLen));
								totalLen-=48000*2;
								
								break;
							}
						}
					}
				}
				try{
					Thread.sleep(50);
				}catch(Exception ex){}
				if(wavCNT>100){
					isLoop=false;
				}
			}
			baos.close();
			targetDataLine.stop();
			targetDataLine.close();

		} catch (Exception e){
			e.printStackTrace();
			System.exit(0);
		}
		// 指定的文件类型
		AudioFileFormat.Type fileType = null;
		// 设置文件类型和文件扩展名
		fileType = AudioFileFormat.Type.WAVE;
		try {
			// format - 所需音频格式
			//targetDataLine.open(audioFormat);
			// 当开始音频捕获或回放时,生成 START 事件。
			//targetDataLine.start();
			// new AudioInputStream(TargetDataLine line):构造从指示的目标数据行读取数据的音频输入流。该流的格式与目标数据行的格式相同,line - 此流从中获得数据的目标数据行。
			// stream - 包含要写入文件的音频数据的音频输入流
			// fileType - 要写入的音频文件的种类
			// out - 应将文件数据写入其中的外部文件
			//AudioSystem.write(new AudioInputStream(targetDataLine),fileType, new File("F://ss.wav"));
			//AudioSystem.write(new AudioInputStream(new ByteArrayInputStream(bt),audioFormat,bt.length / audioFormat.getFrameSize()),fileType,"new File("D://ss.wav")");

			//DataOutputStream dos=new DataOutputStream(dos);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

package cn.lixirong.audiotest;

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

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;

public class FileThread extends Thread{
	byte[] fileByte;
	long fileName;
	int baosBufIndex=0;
	
	AudioFormat af;
	public FileThread(byte[] arg0,long arg1,int arg2){
		fileByte=arg0;
		fileName=arg1;
		baosBufIndex=arg2;
		af=getAudioFormat();
	}
	
	public void run(){
		try{
			File file=new File("F:\\AudioTest\\"+String.valueOf(fileName)+".wav");
			if(!file.exists()){
				file.createNewFile();
			}
			ByteArrayInputStream bais=new ByteArrayInputStream(fileByte);
			AudioInputStream ais = new AudioInputStream(bais, af, 48000*2 / af.getFrameSize());
			AudioSystem.write(ais, AudioFileFormat.Type.WAVE, file);
		}catch(Exception ex){}
		RecordThread.setIsUseBaosBuf(baosBufIndex, false);
	}
	
	private AudioFormat getAudioFormat() {
	
		float sampleRate = 48000.000001f;
	
		int sampleSizeInBits = 16;
	
		int channels = 1;
	
		boolean signed = true;

		boolean bigEndian = false;

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Java 上传录音文件的示例代码,其中使用了 Apache 的文件上传组件: ```java import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class UploadServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 检查是否是 multipart/form-data 表单 boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (!isMultipart) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "上传表单不正确"); return; } // 创建文件上传工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); // 设置缓存目录 File tempDir = new File(System.getProperty("java.io.tmpdir")); factory.setRepository(tempDir); // 创建文件上传处理器 ServletFileUpload upload = new ServletFileUpload(factory); try { // 解析文件上传请求 FileItem fileItem = upload.parseRequest(request).get(0); // 获取文件名 String fileName = fileItem.getName(); // 保存文件到服务器 File uploadedFile = new File("/path/to/upload/directory", fileName); FileUtils.writeByteArrayToFile(uploadedFile, fileItem.get()); // 返回成功响应 response.setStatus(HttpServletResponse.SC_OK); response.getWriter().println("文件上传成功!"); } catch (Exception e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "上传文件失败:" + e.getMessage()); } } } ``` 在上面的代码中,我们使用了 Apache 的 Commons IO 和 Commons FileUpload 组件来处理文件上传。在 `doPost` 方法中,我们首先检查请求是否是一个 multipart/form-data 表单,然后创建一个文件上传工厂,并设置缓存目录。接着,我们创建一个文件上传处理器,并解析文件上传请求。最后,我们获取文件名,保存文件到服务器,并返回成功响应。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值