Java实现多个wav文件合成一个的方法示例

 更新时间:2019年05月16日 11:18:59   作者:大爱一生  
这篇文章主要介绍了Java实现多个wav文件合成一个的方法,涉及java文件流读写、编码转换、解析等相关操作技巧,需要的朋友可以参考下

本文实例讲述了Java实现多个wav文件合成一个的方法。分享给大家供大家参考,具体如下:

前面一篇介绍了java切割wav音频文件的方法,这里再给出合并多个wav音频文件的方法。

package com.cmos.nomsapp.utils.wavmeger;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
/**
 * 获取wav头文件然后合并成单个wav
 * @author zcf
 * @date 2017-10-17
 */
public class WavMergeUtil {
  /**
   * meger多个wav
   * @param inputs 多个wav
   * @param output 要生成的wav
   * @throws IOException
   */
  public static void mergeWav(File[] inputs, String output) throws IOException {
    if (inputs.length < 1) {
      return;
    }
    try(FileInputStream fis = new FileInputStream(inputs[0]);
      FileOutputStream fos = new FileOutputStream(new File(output))){
      byte[] buffer = new byte[1024 * 4];
      int total = 0;
      int count;
      while ((count = fis.read(buffer)) > -1) {
        fos.write(buffer, 0, count);
        total += count;
      }
      fis.close();
      for (int i = 1; i < inputs.length; i++) {
        File file = inputs[i];
        try(FileInputStream fisH = new FileInputStream(file)){
          Header header = resolveHeader(fisH);
          FileInputStream dataInputStream = header.dataInputStream;
          while ((count = dataInputStream.read(buffer)) > -1) {
            fos.write(buffer, 0, count);
            total += count;
          }
        }
      }
      fos.flush();
      fos.close();
      FileInputStream fisHo = new FileInputStream(new File(output));
      Header outputHeader = resolveHeader(fisHo);
      outputHeader.dataInputStream.close();
      try(RandomAccessFile res = new RandomAccessFile(output, "rw")){
        res.seek(4);
        byte[] fileLen = intToByteArray(total + outputHeader.dataOffset - 8);
        res.write(fileLen, 0, 4);
        res.seek(outputHeader.dataSizeOffset);
        byte[] dataLen = intToByteArray(total);
        res.write(dataLen, 0, 4);
      }
    }
  }
  /**
   * 解析头部,并获得文件指针指向数据开始位置的InputStreram,记得使用后需要关闭
   */
  private static Header resolveHeader(FileInputStream fis) throws IOException {
      byte[] byte4 = new byte[4];
      byte[] buffer = new byte[2048];
      int readCount = 0;
      Header header = new Header();
      fis.read(byte4);// RIFF
      fis.read(byte4);
      readCount += 8;
      header.fileSizeOffset = 4;
      header.fileSize = byteArrayToInt(byte4);
      fis.read(byte4);// WAVE
      fis.read(byte4);// fmt
      fis.read(byte4);
      readCount += 12;
      int fmtLen = byteArrayToInt(byte4);
      fis.read(buffer, 0, fmtLen);
      readCount += fmtLen;
      fis.read(byte4);// data or fact
      readCount += 4;
      if (isFmt(byte4, 0)) {// 包含fmt段
        fis.read(byte4);
        int factLen = byteArrayToInt(byte4);
        fis.read(buffer, 0, factLen);
        fis.read(byte4);// data
        readCount += 8 + factLen;
      }
      fis.read(byte4);// data size
      int dataLen = byteArrayToInt(byte4);
      header.dataSize = dataLen;
      header.dataSizeOffset = readCount;
      readCount += 4;
      header.dataOffset = readCount;
      header.dataInputStream = fis;
      return header;
  }
  private static boolean isRiff(byte[] bytes, int start) {
    if (bytes[start + 0] == 'R' && bytes[start + 1] == 'I' && bytes[start + 2] == 'F' && bytes[start + 3] == 'F') {
      return true;
    } else {
      return false;
    }
  }
  private static boolean isFmt(byte[] bytes, int start) {
    if (bytes[start + 0] == 'f' && bytes[start + 1] == 'm' && bytes[start + 2] == 't' && bytes[start + 3] == ' ') {
      return true;
    } else {
      return false;
    }
  }
  private static boolean isData(byte[] bytes, int start) {
    if (bytes[start + 0] == 'd' && bytes[start + 1] == 'a' && bytes[start + 2] == 't' && bytes[start + 3] == 'a') {
      return true;
    } else {
      return false;
    }
  }
  /**
   * 将int转化为byte[]
   */
  private static byte[] intToByteArray(int data) {
    return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(data).array();
  }
  /**
   * 将short转化为byte[]
   */
  private static byte[] shortToByteArray(short data) {
    return ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN).putShort(data).array();
  }
  /**
   * 将byte[]转化为short
   */
  private static short byteArrayToShort(byte[] b) {
    return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getShort();
  }
  /**
   * 将byte[]转化为int
   */
  private static int byteArrayToInt(byte[] b) {
    return ByteBuffer.wrap(b).order(ByteOrder.LITTLE_ENDIAN).getInt();
  }
  /**
   * 头部部分信息
   */
  static class Header {
    public int fileSize;
    public int fileSizeOffset;
    public int dataSize;
    public int dataSizeOffset;
    public int dataOffset;
    public FileInputStream dataInputStream;
  }
}

更多关于java算法相关内容感兴趣的读者可查看本站专题:《Java文件与目录操作技巧汇总》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》和《Java缓存操作技巧汇总

希望本文所述对大家java程序设计有所帮助。

相关文章

  • java基于NIO实现群聊模式

    java基于NIO实现群聊模式

    这篇文章主要为大家详细介绍了java实现NIO实现群聊模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • SpringBoot项目防止反编译的方案

    SpringBoot项目防止反编译的方案

    最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去,要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来,所以本文给大家介绍了SpringBoot项目如何防止反编译,需要的朋友可以参考下
    2024-01-01
  • SpringBoot 如何实现自定义Redis序列化

    SpringBoot 如何实现自定义Redis序列化

    这篇文章主要介绍了SpringBoot 如何实现自定义Redis序列化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • java实现多层级zip解压的示例代码

    java实现多层级zip解压的示例代码

    这篇文章主要为大家详细介绍了java实现多层级zip解压的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2024-12-12
  • 利用Java理解sql的语法(实例讲解)

    利用Java理解sql的语法(实例讲解)

    下面小编就为大家分享一篇利用Java理解sql的语法(实例讲解),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • jdk源码阅读Collection详解

    jdk源码阅读Collection详解

    这篇文章主要介绍了jdk源码阅读Collection详解,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • 关于Gateway网关中配置跨域的三种方案

    关于Gateway网关中配置跨域的三种方案

    文章总结:介绍了三种处理跨域请求的方法:在Controller类上添加注解、通过配置类实现重写WebMvcConfigurer接口和在配置文件中统一设置,希望这些方法能帮助读者解决跨域问题
    2024-11-11
  • Java中synchronized实现原理详解

    Java中synchronized实现原理详解

    这篇文章主要介绍了Java中synchronized实现原理详解,涉及synchronized实现同步的基础,Java对象头,Monitor,Mark Word,锁优化,自旋锁等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
    2017-11-11
  • SpringBoot整合Caffeine使用示例

    SpringBoot整合Caffeine使用示例

    Spring Boot 和 Caffeine 可以很容易地进行整合,Caffeine 是一个现代化的 Java 缓存库,提供了高性能和灵活的缓存策略,本文给大家介绍了SpringBoot整合Caffeine使用示例,需要的朋友可以参考下
    2024-07-07
  • springboot连接oracle全流程

    springboot连接oracle全流程

    这篇文章主要介绍了springboot连接oracle全流程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-03-03

最新评论