最近在学习Android 音频这块相关支持,发现用AudioRecord录制PCM音频直接保存在本地后无法播放,需将PCM数据转成WAV格式保存。生成WAV时需要给文件添加一个头部如下:
参考文章
/**
* 加入wav文件头
*/
private void writeWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen,
long longSampleRate, int channels, long byteRate) throws IOException {
byte[] header = new byte[44];
// RIFF/WAVE header
header[0] = 'R';
header[1] = 'I';
header[2] = 'F';
header[3] = 'F';
//文件长度 音频数据长度+头部44-8(不包含前8位)
header[4] = (byte) (totalDataLen & 0xff);
header[5] = (byte) ((totalDataLen >> 8) & 0xff);
header[6] = (byte) ((totalDataLen >> 16) & 0xff);
header[7] = (byte) ((totalDataLen >> 24) & 0xff);
//WAVE
header[8] = 'W';
header[9] = 'A';
header[10] = 'V';
header[11] = 'E';
// 'fmt ' chunk
header[12] = 'f';
header[13] = 'm';
header[14] = 't';
header[15] = ' ';
// 4 bytes: size of 'fmt ' chunk
//过滤字节 (一般为00000010H 也就是16)
header[16] = 16;
header[17] = 0;
header[18] = 0;
header[19] = 0;
// 格式format = 1 值为1时,表示数据为线性PCM编码
header[20] = 1;
header[21] = 0;
//通道数,单声道为1,双声道为2
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);
//波形音频数据传送速率,其值为通道数×每秒数据位数×每样本的数据位数/8
header[28] = (byte) (byteRate & 0xff);
header[29] = (byte) ((byteRate >> 8) & 0xff);
header[30] = (byte) ((byteRate >> 16) & 0xff);
header[31] = (byte) ((byteRate >> 24) & 0xff);
//data数据块长度
header[32] = (byte) (2 * 16 / 8);
header[33] = 0;
// PCM位宽
header[34] = 16;
header[35] = 0;
//data数据头
header[36] = 'd';
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);
}
可以看到WAV头部由44个字节组成
0-3 | 固定为"RIFF" |
4-7 | 文件长度 音频数据长度+头部44-8(不包含前8位) |
8-11 | "AVI " 或 "WAVE"具体 |
12-15 | "fmt"标志 |
16-19 | 过滤字节 (一般为00000010H 也就是16) |
20-21 | 格式format = 1 值为1时,表示数据为线性PCM编码 |
22-23 | 通道数,单声道为1,双声道为2 |
24-27 | 采样率 |
28-31 | 波形音频数据传送速率,其值为通道数×每秒数据位数×每样本的数据位数/8 |
32-33 | data数据块长度 |
34-35 | PCM位宽 |
36-39 | data数据头 |
40-43 | 文件长度 |
上面可以看到WAV头部的组成部分,但很多具体地方还是一知半解,后续继续补充……