zoukankan      html  css  js  c++  java
  • 转载-java将pcm音频转换成wav格式

    原文链接:https://blog.csdn.net/qq_25925973/article/details/90441386

    PCM(Pulse Code Modulation)脉冲编码调制是数字通信的编码方式之一。主要过程是将话音、图像等模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值。

    pcm音频想要直接听需要专业的软件才可以,这里我需要把pcm的音频转化为wav这种无损的格式,也就是需要在pcm文件添加wav的音频头,这样就可以直接使用音频软件打开了。使用Java实现的方式见下文

     1 package com.test.shell;
     2 
     3 import java.io.*;
     4 import com.alibaba.druid.util.StringUtils;
     5 
     6 public class ShellUtils {
     7     public static File tranPcmToWavFile(File pcmFile) {
     8         FileInputStream fis = null;
     9         FileOutputStream fos = null;
    10         try {
    11             fis = new FileInputStream(pcmFile);
    12             String wavfilepath = pcmFile.getAbsolutePath().substring(0, pcmFile.getAbsolutePath().lastIndexOf(".")) + "." + SysConstants.IVR_SPEAK_TYPE_WAV.toLowerCase();
    13 
    14 
    15             File file = new File(wavfilepath);
    16             if (!file.exists()) {
    17                 file.createNewFile();
    18             }
    19             fos = new FileOutputStream(wavfilepath);
    20 
    21 
    22             int PCMSize = 0;
    23             byte[] buf = new byte[1024 * 4];
    24             int size = fis.read(buf);
    25 
    26             while (size != -1) {
    27                 PCMSize += size;
    28                 size = fis.read(buf);
    29             }
    30             fis.close();
    31 
    32             //填入参数,比特率等等。这里用的是16位单声道 8000 hz
    33 
    34             WaveHeader header = new WaveHeader();
    35             //长度字段 = 内容的大小(PCMSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)
    36             header.fileLength = PCMSize + (44 - 8);
    37             header.FmtHdrLeth = 16;
    38             header.BitsPerSample = 16;
    39             header.Channels = 1;
    40             header.FormatTag = 0x0001;
    41             header.SamplesPerSec = 8000;
    42             header.BlockAlign = (short) (header.Channels * header.BitsPerSample / 8);
    43             header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
    44             header.DataHdrLeth = PCMSize;
    45 
    46             byte[] h = header.getHeader();
    47 
    48             assert h.length == 44; //WAV标准,头部应该是44字节
    49             //write header
    50             fos.write(h, 0, h.length);
    51             //write data stream
    52             fis = new FileInputStream(pcmFile);
    53             size = fis.read(buf);
    54             while (size != -1) {
    55                 fos.write(buf, 0, size);
    56                 size = fis.read(buf);
    57             }
    58             fis.close();
    59             fos.close();
    60             return new File(wavfilepath);
    61         } catch (Exception e) {
    62             e.printStackTrace();
    63         } finally {
    64             if (fis != null) {
    65                 try {
    66                     fis.close();
    67                 } catch (IOException e) {
    68                     e.printStackTrace();
    69                 }
    70             }
    71             if (fos != null) {
    72                 try {
    73                     fos.close();
    74                 } catch (IOException e) {
    75                     e.printStackTrace();
    76                 }
    77             }
    78         }
    79         return null;
    80     }
    81 }

    2、其中用到的WaveHeader 如下:

    package com.test.shell;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    
    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);
            }
        }
    }
  • 相关阅读:
    将kali linux装入U盘 制作随身携带的kali linux
    arch/manjaro linux configuration
    python资源

    JSP通过AJAX获取服务端的时间,在页面上自动更新
    Spark基础
    MapReduce基础
    HDFS基础
    C#输出杨辉三角形
    Java窗体居中显示的2种方法
  • 原文地址:https://www.cnblogs.com/hxz-nl/p/12619754.html
Copyright © 2011-2022 走看看