兩個(gè)wav文件合并過(guò)程
主要的思路 :wav格式的音頻文件有一定的格式:head+數(shù)據(jù)字節(jié)數(shù)組!兩個(gè)wav格式的文件,消息頭中主要文件大小區(qū)間和數(shù)據(jù)量大小區(qū)間不一樣,以及具體的數(shù)據(jù)字節(jié)數(shù)組不一樣而已! 主要生成兩個(gè)文件量的文件head+兩個(gè)音頻文件的數(shù)據(jù)字節(jié)數(shù)組!
具體解說(shuō)wav 和 RIFF文件格式:詳情參照
具體的代碼過(guò)程:
多個(gè)文件合并一個(gè)文件
/**
* 合并文件2
* @param fileList
*/
public static void fixFils2(List<File> fileList,String fileOutPath){
//先進(jìn)行獲取文件長(zhǎng)度 和音頻文件長(zhǎng)度 寫(xiě)入到Head byte數(shù)組中!
long []length=new long[4];
long totalLength=0;
for (int i=0;i<fileList.size();++i) {
length[i]=fileList.get(i).length()-44;//每個(gè)文件長(zhǎng)度-44
totalLength+=length[i];
}
//設(shè)置總長(zhǎng)度:
ByteBuffer byteBuffer=ByteBuffer.allocate(4);//整型為4個(gè)字節(jié)
byteBuffer.putInt(Integer.parseInt(totalLength+"")+36);
byte []fileLength=byteBuffer.array();//獲取文件長(zhǎng)度
ByteBuffer byteBuffer1=ByteBuffer.allocate(4);
byteBuffer1.putInt(Integer.parseInt(totalLength+""));
byte []dataLength=byteBuffer1.array();//音頻數(shù)據(jù)長(zhǎng)度
fileLength = reverse(fileLength); //數(shù)組反轉(zhuǎn)
dataLength = reverse(dataLength);
byte []head=new byte[44];
ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
int len=-1;
byte []buffer=new byte[1024];
//進(jìn)行獲取頭部信息:
try {
for (int i=0;i<fileList.size();++i) {
//
FileInputStream fileInputStream=new FileInputStream(fileList.get(i));
if(i==0){
//讀取第一個(gè)文件頭的信息
fileInputStream.read(head,0,head.length);
for(int j=0; j<4; j++){ //4代表一個(gè)int占用字節(jié)數(shù)
head[j+4] = fileLength[j]; //替換原頭部信息里的文件長(zhǎng)度
head[j+40] = dataLength[j]; //替換原頭部信息里的數(shù)據(jù)長(zhǎng)度
}
//先將頭文件 寫(xiě)進(jìn)去!
byteArrayOutputStream.write(head,0,head.length);
while ((len = fileInputStream.read(buffer, 0, buffer.length)) != -1) {
byteArrayOutputStream.write(buffer,0,len);
}
fileInputStream.close();
}else{
fileInputStream.read(buffer,0,44);
while ((len = fileInputStream.read(buffer, 0, buffer.length)) != -1) {
byteArrayOutputStream.write(buffer,0,len);
}
fileInputStream.close();
}
}
//進(jìn)行寫(xiě)出文件:
FileOutputStream fileOutputStream=new FileOutputStream(fileOutPath);
byteArrayOutputStream.writeTo(fileOutputStream);
fileOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
將一個(gè)wav文件切成多個(gè)wav文件: 主要確定切割時(shí)間的范圍,解析到對(duì)應(yīng)區(qū)間的數(shù)據(jù)量,跳轉(zhuǎn)間隔值!將head的文件大小和音頻數(shù)據(jù)量改為對(duì)應(yīng)切割小文件的數(shù)據(jù)量(由時(shí)間-->數(shù)據(jù)量):
剪切過(guò)程
/**
* 截取wav音頻文件
* @param start 截取開(kāi)始時(shí)間(秒)
* @param end 截取結(jié)束時(shí)間(秒)
*
* return 截取成功返回true,否則返回false
*/
public static boolean cut(String sourcefile, String targetfile, int start, int end) {
try{
if(!sourcefile.toLowerCase().endsWith(".wav") || !targetfile.toLowerCase().endsWith(".wav")){
return false;
}
File wav = new File(sourcefile);
if(!wav.exists()){
return false;
}
long t1 = getTimeLen(wav); //總時(shí)長(zhǎng)(秒)
if(start<0 || end<=0 || start>=t1 || end>t1 || start>=end){
return false;
}
FileInputStream fis = new FileInputStream(wav);
long wavSize = wav.length()-44; //音頻數(shù)據(jù)大小(44為128kbps比特率wav文件頭長(zhǎng)度)
long splitSize = (wavSize/t1)*(end-start); //截取的音頻數(shù)據(jù)大小
long skipSize = (wavSize/t1)*start; //截取時(shí)跳過(guò)的音頻數(shù)據(jù)大小
int splitSizeInt = Integer.parseInt(String.valueOf(splitSize));
int skipSizeInt = Integer.parseInt(String.valueOf(skipSize));
ByteBuffer buf1 = ByteBuffer.allocate(4); //存放文件大小,4代表一個(gè)int占用字節(jié)數(shù)
buf1.putInt(splitSizeInt+36); //放入文件長(zhǎng)度信息
byte[] flen = buf1.array(); //代表文件長(zhǎng)度
ByteBuffer buf2 = ByteBuffer.allocate(4); //存放音頻數(shù)據(jù)大小,4代表一個(gè)int占用字節(jié)數(shù)
buf2.putInt(splitSizeInt); //放入數(shù)據(jù)長(zhǎng)度信息
byte[] dlen = buf2.array(); //代表數(shù)據(jù)長(zhǎng)度
System.out.println("flen length:"+flen.length+".....dlen length:"+dlen.length);
flen = reverse(flen); //數(shù)組反轉(zhuǎn)
dlen = reverse(dlen);
byte[] head = new byte[44]; //定義wav頭部信息數(shù)組
fis.read(head, 0, head.length); //讀取源wav文件頭部信息
for(int i=0; i<4; i++){ //4代表一個(gè)int占用字節(jié)數(shù)
head[i+4] = flen[i]; //替換原頭部信息里的文件長(zhǎng)度
head[i+40] = dlen[i]; //替換原頭部信息里的數(shù)據(jù)長(zhǎng)度
}
byte[] fbyte = new byte[splitSizeInt+head.length]; //存放截取的音頻數(shù)據(jù)
for(int i=0; i<head.length; i++){ //放入修改后的頭部信息
fbyte[i] = head[i];
}
byte[] skipBytes = new byte[skipSizeInt]; //存放截取時(shí)跳過(guò)的音頻數(shù)據(jù)
fis.read(skipBytes, 0, skipBytes.length); //跳過(guò)不需要截取的數(shù)據(jù)
fis.read(fbyte, head.length, fbyte.length-head.length); //讀取要截取的數(shù)據(jù)到目標(biāo)數(shù)組
fis.close();
File target = new File(targetfile);
if(target.exists()){ //如果目標(biāo)文件已存在,則刪除目標(biāo)文件
target.delete();
}
FileOutputStream fos = new FileOutputStream(target);
fos.write(fbyte);
fos.flush();
fos.close();
}catch(IOException e){
e.printStackTrace();
return false;
}
return true;
}
/**
* 獲取音頻文件總時(shí)長(zhǎng)
* @return
*/
public static long getTimeLen(File file){
long tlen = 0;
if(file!=null && file.exists()){
Encoder encoder = new Encoder();
try {
MultimediaInfo m = encoder.getInfo(file);
long ls = m.getDuration();
tlen = ls/1000;
} catch (Exception e) {
e.printStackTrace();
}
}
return tlen;
}
/**
* 數(shù)組反轉(zhuǎn)
* @param array
*/
public static byte[] reverse(byte[] array){
byte temp;
int len=array.length;
for(int i=0;i<len/2;i++){
temp=array[i];
array[i]=array[len-1-i];
array[len-1-i]=temp;
}
return array;
}