你好,游客 登录 注册 搜索
背景:
阅读新闻

android录音程序之wav文件头 - KimmKing的技术博客

[日期:2013-03-30] 来源:  作者: [字体: ]

网上搜索到的录音代码里都有一段处理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);
    }








收藏 推荐 打印 | 录入:admin | 阅读:
相关新闻