Android PCM文件转WAV文件

  

之前对android音频方面根本不了解,找了很多博客都没找到合适自己的,顺便看了很多代码,发现pcm基本上所有的音频格式都能转,我项目里面用到的就是wav的,所以这里贴一下pcm转wav的代码,之前看到一位大佬说wav的头文件很简单,反正我是没看懂,菜得哭.....


顺便祝涵宝宝新年快乐~么么哒


/**
 * PCM文件转WAV文件
 *
 * @param inPcmFilePath  输入PCM文件路径
 * @param outWavFilePath 输出WAV文件路径
 * @param sampleRate     采样率,例如15000
 * @param channels       声道数 单声道:1或双声道:2
 * @param bitNum         采样位数,8或16
 */
public static void convertPcmToWav(String inPcmFilePath, String outWavFilePath,
                                   int sampleRate,
                                   int channels, int bitNum) {
    FileInputStream in = null;
    FileOutputStream out = null;
    byte[] data = new byte[1024];

    try {
        //采样字节byte率
        long byteRate = sampleRate * channels * bitNum / 8;

        in = new FileInputStream(inPcmFilePath);
        out = new FileOutputStream(outWavFilePath);

        //PCM文件大小
        long totalAudioLen = in.getChannel().size();

        //总大小,由于不包括RIFF和WAV,所以是44 - 8 = 36,在加上PCM文件大小
        long totalDataLen = totalAudioLen + 36;

        writeWaveFileHeader(out, totalAudioLen, totalDataLen, sampleRate, channels, byteRate);

        int length = 0;
        while ((length = in.read(data)) > 0) {
            out.write(data, 0, length);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 输出WAV文件
 *
 * @param out           WAV输出文件流
 * @param totalAudioLen 整个音频PCM数据大小
 * @param totalDataLen  整个数据大小
 * @param sampleRate    采样率
 * @param channels      声道数
 * @param byteRate      采样字节byte率
 * @throws IOException
 */
private static void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                        long totalDataLen, int sampleRate, int channels, long byteRate) throws IOException {
    byte[] header = new byte[44];
    header[0] = 'R'; // RIFF
    header[1] = 'I';
    header[2] = 'F';
    header[3] = 'F';
    header[4] = (byte) (totalDataLen & 0xff);//数据大小
    header[5] = (byte) ((totalDataLen >> 8) & 0xff);
    header[6] = (byte) ((totalDataLen >> 16) & 0xff);
    header[7] = (byte) ((totalDataLen >> 24) & 0xff);
    header[8] = 'W';//WAVE
    header[9] = 'A';
    header[10] = 'V';
    header[11] = 'E';
    //FMT Chunk
    header[12] = 'f'; // 'fmt '
    header[13] = 'm';
    header[14] = 't';
    header[15] = ' ';//过渡字节
    //数据大小
    header[16] = 16; // 4 bytes: size of 'fmt ' chunk
    header[17] = 0;
    header[18] = 0;
    header[19] = 0;
    //编码方式 10H为PCM编码格式
    header[20] = 1; // format = 1
    header[21] = 0;
    //通道数
    header[22] = (byte) channels;
    header[23] = 0;
    //采样率,每个通道的播放速度
    header[24] = (byte) (sampleRate & 0xff);
    header[25] = (byte) ((sampleRate >> 8) & 0xff);
    header[26] = (byte) ((sampleRate >> 16) & 0xff);
    header[27] = (byte) ((sampleRate >> 24) & 0xff);
    //音频数据传送速率,采样率*通道数*采样深度/8
    header[28] = (byte) (byteRate & 0xff);
    header[29] = (byte) ((byteRate >> 8) & 0xff);
    header[30] = (byte) ((byteRate >> 16) & 0xff);
    header[31] = (byte) ((byteRate >> 24) & 0xff);
    // 确定系统一次要处理多少个这样字节的数据,确定缓冲区,通道数*采样位数
    header[32] = (byte) (channels * 16 / 8);
    header[33] = 0;
    //每个样本的数据位数
    header[34] = 16;
    header[35] = 0;
    //Data chunk
    header[36] = 'd';//data
    header[37] = 'a';
    header[38] = 't';
    header[39] = 'a';
    header[40] = (byte) (totalAudioLen & 0xff);
    header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
    header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
    header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
    out.write(header, 0, 44);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值