【android 】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);
}

 

posted @ 2023-02-16 10:01  opensmarty  阅读(131)  评论(0编辑  收藏  举报