java 将pcm字节数组转为wav文件

1、前言

参考 java将pcm音频转换成wav格式

2、关键代码

public void pcmByteToWavFile(byte[] pcmData, String fileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(fileName);
//填入参数,比特率等等。这里用的是16位 双声道 48000 hz
WaveHeader header = new WaveHeader();
//长度字段 = 内容的大小(PCMSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)
header.fileLength = pcmData.length + (44 - 8);
header.FmtHdrLeth = 16;
header.BitsPerSample = 16;//比特率
header.Channels = 2;//双通道
header.FormatTag = 0x0001;
header.SamplesPerSec = 48000;//采样率
header.BlockAlign = (short) (header.Channels * header.BitsPerSample / 8);
header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
header.DataHdrLeth = pcmData.length;
byte[] headerBytes = header.getHeader();
assert headerBytes.length == 44; //WAV标准,头部应该是44字节
byte[] byteResult = new byte[headerBytes.length + pcmData.length];
System.arraycopy(headerBytes, 0, byteResult, 0, headerBytes.length);
System.arraycopy(pcmData, 0, byteResult, headerBytes.length, pcmData.length);
fos.write(byteResult, 0, byteResult.length);
fos.flush();
fos.close();
} catch (Exception e) {
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}

3、代码

package com.ruoyi.project.utils;
import java.io.*;
public class AudioUtil {
private static AudioUtil Instance = new AudioUtil();
public static AudioUtil getInstance() {
return Instance;
}
public void pcmByteToWavFile(byte[] pcmData, String fileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(fileName);
//填入参数,比特率等等。这里用的是16位 双声道 48000 hz
WaveHeader header = new WaveHeader();
//长度字段 = 内容的大小(PCMSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)
header.fileLength = pcmData.length + (44 - 8);
header.FmtHdrLeth = 16;
header.BitsPerSample = 16;//比特率
header.Channels = 2;//双通道
header.FormatTag = 0x0001;
header.SamplesPerSec = 48000;//采样率
header.BlockAlign = (short) (header.Channels * header.BitsPerSample / 8);
header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
header.DataHdrLeth = pcmData.length;
byte[] headerBytes = header.getHeader();
assert headerBytes.length == 44; //WAV标准,头部应该是44字节
byte[] byteResult = new byte[headerBytes.length + pcmData.length];
System.arraycopy(headerBytes, 0, byteResult, 0, headerBytes.length);
System.arraycopy(pcmData, 0, byteResult, headerBytes.length, pcmData.length);
fos.write(byteResult, 0, byteResult.length);
fos.flush();
fos.close();
} catch (Exception e) {
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
public class WaveHeader {
public final char fileID[] = {'R', 'I', 'F', 'F'};
public int fileLength;
public char wavTag[] = {'W', 'A', 'V', 'E'};
;
public char FmtHdrID[] = {'f', 'm', 't', ' '};
public int FmtHdrLeth;
public short FormatTag;
public short Channels;
public int SamplesPerSec;
public int AvgBytesPerSec;
public short BlockAlign;
public short BitsPerSample;
public char DataHdrID[] = {'d', 'a', 't', 'a'};
public int DataHdrLeth;
public byte[] getHeader() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
WriteChar(bos, fileID);
WriteInt(bos, fileLength);
WriteChar(bos, wavTag);
WriteChar(bos, FmtHdrID);
WriteInt(bos, FmtHdrLeth);
WriteShort(bos, FormatTag);
WriteShort(bos, Channels);
WriteInt(bos, SamplesPerSec);
WriteInt(bos, AvgBytesPerSec);
WriteShort(bos, BlockAlign);
WriteShort(bos, BitsPerSample);
WriteChar(bos, DataHdrID);
WriteInt(bos, DataHdrLeth);
bos.flush();
byte[] r = bos.toByteArray();
bos.close();
return r;
}
private void WriteShort(ByteArrayOutputStream bos, int s) throws IOException {
byte[] mybyte = new byte[2];
mybyte[1] = (byte) ((s << 16) >> 24);
mybyte[0] = (byte) ((s << 24) >> 24);
bos.write(mybyte);
}
private void WriteInt(ByteArrayOutputStream bos, int n) throws IOException {
byte[] buf = new byte[4];
buf[3] = (byte) (n >> 24);
buf[2] = (byte) ((n << 8) >> 24);
buf[1] = (byte) ((n << 16) >> 24);
buf[0] = (byte) ((n << 24) >> 24);
bos.write(buf);
}
private void WriteChar(ByteArrayOutputStream bos, char[] id) {
for (int i = 0; i < id.length; i++) {
char c = id[i];
bos.write(c);
}
}
}
}
posted @   一只桔子2233  阅读(1190)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2020-11-25 Jquery off() on() data()
2018-11-25 6.2 C# 2:利用 yield 语句简化迭代器
点击右上角即可分享
微信分享提示