网上搜索到的录音代码里都有一段处理wav文件头的代码:
/** * 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。 * 为我为啥插入这44个字节,这个还真没深入研究,不过你随便打开一个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'; 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'; 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); }
反编译出来原音录音机,可以看到类似的处理:
private static byte[] intToByteArray(int paramInt) { byte[] arrayOfByte = new byte[4]; arrayOfByte[0] = (byte)(paramInt & 0xFF); arrayOfByte[1] = (byte)(0xFF & paramInt >> 8); arrayOfByte[2] = (byte)(0xFF & paramInt >> 16); arrayOfByte[3] = (byte)(0xFF & paramInt >> 24); return arrayOfByte; } private static byte[] shortToByteArray(short paramShort) { byte[] arrayOfByte = new byte[2]; arrayOfByte[0] = (byte)(paramShort & 0xFF); arrayOfByte[1] = (byte)(0xFF & paramShort >>> 8); return arrayOfByte; } private void writerHeader(RandomAccessFile paramRandomAccessFile, int paramInt) throws IOException { if (this.waveFile == null) return; paramRandomAccessFile.writeBytes("RIFF"); paramRandomAccessFile.write(intToByteArray(paramInt + 24), 0, 4); paramRandomAccessFile.writeBytes("WAVE"); paramRandomAccessFile.writeBytes("fmt "); paramRandomAccessFile.write(intToByteArray(16), 0, 4); paramRandomAccessFile.write(shortToByteArray(1), 0, 2); paramRandomAccessFile.write(shortToByteArray((short)this.channels), 0, 2); paramRandomAccessFile.write(intToByteArray(this.sampleRate), 0, 4); paramRandomAccessFile.write(intToByteArray(this.byteRate * this.sampleRate * this.channels), 0, 4); paramRandomAccessFile.write(shortToByteArray((short)(this.byteRate * this.channels)), 0, 2); paramRandomAccessFile.write(shortToByteArray((short)(8 * this.byteRate)), 0, 2); paramRandomAccessFile.writeBytes("data"); paramRandomAccessFile.write(intToByteArray(paramInt), 0, 4); }
可以看到,其中有几个参数是跟byteRate和channels有关的,如果前面的几个参数调整,会影响这两个参数,而网上的代码是写死的。
另外常用的几个音质的参数:
WAVE_STEREO_44K_16B = new AudioSetting(44100, 12, 12, 2, 2, 2, "CD 音质", FileType.Wav); WAVE_STEREO_22K_16B = new AudioSetting(22050, 12, 12, 2, 2, 2, "Half CD 音质", FileType.Wav); WAVE_STEREO_16K_8B = new AudioSetting(16000, 12, 12, 3, 2, 1, "VoIP 音质", FileType.Wav); WAVE_STEREO_8K_8B = new AudioSetting(8000, 12, 12, 3, 2, 1, "电话音质", FileType.Wav); WAVE_MONO_44K_16B = new AudioSetting(44100, 16, 4, 2, 1, 2, "CD 音质", FileType.Wav); WAVE_MONO_16K_8B = new AudioSetting(16000, 16, 4, 3, 1, 1, "VoIP 音质", FileType.Wav); MP3_STEREO_44K_16B_128 = new MP3AudioSetting(44100, 12, 12, 2, 2, 2, "CD 音质", FileType.MP3, 128); MP3_MONO_44K_16B_128 = new MP3AudioSetting(44100, 16, 4, 2, 1, 2, "CD 音质", FileType.MP3, 128); MP3_STEREO_44K_16B_160 = new MP3AudioSetting(44100, 12, 12, 2, 2, 2, "CD 音质", FileType.MP3, 160); MP3_MONO_44K_16B_160 = new MP3AudioSetting(44100, 16, 4, 2, 1, 2, "CD 音质", FileType.MP3, 160); MP3_STEREO_44K_16B_192 = new MP3AudioSetting(44100, 12, 12, 2, 2, 2, "CD 音质", FileType.MP3, 192); MP3_MONO_44K_16B_192 = new MP3AudioSetting(44100, 16, 4, 2, 1, 2, "CD 音质", FileType.MP3, 192);
另外发现获取到最低缓冲区大小后,创建Record时可以使用最低缓冲区大小的多倍作为参数。
this.audioRecord = new AudioRecord(1, this.setting.sampleRate, this.setting.inChannelConfiguration, this.setting.audioEncoding, 2 * this.setting.inBufferSize); this.audioRecord = new AudioRecord(1, this.setting.sampleRate, this.setting.inChannelConfiguration, this.setting.audioEncoding, 10 * this.setting.inBufferSize);
创建后,可以使用下面的代码判断Record的状态。
if (this.audioRecord.getState() == 0) { this.audioRecord = null; throw new AudioDeviceException(AudioDeviceException.DEVICE_TYPE_RECORD); }