录音文件截取

Java代码  收藏代码
  1. import it.sauronsoftware.jave.Encoder;  
  2. import it.sauronsoftware.jave.MultimediaInfo;  
  3.   
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.nio.ByteBuffer;  
  9.   
  10. /** 
  11.  * wav音频文件截取工具 
  12.  * (适用于比特率为128kbps的wav音频文件,此类音频文件的头部信息占用长度44字节) 
  13.  * @author lwj 
  14.  * 
  15.  */  
  16. public class WavCut {  
  17.       
  18.     /** 
  19.      * 截取wav音频文件 
  20.      * @param sourcepath  源文件地址 
  21.      * @param targetpath  目标文件地址 
  22.      * @param start  截取开始时间(秒) 
  23.      * @param end  截取结束时间(秒) 
  24.      *  
  25.      * return  截取成功返回true,否则返回false 
  26.      */  
  27.     public static boolean cut(String sourcefile, String targetfile, int start, int end) {  
  28.         try{  
  29.             if(!sourcefile.toLowerCase().endsWith(".wav") || !targetfile.toLowerCase().endsWith(".wav")){  
  30.                 return false;  
  31.             }  
  32.             File wav = new File(sourcefile);  
  33.             if(!wav.exists()){  
  34.                 return false;  
  35.             }  
  36.             long t1 = getTimeLen(wav);  //总时长(秒)  
  37.             if(start<0 || end<=0 || start>=t1 || end>t1 || start>=end){  
  38.                 return false;  
  39.             }  
  40.             FileInputStream fis = new FileInputStream(wav);  
  41.             long wavSize = wav.length()-44;  //音频数据大小(44为128kbps比特率wav文件头长度)  
  42.             long splitSize = (wavSize/t1)*(end-start);  //截取的音频数据大小  
  43.             long skipSize = (wavSize/t1)*start;  //截取时跳过的音频数据大小  
  44.             int splitSizeInt = Integer.parseInt(String.valueOf(splitSize));  
  45.             int skipSizeInt = Integer.parseInt(String.valueOf(skipSize));  
  46.               
  47.             ByteBuffer buf1 = ByteBuffer.allocate(4);  //存放文件大小,4代表一个int占用字节数  
  48.             buf1.putInt(splitSizeInt+36);  //放入文件长度信息  
  49.             byte[] flen = buf1.array();  //代表文件长度  
  50.             ByteBuffer buf2 = ByteBuffer.allocate(4);  //存放音频数据大小,4代表一个int占用字节数  
  51.             buf2.putInt(splitSizeInt);  //放入数据长度信息  
  52.             byte[] dlen = buf2.array();  //代表数据长度  
  53.             flen = reverse(flen);  //数组反转  
  54.             dlen = reverse(dlen);  
  55.             byte[] head = new byte[44];  //定义wav头部信息数组  
  56.             fis.read(head, 0, head.length);  //读取源wav文件头部信息  
  57.             for(int i=0; i<4; i++){  //4代表一个int占用字节数  
  58.                 head[i+4] = flen[i];  //替换原头部信息里的文件长度  
  59.                 head[i+40] = dlen[i];  //替换原头部信息里的数据长度  
  60.             }  
  61.             byte[] fbyte = new byte[splitSizeInt+head.length];  //存放截取的音频数据  
  62.             for(int i=0; i<head.length; i++){  //放入修改后的头部信息  
  63.                 fbyte[i] = head[i];  
  64.             }  
  65.             byte[] skipBytes = new byte[skipSizeInt];  //存放截取时跳过的音频数据  
  66.             fis.read(skipBytes, 0, skipBytes.length);  //跳过不需要截取的数据  
  67.             fis.read(fbyte, head.length, fbyte.length-head.length);  //读取要截取的数据到目标数组  
  68.             fis.close();  
  69.               
  70.             File target = new File(targetfile);  
  71.             if(target.exists()){  //如果目标文件已存在,则删除目标文件  
  72.                 target.delete();  
  73.             }  
  74.             FileOutputStream fos = new FileOutputStream(target);  
  75.             fos.write(fbyte);  
  76.             fos.flush();  
  77.             fos.close();  
  78.         }catch(IOException e){  
  79.             e.printStackTrace();  
  80.             return false;  
  81.         }  
  82.         return true;  
  83.     }  
  84.       
  85.     /** 
  86.      * 获取音频文件总时长 
  87.      * @param filePath  文件路径 
  88.      * @return 
  89.      */  
  90.     public static long getTimeLen(File file){  
  91.         long tlen = 0;  
  92.         if(file!=null && file.exists()){  
  93.             Encoder encoder = new Encoder();  
  94.             try {  
  95.                  MultimediaInfo m = encoder.getInfo(file);  
  96.                  long ls = m.getDuration();  
  97.                  tlen = ls/1000;  
  98.             } catch (Exception e) {  
  99.                 e.printStackTrace();  
  100.             }  
  101.         }  
  102.         return tlen;  
  103.     }  
  104.       
  105.     /** 
  106.     * 数组反转 
  107.     * @param array 
  108.     */  
  109.     public static byte[] reverse(byte[] array){  
  110.         byte temp;  
  111.         int len=array.length;  
  112.         for(int i=0;i<len/2;i++){  
  113.             temp=array[i];  
  114.             array[i]=array[len-1-i];  
  115.             array[len-1-i]=temp;  
  116.         }  
  117.         return array;  
  118.     }  
  119.       
  120.     public static void main(String[] args){  
  121.         System.out.println(cut("f:\111.wav","f:\111-cut_0_10.wav",0,10));  
  122.         System.out.println(cut("f:\111.wav","f:\111-cut_10_20.wav",10,20));  
  123.         System.out.println(cut("f:\111.wav","f:\111-cut_20_28.wav",20,28));  
  124.     }  
  125.   
  126. }  

wave类型的音频文件切割时必须注意头信息,128kbps比特率的wave文件头信息占用44字节。

可以把头信息作为一个对象,用ByteBuffer获取头信息。

注意:wave文件的头信息字节数组中每个属性都进行了数组反转

wave头信息对象模型如下:

Java代码  收藏代码
  1. /** 
  2.  * wave文件头信息 
  3.  * @author lwj 
  4.  * 
  5.  */  
  6. public class Head {  
  7.       
  8.     public int riff_id;           //4 byte , 'RIFF'  
  9.     public int file_size;         //4 byte , 文件长度(数据长度+36)  
  10.     public int riff_type;         //4 byte , 'WAVE'  
  11.   
  12.     public int fmt_id;            //4 byte , 'fmt'  
  13.     public int fmt_size;          //4 byte , 数值为16或18,18则最后又附加信息  
  14.     public short fmt_tag;          //2 byte , 编码方式,一般为0x0001  
  15.     public short fmt_channel;     //2 byte , 声道数目,1--单声道;2--双声道  
  16.     public int fmt_samplesPerSec;//4 byte , 采样频率  
  17.     public int avgBytesPerSec;   //4 byte , 每秒所需字节数,记录每秒的数据量  
  18.     public short blockAlign;      //2 byte , 数据块对齐单位(每个采样需要的字节数)  
  19.     public short bitsPerSample;   //2 byte , 每个采样需要的bit数  
  20.   
  21.     public int data_id;           //4 byte , 字符data  
  22.     public int data_size;         //4 byte , 数据长度  
  23.       
  24.     public int getRiff_id() {  
  25.         return riff_id;  
  26.     }  
  27.     public void setRiff_id(int riff_id) {  
  28.         this.riff_id = riff_id;  
  29.     }  
  30.     public int getFile_size() {  
  31.         return file_size;  
  32.     }  
  33.     public void setFile_size(int file_size) {  
  34.         this.file_size = file_size;  
  35.     }  
  36.     public int getRiff_type() {  
  37.         return riff_type;  
  38.     }  
  39.     public void setRiff_type(int riff_type) {  
  40.         this.riff_type = riff_type;  
  41.     }  
  42.     public int getFmt_id() {  
  43.         return fmt_id;  
  44.     }  
  45.     public void setFmt_id(int fmt_id) {  
  46.         this.fmt_id = fmt_id;  
  47.     }  
  48.     public int getFmt_size() {  
  49.         return fmt_size;  
  50.     }  
  51.     public void setFmt_size(int fmt_size) {  
  52.         this.fmt_size = fmt_size;  
  53.     }  
  54.     public short getFmt_tag() {  
  55.         return fmt_tag;  
  56.     }  
  57.     public void setFmt_tag(short fmt_tag) {  
  58.         this.fmt_tag = fmt_tag;  
  59.     }  
  60.     public short getFmt_channel() {  
  61.         return fmt_channel;  
  62.     }  
  63.     public void setFmt_channel(short fmt_channel) {  
  64.         this.fmt_channel = fmt_channel;  
  65.     }  
  66.     public int getFmt_samplesPerSec() {  
  67.         return fmt_samplesPerSec;  
  68.     }  
  69.     public void setFmt_samplesPerSec(int fmt_samplesPerSec) {  
  70.         this.fmt_samplesPerSec = fmt_samplesPerSec;  
  71.     }  
  72.     public int getAvgBytesPerSec() {  
  73.         return avgBytesPerSec;  
  74.     }  
  75.     public void setAvgBytesPerSec(int avgBytesPerSec) {  
  76.         this.avgBytesPerSec = avgBytesPerSec;  
  77.     }  
  78.     public short getBlockAlign() {  
  79.         return blockAlign;  
  80.     }  
  81.     public void setBlockAlign(short blockAlign) {  
  82.         this.blockAlign = blockAlign;  
  83.     }  
  84.     public short getBitsPerSample() {  
  85.         return bitsPerSample;  
  86.     }  
  87.     public void setBitsPerSample(short bitsPerSample) {  
  88.         this.bitsPerSample = bitsPerSample;  
  89.     }  
  90.     public int getData_id() {  
  91.         return data_id;  
  92.     }  
  93.     public void setData_id(int data_id) {  
  94.         this.data_id = data_id;  
  95.     }  
  96.     public int getData_size() {  
  97.         return data_size;  
  98.     }  
  99.     public void setData_size(int data_size) {  
  100.         this.data_size = data_size;  
  101.     }  
  102.       
  103. }  

附件为wave切割程序所依赖的外部jar包

Next lines extracts audio informations from an AVI and store them in a plain WAV file:

File source = new File("source.avi");
File target = new File("target.wav");
AudioAttributes audio = new AudioAttributes();
audio.setCodec("pcm_s16le");
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("wav");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder();
encoder.encode(source, target, attrs);




Next example takes an audio WAV file and generates a 128 kbit/s, stereo, 44100 Hz MP3 file:

File source = new File("source.wav");
File target = new File("target.mp3");
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
audio.setBitRate(new Integer(128000));
audio.setChannels(new Integer(2));
audio.setSamplingRate(new Integer(44100));
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("mp3");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder();
encoder.encode(source, target, attrs);



http://lwjwd.iteye.com/blog/2025072



http://www.sauronsoftware.it/projects/jave/manual.php#10




自己的代码

package io.renren.util;


import it.sauronsoftware.jave.AudioAttributes;
import it.sauronsoftware.jave.Encoder;
import it.sauronsoftware.jave.EncoderException;
import it.sauronsoftware.jave.EncodingAttributes;
import it.sauronsoftware.jave.InputFormatException;
import it.sauronsoftware.jave.MultimediaInfo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
* wav音频文件截取工具
* (适用于比特率为128kbps的wav音频文件,此类音频文件的头部信息占用长度44字节)
* @author lwj
*
*/
public class WavCut {

/**
* 截取wav音频文件
* @param sourcepath 源文件地址
* @param targetpath 目标文件地址
* temFile 128文件,中间文件
* @param start 截取开始时间(毫秒)
* @param end 截取结束时间(毫秒)
*
* return 截取成功返回true,否则返回false
* @throws Exception
* @throws InputFormatException
* @throws IllegalArgumentException
*/
public static boolean cut(String sourcefile,String temFile, String targetfile, long start, long end) throws IllegalArgumentException, InputFormatException, Exception {
try{
if(!sourcefile.toLowerCase().endsWith(".wav") || !targetfile.toLowerCase().endsWith(".wav")){
return false;
}
//转出128文件
remake(sourcefile, temFile);

File wav = new File(temFile);



if(!wav.exists()){
return false;
}
long t1 = getTimeLenMs(wav); //总时长(毫秒)
System.out.println(t1);




if(start<0 || end<=0 || start>=t1 || end>t1 || start>=end){
return false;
}
FileInputStream fis = new FileInputStream(wav);
long wavSize = wav.length()-44; //音频数据大小(44为128kbps比特率wav文件头长度)
long splitSize = (wavSize/t1)*(end-start); //截取的音频数据大小
long skipSize = (wavSize/t1)*start; //截取时跳过的音频数据大小



int splitSizeInt = Integer.parseInt(String.valueOf(splitSize));
int skipSizeInt = Integer.parseInt(String.valueOf(skipSize));

ByteBuffer buf1 = ByteBuffer.allocate(4); //存放文件大小,4代表一个int占用字节数
buf1.putInt(splitSizeInt+36); //放入文件长度信息
byte[] flen = buf1.array(); //代表文件长度
ByteBuffer buf2 = ByteBuffer.allocate(4); //存放音频数据大小,4代表一个int占用字节数
buf2.putInt(splitSizeInt); //放入数据长度信息
byte[] dlen = buf2.array(); //代表数据长度
flen = reverse(flen); //数组反转
dlen = reverse(dlen);
byte[] head = new byte[44]; //定义wav头部信息数组
fis.read(head, 0, head.length); //读取源wav文件头部信息
for(int i=0; i<4; i++){ //4代表一个int占用字节数
head[i+4] = flen[i]; //替换原头部信息里的文件长度
head[i+40] = dlen[i]; //替换原头部信息里的数据长度
}
byte[] fbyte = new byte[splitSizeInt+head.length]; //存放截取的音频数据
for(int i=0; i<head.length; i++){ //放入修改后的头部信息
fbyte[i] = head[i];
}
byte[] skipBytes = new byte[skipSizeInt]; //存放截取时跳过的音频数据
fis.read(skipBytes, 0, skipBytes.length); //跳过不需要截取的数据
fis.read(fbyte, head.length, fbyte.length-head.length); //读取要截取的数据到目标数组
fis.close();

File target = new File(targetfile);
if(target.exists()){ //如果目标文件已存在,则删除目标文件
target.delete();
}
FileOutputStream fos = new FileOutputStream(target);
fos.write(fbyte);
fos.flush();
fos.close();
}catch(IOException e){
e.printStackTrace();
return false;
}
return true;
}

/**
* 获取音频文件总时长
* @param filePath 文件路径
* @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;
}

/**
* 获取音频文件总时长(ms)
* @param filePath 文件路径
* @return
*/
public static long getTimeLenMs(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;
} catch (Exception e) {
e.printStackTrace();
}
}
return tlen;
}

/**
* 数组反转
* @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;
}



/**
* 把256转出128
* @author yanwenbin
* @version 创建时间:2018年10月25日 下午3:11:24
*/
public static void remake(String sourcefile, String targetfile) throws IllegalArgumentException, InputFormatException, EncoderException{
File tag = new File(targetfile);
File wav = new File(sourcefile);
Encoder encoder = new Encoder();
//ywb
/*文件来源=新文件(“source.wav”);
文件目标=新文件(“target.mp3”); */
AudioAttributes audio = new AudioAttributes();
audio.setCodec( "libmp3lame");
audio.setBitRate(new Integer(128000));
audio.setChannels(new Integer(2));
audio.setSamplingRate(new Integer(44100));
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("wav");
//attrs.setAudioAttributes("音频");

attrs.setAudioAttributes(audio);
//编码器编码器=新编码器();

encoder.encode(wav,tag,attrs);

//ywb
}

public static void main(String[] args){
/*try {
a("C:\Users\Administrator\Desktop\20_1_1539940059183.wav","f:\111-cut_0_10.wav");
} catch (IllegalArgumentException | EncoderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
try {
System.out.println(cut("C:\Users\Administrator\Desktop\audio\5.wav","C:\Users\Administrator\Desktop\audio\5-128.wav","C:\Users\Administrator\Desktop\audio\5-son1.wav",0,3000));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InputFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* System.out.println(cut("f:\111.wav","f:\111-cut_10_20.wav",10,20));
System.out.println(cut("f:\111.wav","f:\111-cut_20_28.wav",20,28)); */
}

}

原文地址:https://www.cnblogs.com/ywb2018/p/9850108.html