关闭

Android进阶——pcm格式转wav格式

标签: pcmwav讯飞
4292人阅读 评论(6) 收藏 举报
分类:

背景

程序中的录音文件之前直接保存的是 .pcm格式,一直也相安无事,用的挺好。最近有一个webview中需要加载录音文件,出现了不兼容的问题,所以需要把 .pcm格式文件转换为 .wav格式。

PCM

PCM(Pulse Code Modulation----脉码调制录音)。所谓PCM录音就是将声音等模拟信号变成符号化的脉冲列,再予以记录。PCM信号是由[1]、[0]等符号构成的数字信号,而未经过任何编码和压缩处理。与模拟信号比,它不易受传送系统的杂波及失真的影响。动态范围宽,可得到音质相当好的效果。简单的说,pcm就是没有压缩的音频格式。

wav

wav全称是WAVE,.wav是其扩展名,它是一种无损的音频文件格式,WAV符合 RIFF(Resource Interchange File Format)规范。所有的WAV都有一个文件头,这个文件头是音频流的编码参数。WAV对音频流的编码没有硬性规定,除了PCM之外,还有几乎所有支持ACM规范的编码都可以为WAV的音频流进行编码。

pcm和wav关系

pcm是无损wav文件中音频数据的一种编码方式,pcm加上wav文件头就可以转为wav格式,但wav还可以用其它方式编码。

PcmToWavUtil

package com.hgb.mytest;

import android.media.AudioFormat;
import android.media.AudioRecord;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by HaoGuibao
 * Date 2016/8/26.
 * Description :pcm格式的音频转换为wav格式的工具类
 */
public class PcmToWavUtil {
    private int mBufferSize;  //缓存的音频大小
    private int mSampleRate = 8000;// 8000|16000
    private int mChannel = AudioFormat.CHANNEL_IN_STEREO;   //立体声
    private int mEncoding = AudioFormat.ENCODING_PCM_16BIT;

    public PcmToWavUtil() {
        this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, mEncoding);
    }

    /**
     * @param sampleRate sample rate、采样率
     * @param channel    channel、声道
     * @param encoding   Audio data format、音频格式
     */
    public PcmToWavUtil(int sampleRate, int channel, int encoding) {
        this.mSampleRate = sampleRate;
        this.mChannel = channel;
        this.mEncoding = encoding;
        this.mBufferSize = AudioRecord.getMinBufferSize(mSampleRate, mChannel, mEncoding);
    }

    /**
     * pcm文件转wav文件
     *
     * @param inFilename  源文件路径
     * @param outFilename 目标文件路径
     */
    public void pcmToWav(String inFilename, String outFilename) {
        FileInputStream in;
        FileOutputStream out;
        long totalAudioLen;
        long totalDataLen;
        long longSampleRate = mSampleRate;
        int channels = 2;
        long byteRate = 16 * mSampleRate * channels / 8;
        byte[] data = new byte[mBufferSize];
        try {
            in = new FileInputStream(inFilename);
            out = new FileOutputStream(outFilename);
            totalAudioLen = in.getChannel().size();
            totalDataLen = totalAudioLen + 36;

            writeWaveFileHeader(out, totalAudioLen, totalDataLen,
                    longSampleRate, channels, byteRate);
            while (in.read(data) != -1) {
                out.write(data);
            }
            in.close();
            out.close();
        }  catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 加入wav文件头
     */
    private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                     long totalDataLen, long longSampleRate, int channels, long byteRate)
            throws IOException {
        byte[] header = new byte[44];
        header[0] = 'R'; // RIFF/WAVE header
        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';
        header[12] = 'f'; // 'fmt ' chunk
        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;
        header[20] = 1;   // format = 1
        header[21] = 0;
        header[22] = (byte) channels;
        header[23] = 0;
        header[24] = (byte) (longSampleRate & 0xff);
        header[25] = (byte) ((longSampleRate >> 8) & 0xff);
        header[26] = (byte) ((longSampleRate >> 16) & 0xff);
        header[27] = (byte) ((longSampleRate >> 24) & 0xff);
        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) (2 * 16 / 8); // block align
        header[33] = 0;
        header[34] = 16;  // bits per sample
        header[35] = 0;
        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);
    }
}

Demo

把手机内存卡上 /sdcard/yxck/treamentRecord/ 的123.pcm转换为123.wav文件
public class MainActivity extends AppCompatActivity {
    /**
     * pcm格式转wav格式工具类
     */
    private PcmToWavUtil pcmToWavUtil = new PcmToWavUtil();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final String path = "/sdcard/yxck/treamentRecord/123.pcm";
        //按原路径把音频文件后缀改一下;
        final String outpath = path.replace(".pcm", ".wav");

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pcmToWavUtil.pcmToWav(path, outpath);
            }
        });
    }
}
pcm转换wav格式成功

参考文章
http://www.360doc.com/content/14/0304/15/2306903_357656935.shtml
http://www.cnblogs.com/lidabo/p/3729615.html
http://blog.csdn.net/u014040795/article/details/52188978


1
1
查看评论

【Android】AudioRecord--录音并将 PCM文件转为WAV

前言Android提供可以用来录音的有AudioRecord和MediaRecord,通过MediaRecord录音,我们可以选择所要录音的格式,然后录完之后,自动生成这种格式的文件,而AudioRecord得到的是PCM编码格式的数据,因此如果我们要对录音的数据做处理,显然我们需要的是通过后者,同...
  • JenseaChen
  • JenseaChen
  • 2015-07-14 20:48
  • 4303

PCM到WAV的转换(Java)

公司的另一个产品,监控CTI的时候录音的格式是PCM. 为了能在IE里面播放, 需要转换成标准的WAV. 以前用的是一个COM库来做转换, 现在因为各种原因不能用那个库了(64位支持不好等等),就用Java实现了一个。基本代码如下。 其实WAV只是PCM文件加上相关的文件头和
  • xiunai78
  • xiunai78
  • 2011-10-12 18:03
  • 9776

PCM 转换为 WAV (java)

package com.example.pcm2wave; import java.io.ByteArrayOutputStream; import java.io.IOException; public class WaveHeader { private char...
  • u013611548
  • u013611548
  • 2016-12-27 15:23
  • 1147

PCM文件转WAV文件

PCM文件转WAV文件 Intel数端方式 VC C++
  • lee353086
  • lee353086
  • 2010-07-30 15:12
  • 8681

PCM转WAV格式 Wav数据格式的44个字节头部信息汇总

http://ikinglai.blog.51cto.com/6220785/1224481 一般通过麦克风采集的录音数据都是PCM格式的,即不包含头部信息,这样导致很多播放器都播放不了,你只能用像Audition这样的专业工具才能进行播放,显然是非常不方便的。为了得到wav格式的录音数据,我...
  • jeffasd
  • jeffasd
  • 2017-05-18 14:10
  • 707

PCM到WAV的转换(java)

其实WAV只是PCM文件加上相关的文件头和描述信息,不算复杂。这段程序参考了网上的一些实现(C/C++),修改了其中的一些错误,比如转换后的文件能够播放但是时间长度是错误的;或者不能拖动等等。 代码见下。 private void convertAudioFiles(String s...
  • u013611548
  • u013611548
  • 2016-12-27 15:19
  • 1229

PCM转WAV

WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型,属于无损音乐格式的一种。 WAV文件的文件头: 偏移地址 大小 字节 数据块 类型 内容 00H~03H ...
  • boywgw
  • boywgw
  • 2015-10-13 15:38
  • 1245

wav 与 pcm 互转

语音wav转pcm可以用ffmpeg工具,也可以自己写,主要是要了解pcm和wav的格式以及头信息的: pcm 是没有头信息的,wav有44字节的头文件,所以去掉44字节的头文件就okay了import os import numpy as np f = open("sw02725-A_0...
  • zjm750617105
  • zjm750617105
  • 2017-05-11 21:11
  • 2631

pcm转wav的方法及代码示例

pcm文件转wav文件 pcm wav 格式转换
  • lzyzuixin
  • lzyzuixin
  • 2016-07-06 12:03
  • 3921

利用FFmpeg将pcm文件转成wav文件

现在需要利用cool edit对一批pcm音频文件进行分析。由于没有相关信息指定音频的采样率,信道数和精度,所以cool edit在打开一个pcm的时候需要让我们指定相关参数。当需要分析的pcm非常多时,每次都需要指定相关参数就显得非常麻烦。我们可以给pcm文件添加一个wav文件头来指定相关参数,从...
  • yutianzuijin
  • yutianzuijin
  • 2017-03-12 14:24
  • 4503
    个人资料
    • 访问:391654次
    • 积分:6520
    • 等级:
    • 排名:第4395名
    • 原创:99篇
    • 转载:12篇
    • 译文:0篇
    • 评论:1512条
    联系我
    QQ交流群 559136449
    博客专栏