Java实现合成多个wav音频文件

时间:2022-02-19 19:42:49

参考地址    http://blog.sina.com.cn/s/blog_13c6397540102wxyn.html

 

 

package test;
/**
* @author yanwenbin
* @version 创建时间:2018年11月1日 下午12:03:34
* 合成wav文件
*/

import java.io.File;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class WAVTest {
private int headlength1 = 0;
private int headlength2 = 0;

/*
* 16进制字节数组转换成int
*/
public static int byteArrayToInt(byte[] b) {
return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16 | (b[0] & 0xFF) << 24;
}

/**
* int转换成16进制字节数组
*/
public static byte[] intToByteArray(int a) {
return new byte[] { (byte) ((a >> 24) & 0xFF), (byte) ((a >> 16) & 0xFF), (byte) ((a >> 8) & 0xFF),
(byte) (a & 0xFF) };
}

/**
* 字节数组的转换 0x00 00 27 56在内存中的位置是56 27 00 00 所以要反过来
*/
public static byte[] byteToByte(byte[] a) {
if (a.length == 4) {
byte[] b = new byte[4];
b[0] = a[3];
b[1] = a[2];
b[2] = a[1];
b[3] = a[0];
return b;
}
return null;
}

/**
* 将两个wav合成一个新的wav
*/
public void addWav(String filepath1, String filepath2, String filepath3) throws IOException {
File file1 = new File(filepath1);
System.out.println("1.wav:" + -file1.length());
File file2 = new File(filepath2);
System.out.println("2.wav:" + file2.length());
File file3 = new File(filepath3);
if (!file3.exists()) {
file3.createNewFile();
}
InputStream is1 = new FileInputStream(file1);
InputStream is2 = new FileInputStream(file2);
OutputStream os = new FileOutputStream(file3);// 追加
byte[] tempbuffer = new byte[1024];
int nRed = 0;
while ((nRed = is1.read(tempbuffer)) != -1)// 将1.wav全部内容复制到3.wav
{
os.write(tempbuffer, 0, nRed);
os.flush();
}

is1.close();
is2.skip(44);// 跳过2.wav的文件头
while ((nRed = is2.read(tempbuffer)) != -1)// 将2.wav全部内容追加复制到3.wav结尾处
{
os.write(tempbuffer, 0, nRed);
os.flush();
}
is2.close();
os.close();
// 到此完成了1.wav和2.wav合并成3.wav,但是此时播放3.wav,会发现大小虽然是1.wav和2.wav的和
// 但是音频内容仍然只是第一个音频的内容,所以还要更改3.wav的文件头

}

/**
* 更改addWav.wav.wav的文件头
*/
public void updateFileHead(String filepath3, boolean ifUpdate) throws IOException {
RandomAccessFile raf = new RandomAccessFile(filepath3, "rw");
long filelength = raf.length();
System.out.println(filepath3 + filelength);
// 打开一个文件通道
FileChannel channel = raf.getChannel();
// 映射文件中的某一部分数据以读写模式到内存中
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 44);// 文件头长度
byte[] b = new byte[4];
b[0] = buffer.get(4);
b[1] = buffer.get(5);
b[2] = buffer.get(6);
b[3] = buffer.get(7);
int length1 = WAVTest.byteArrayToInt(WAVTest.byteToByte(b));
System.out.println(length1);// 显示data+44-8

byte[] b1 = new byte[4];
b1[0] = buffer.get(40);
b1[1] = buffer.get(41);
b1[2] = buffer.get(42);
b1[3] = buffer.get(43);
int length2 = WAVTest.byteArrayToInt(WAVTest.byteToByte(b1));
System.out.println(length2);
if (ifUpdate)// 修改头部文件
{
byte[] head1 = this.byteToByte(this.intToByteArray(headlength1));
byte[] head2 = this.byteToByte(this.intToByteArray(headlength2));
// 进行修改操作
buffer.put(4, head1[0]);
buffer.put(5, head1[1]);
buffer.put(6, head1[2]);
buffer.put(7, head1[3]);
buffer.put(40, head2[0]);
buffer.put(41, head2[1]);
buffer.put(42, head2[2]);
buffer.put(43, head2[3]);

buffer.force();// 强制输出,在buffer中的改动生效到文件
System.out.println("文件头修改成功");
/**************************************** 进行查询,看修改是否生效 ***************/

b = new byte[4];
b[0] = buffer.get(4);
b[1] = buffer.get(5);
b[2] = buffer.get(6);
b[3] = buffer.get(7);
length1 = WAVTest.byteArrayToInt(WAVTest.byteToByte(b));
System.out.println(length1);// 显示data+44-8
b1 = new byte[4];

b1[0] = buffer.get(40);
b1[1] = buffer.get(41);
b1[2] = buffer.get(42);
b1[3] = buffer.get(43);
length2 = WAVTest.byteArrayToInt(WAVTest.byteToByte(b1));
System.out.println(length2);

} else {
this.headlength1 = this.headlength1 + length1;
this.headlength2 = this.headlength2 + length2;

}

buffer.clear();
channel.close();
raf.close();

}

public static void main(String[] args) throws IOException {
String filepath1 = "C:\\Users\\Administrator\\Desktop\\audio\\5-son1.wav";// 源文件1.wav
String filepath2 = "C:\\Users\\Administrator\\Desktop\\audio\\5-son.wav";// 源文件2.wav
String filepath3 = "C:/Users/Administrator/Desktop/audio/son1-son.wav";// 合成文件addwav.wav
WAVTest wavTest = new WAVTest();
wavTest.addWav(filepath1, filepath2, filepath3);// data合成
wavTest.updateFileHead(filepath1, false);
wavTest.updateFileHead(filepath2, false);
wavTest.updateFileHead(filepath3, true);//头部合成

}

}