Android pcm转码wav
2019-12-05 本文已影响0人
CQ_TYL
百度语音识别后生成的语音文件为pcm文件,pcm可以使用ffmpeg进行转码,我自己尝试过使用其他工具转码均失败,其他播放软件直接播放pcm也均是失败!
ffmpeg下载地址:(window64)https://ffmpeg.zeranoe.com/builds/win64/static/

转换命令:
//将pcm文件复制到bin目录,然后命令行直接输入下面命令即可转换后使用常用的音频播放软件播放
ffmpeg -y -f s16le -ac 1 -ar 16000 -i "outfile(2).pcm" -ac 1 -ar 16000 outfile(2).wav
下面直接上android pcm转wav代码:
package com.shiyoukeji.book.activity.SpeechRecongnition;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by tyl
* 2019/12/5/005
* Describe:音频pcm转码wav
*/
public class convertPcmToWav {
/**
* 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);
}
}
调用代码:
String recordFilePath="/storage/emulated/0/dacheASR/outfile.pcm";
String wavFilePath="/storage/emulated/0/dacheASR/outfile.wav";
convertPcmToWav.convertPcmToWav(recordFilePath,wavFilePath,16000,1,16);