2019-04-07 音频文件合并

两个wav文件合并过程

主要的思路 :wav格式的音频文件有一定的格式:head+数据字节数组!两个wav格式的文件,消息头中主要文件大小区间和数据量大小区间不一样,以及具体的数据字节数组不一样而已! 主要生成两个文件量的文件head+两个音频文件的数据字节数组!

具体解说wav 和 RIFF文件格式:详情参照

具体的代码过程:

多个文件合并一个文件
/**
 * 合并文件2
 * @param fileList
 */
public static void fixFils2(List<File> fileList,String fileOutPath){
    //先进行获取文件长度 和音频文件长度 写入到Head byte数组中!
    long []length=new long[4];
    long totalLength=0;
    for (int i=0;i<fileList.size();++i) {
        length[i]=fileList.get(i).length()-44;//每个文件长度-44
        totalLength+=length[i];
    }
    //设置总长度:
    ByteBuffer byteBuffer=ByteBuffer.allocate(4);//整型为4个字节
    byteBuffer.putInt(Integer.parseInt(totalLength+"")+36);
    byte []fileLength=byteBuffer.array();//获取文件长度

    ByteBuffer byteBuffer1=ByteBuffer.allocate(4);
    byteBuffer1.putInt(Integer.parseInt(totalLength+""));
    byte []dataLength=byteBuffer1.array();//音频数据长度

    fileLength = reverse(fileLength);  //数组反转
    dataLength = reverse(dataLength);

    byte []head=new byte[44];
    ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
    int len=-1;
    byte []buffer=new byte[1024];
    //进行获取头部信息:
    try {
        for (int i=0;i<fileList.size();++i) {
            //
            FileInputStream fileInputStream=new FileInputStream(fileList.get(i));
            if(i==0){
                //读取第一个文件头的信息
                fileInputStream.read(head,0,head.length);
                for(int j=0; j<4; j++){  //4代表一个int占用字节数
                    head[j+4] = fileLength[j];  //替换原头部信息里的文件长度
                    head[j+40] = dataLength[j];  //替换原头部信息里的数据长度
                }
                //先将头文件 写进去!
                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();
            }
        }

        //进行写出文件:
        FileOutputStream fileOutputStream=new FileOutputStream(fileOutPath);
        byteArrayOutputStream.writeTo(fileOutputStream);
        fileOutputStream.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


将一个wav文件切成多个wav文件: 主要确定切割时间的范围,解析到对应区间的数据量跳转间隔值将head的文件大小和音频数据量改为对应切割小文件的数据量(由时间-->数据量):


剪切过程

  /**
 * 截取wav音频文件
 * @param start  截取开始时间(秒)
 * @param end  截取结束时间(秒)
 *
 * 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);  //总时长(秒)
        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();  //代表数据长度
        System.out.println("flen length:"+flen.length+".....dlen length:"+dlen.length);
        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;
}

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

/**
 * 数组反转
 * @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;
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容