??? }
??? in.close(); ??? out.close();
??? } catch (FileNotFoundException e) { ??? e.printStackTrace(); ??? } catch (IOException e) { ??? e.printStackTrace(); ??? } ??? } ??? ??? /**
??? * 这里提供一个头信息。插入这些信息就可以得到可以播放的文件。 ??? * 为我为啥插入这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); ??? } ???
??? @Override
??? protected void onDestroy() { ??? close();
??? super.onDestroy(); ??? } ??? }
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Android入门(9)AudioRecord和AudioTrack类的使用 (2010-05-07 09:07:05
AudioRecord和AudioTrack类是Android获取和播放音频流的重要类,放置在android.media包中。与该包中的MediaRecorder和MediaPlayer类不同,AudioRecord和AudioTrack类在获取和播放音频数据流时无需通过文件保存和文件读取,可以动态地直接获取和播放音频流,在实时处理音频数据流时非常有用。
当然,如果用户只想录音后写入文件或从文件中取得音频流进行播放,那么直接使用MediaRecorder和MediaPlayer类是首选方案,因为这两个类使用非常方便,而且成功率很高。而AudioRecord和AudioTrack类的使用却比较复杂,我们发现很多人都不能成功
地使用这两个类,甚至认为Android的这两个类是不能工作的。
其实,AudioRecord和AudioTrack类的使用虽然比较复杂,但是可以工作,我们不仅可以很好地使用了这两个类,而且还通过套接字(Socket)实现了音频数据的网络传输,做到了一端使用AudioRecord获取音频流然后通过套接字传输出去,而另一端通过套接字接收后使用AudioTrack类播放。
下面是我们对AudioRecord和AudioTrack类在使用方面的经验总结:
(1)创建AudioRecord和AudioTrack类对象:创建这两个类的对象比较复杂,通过对文档的反复和仔细理解,并通过多次失败的尝试,并在北理工的某个Android大牛的网上的文章启发下,我们也最终成功地创建了这两个类的对象。创建AudioRecord和AudioTrack类对象的代码如下: AudioRecord类:
m_in_buf_size =AudioRecord.getMinBufferSize(8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
m_in_rec = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,
AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, m_in_buf_size) ; AudioTrack类: