1、前言
参考 java将pcm音频转换成wav格式
2、关键代码
| public void pcmByteToWavFile(byte[] pcmData, String fileName) { |
| FileOutputStream fos = null; |
| try { |
| fos = new FileOutputStream(fileName); |
| |
| WaveHeader header = new WaveHeader(); |
| |
| 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; |
| 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); |
| |
| WaveHeader header = new WaveHeader(); |
| |
| 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; |
| 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); |
| } |
| } |
| } |
| } |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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 语句简化迭代器