參考文章:https://blog.csdn.net/hesong1120/article/details/79043482
最近工作開發(fā)中茉稠,碰到一個BUG,由于WebApp開發(fā)钾麸,一套H5代碼適用于Android和IOS,但是發(fā)語音時,Android無法打開IOS的pcm格式文件穷蛹,而IOS同樣無法打開Android的wav格式文件。很尷尬沐绒,嘗試了直接改文件后綴名強轉(zhuǎn)俩莽,可惜會損壞文件。那么只有轉(zhuǎn)碼這一條路可以走了乔遮。
Android中扮超,想要播放,那么就需要單獨判斷pcm文件蹋肮,轉(zhuǎn)碼給wav出刷,再使用mediaplayer播放。
先上代碼:
/**
* PCM文件轉(zhuǎn)WAV文件
* @param inPcmFilePath 輸入PCM文件路徑
* @param outWavFilePath 輸出WAV文件路徑
* @param sampleRate 采樣率坯辩,例如15000
* @param channels 聲道數(shù) 單聲道:1或雙聲道:2
* @param bitNum 采樣位數(shù)馁龟,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 {
//采樣字節(jié)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數(shù)據(jù)大小
* @param totalDataLen 整個數(shù)據(jù)大小
* @param sampleRate 采樣率
* @param channels 聲道數(shù)
* @param byteRate 采樣字節(jié)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);//數(shù)據(jù)大小
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] = ' ';//過渡字節(jié)
//數(shù)據(jù)大小
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;
//通道數(shù)
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);
//音頻數(shù)據(jù)傳送速率,采樣率*通道數(shù)*采樣深度/8
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
// 確定系統(tǒng)一次要處理多少個這樣字節(jié)的數(shù)據(jù)改抡,確定緩沖區(qū)矢炼,通道數(shù)*采樣位數(shù)
header[32] = (byte) (channels * 16 / 8);
header[33] = 0;
//每個樣本的數(shù)據(jù)位數(shù)
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);
}
詳細的音頻知識筆者一知半解,想要了解的朋友可以查看上面的參考文章阿纤,有詳細介紹句灌。調(diào)用convertPcmToWav方法可以將pcm文件轉(zhuǎn)化成wav文件。下面是筆者在項目中的使用方法:
if(end.equals("pcm")){
String pcmPath=f.getPath();
String wavPath=f.getPath().replace("pcm","wav");
AudioRecoderUtils audioRecoderUtils=AudioRecoderUtils.getInstance();
audioRecoderUtils.convertPcmToWav(pcmPath,wavPath,15000,1,8);
audioRecoderUtils.playerStart(wavPath);
}
End
筆者的Github Blog欠拾,希望各位大大提意見胰锌,點個star,謝謝
傳送門:WusyBlog求互粉互贊藐窄,互贊所有文章可以私聊我资昧。哈哈,希望我們的原創(chuàng)文章能讓更多朋友看到荆忍,一起變強榛搔。
筆者新開通了微信公眾號——飲水思源|wusy 計劃持續(xù)運營诺凡,每日為您分享Android干貨、原創(chuàng)文章践惑。微信掃描下方的二維碼關(guān)注我腹泌,開發(fā)學(xué)習(xí)路上不迷路。謝謝各位
飲水思源|wusy.jpg