Java实现多个wav文件合成一个的方法示例
作者:大爱一生 发布时间:2021-10-08 08:14:25
标签:Java,wav文件,合成
本文实例讲述了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程序设计有所帮助。
来源:https://blog.csdn.net/weixin_39372979/article/details/80493719


猜你喜欢
- 如下所示:<?xml version="1.0" encoding="utf-8"?>&
- 使用Convert接口实现类型转换器在Spring3中引入了一个Converter接口,它支持从一个Object转为另一个Object。除了
- SpringMVC获取表单数据1、实体类package cn.hadron.bean;import java.io.Serializable
- 安装配置完Java的jdk,下面就开始写第一个java程序--hello World.用来在控制台输出“Hello World”。首先,我们
- 享元模式概述享元模式(Flyweight Pattern)又称为轻量级模式,是对象池的一种实现。属于结构型模式。类似于线程池,线程池可以避免
- 本文实例为大家分享了Unity动画混合树实例代码,供大家参考,具体内容如下先看效果游戏动画中的一项常见任务是在两个或更多相似运动之间进行混合
- 第9版《Java核心技术卷Ⅰ》的第607页介绍了一个方法:Collections类中的sort方法可以对实现了List接口的集合进行排序。这
- 扇形统计图绘制一个扇形原理也是基于Canvas进行绘制;ArcSegment[1]绘制弧形;绘制指示线;绘制文本;鼠标移入动画;显示详情Po
- 一、Statementimport java.sql.*;public class TestJDBC { public stati
- 本文实例为大家分享了Android实现简单画图画板的具体代码,供大家参考,具体内容如下效果如图:布局文件:<RelativeLayou
- 文件的上传与下载(一)在实现文件上传和下载之前我们需要做一些准备工作,在Apache官网去下载文件上传下载的两个组件,下载链接这里给出:co
- 由于一个项目的需要,我研究了一下android的网络通信方式,大体和java平台的很相似! android平台也提供了很多的AP
- java 实现随机数组输出及求和问题描述:随机生成10个数,填充一个数组,然后用消息框显示数组内容,接着计算数组元素的和,将结果也显示在消息
- 本文开始做一个网上商城的项目,首先从搭建环境开始,一步步
- 1 ArrayList在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:说明:ArrayList实现了Ra
- 实例如下:MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean(); &
- 我们在日常开发中,经常会遇到类似的场景:当要做一件事儿的时候,这件事儿的步骤是固定好的,但是每一个步骤的具体实现方式是不一定的。通常,遇到这
- 本文为大家分享Android自定义Spinner适配器的相关知识点,供大家参考,具体内容如下一、大致效果二.关键代码在注释中讲重点吧。 (1
- Java 序列化和反序列化实例详解在分布式应用中,对象只有经过序列化才能在各个分布式组件之间传输,这就涉及到两个方面的技术-发送者将对象序列
- ShardingSphereShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、