在android中如果需要录制PCM流需要用到AudioRecord这个类,然后播放的话需要用AudioTrack
先看下效果图:
好了我们先看下如何录制PCM,看下核心代码
try {
//输出流
OutputStream os = new FileOutputStream(recordFile);
BufferedOutputStream bos = new BufferedOutputStream(os);
DataOutputStream dos = new DataOutputStream(bos);
/**
* android.media.AudioRecord public static int getMinBufferSize(int
sampleRateInHz,int channelConfig,int audioFormat)
返回成功创建 AudioRecord 对象所需的最小缓冲区大小,以字节为单位。 请注意,此大小
不能保证在负载下顺利录制,应根据 AudioRecord 实例轮询新数据的预期频率选择更高的
值。 有关有效配置值的更多信息,请参阅AudioRecord(int, int, int, int, int) 。
参数:
sampleRateInHz – 以赫兹表示的采样率。 AudioFormat.SAMPLE_RATE_UNSPECIFIED是不允许的。
channelConfig – 描述音频通道的配置。 请参阅AudioFormat.CHANNEL_IN_MONO和
AudioFormat.CHANNEL_IN_STEREO
audioFormat – 表示音频数据的格式。 请参阅AudioFormat.ENCODING_PCM_16BIT 。
回报:
ERROR_BAD_VALUE如果硬件不支持录制参数,或者传递了无效参数,或者如果实现无法查询
硬件以获取其输入属性或以字节表示的最小缓冲区大小,则为ERROR
*/
int bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, AudioFormat.CHANNEL_IN_STEREO, audioEncoding);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, AudioFormat.CHANNEL_IN_STEREO, audioEncoding, bufferSize);
short[] buffer = new short[bufferSize];
audioRecord.startRecording();
Log.e(TAG, "开始录音");
isRecording = true;
while (isRecording) {
int bufferReadResult = audioRecord.read(buffer, 0, bufferSize);
for (int i = 0; i < bufferReadResult; i++) {
dos.writeShort(buffer[i]);
}
}
audioRecord.stop();
dos.close();
} catch (Throwable t) {
Log.e(TAG, "录音失败");
showToast("录音失败");
}
再看下播放pcm,分两种
1.一次性读取所有pcm数据后在播放这种适合数据小的pcm流
2.一边读取pcm流一边播放,这种适合比较大的数据流
先看一次性读取的代码
int musicLength = (int) (recordFile.length() / 2);
short[] music = new short[musicLength];
try {
InputStream is = new FileInputStream(recordFile);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
int i = 0;
while (dis.available() > 0) {
music[i] = dis.readShort();
i++;
}
dis.close();
/**
android.media.AudioTrack public static int getMinBufferSize(int
sampleRateInHz, int channelConfig, int audioFormat)
返回在MODE_STREAM模式下创建的 AudioTrack 对象所需的估计最小缓冲区大小。 大小是一个
估计值,因为它既不考虑路由也不考虑汇,因为两者都不知道。 请注意,此大小并不能保证在
负载下流畅播放,应根据缓冲区重新填充要播放的其他数据的预期频率选择更高的值。 例如,
如果您打算将 AudioTrack 的源采样率动态设置为高于初始源采样率的值,请务必根据计划的
最高采样率配置缓冲区大小。
参数:
sampleRateInHz – 以 Hz 表示的源采样率。 不允许
AudioFormat.SAMPLE_RATE_UNSPECIFIED 。
channelConfig – 描述音频通道的配置。 请参阅AudioFormat.CHANNEL_OUT_MONO和
AudioFormat.CHANNEL_OUT_STEREO
audioFormat – 表示音频数据的格式。 请参阅AudioFormat.ENCODING_PCM_16BIT和
AudioFormat.ENCODING_PCM_8BIT和AudioFormat.ENCODING_PCM_FLOAT 。
返回:
如果传递了无效参数,则为ERROR_BAD_VALUE如果无法查询输出属性,则为ERROR ,或者以字
节为单位表示的 最小缓冲区大小
*
*/
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz, channelConfiguration, audioEncoding, musicLength * 2, AudioTrack.MODE_STREAM);
audioTrack.play();
audioTrack.write(music, 0, musicLength);
audioTrack.stop();
} catch (Throwable t) {
Log.e(TAG, "播放失败");
showToast("播放失败");
}
在看下一边读一边播放
try {
// recordFile = new Fi