前言
我们在刚学习多媒体编程的时候,接触音视频的录制时更多的是通过MediaRecorder实现音频的录制;请看我的这篇文章MediaRecorder录制音频及代码的抽取封装
实现音频的播放通过MediaPlayer;可以查看我的这篇博客MediaPlayer播放不同来源的音频文件
SoundPool更多的是播放短而急促的声音,比如:嘟一声!!!比较简单这里就不再累述;
我们可以通过AudioRecorder、AudioTractor实现录制及播放固定的采样率、声道数、音频格式;
知识结构
AudioRecorder:The AudioRecord class manages the audio resources for Java applications to record audio from the audio input hardware of the platform.(大致意思就是AudioRecord以平台的硬件录制音频)
常用方法:
1、构造方法:
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
- audioSource:声音来源;如:MediaRecorder.AudioSource.MIC
- sampleRateInHz:声音采样率
- audioFormat:声音的格式
- bufferSizeInBytes:缓存大小;常通过bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
- channelConfig, audioFormat);求得缓存大小
2、公共方法:
startRecording():开始录制
read(short[] audioData, int offsetInShorts, int sizeInShorts) Reads audio data from the audio hardware for recording into a buffer.
- audioData :short类型的缓存
- offsetInShorts :偏移量
- int sizeInShorts : 需要读取的大小
stop()停止录制
AudioTractor:The AudioTrack class manages and plays a single audio resource for Java applications(大致意思:管理和播放应用中的音频资源)
常用方法:
1、构造函数:
AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes, int mode)
- streamType:播放音频类型;可以设置为AudioManager.STREAM_MUSIC
- sampleRateInHz、channelConfig、audioFormat这三个参数与上面的AudioRecord设置相同
- bufferSizeInBytes:通过bufferSizePlay = AudioTrack.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat)获得;
2、公共方法
play():开始播放
pause():暂停
write(short[] audioData, int offsetInShorts, int sizeInShorts):Writes the audio data to the audio hardware for playback.(大致意思:把音频数据写入到audioData中让 audio hardware 回放)
stop():停止
示例代码
package com.example.audiorecorderdemo.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.example.audiorecorderdemo.R;
import com.example.audiorecorderdemo.R.id;
import com.example.audiorecorderdemo.R.layout;
public class Main02Activity extends Activity implements OnClickListener{
private Button bt_startAuduio;
private Button bt_stopAudio;
private Button bt_startPlay;
private Button bt_stopPlay;
private AudioRecord mAudioRecord;
private AudioRecordAsyncTask mAudioRecordAsyncTask;
private AudioStartAsyncTask mAudioStartAsyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
bt_startAuduio = (Button) this.findViewById(R.id.startAudio);
bt_stopAudio = (Button) this.findViewById(R.id.stopAudio);
bt_startPlay = (Button) this.findViewById(R.id.startPlay);
bt_stopPlay = (Button) this.findViewById(R.id.stopPlay);
bt_startPlay.setOnClickListener(this);
bt_stopPlay.setOnClickListener(this);
bt_startAuduio.setOnClickListener(this);
bt_stopAudio.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.startAudio:
mAudioRecordAsyncTask = new AudioRecordAsyncTask();
mAudioRecordAsyncTask.execute();
bt_startAuduio.setEnabled(false);
break;
case R.id.stopAudio:
isAudioRecording = false;
bt_startAuduio.setEnabled(true);
break;
case R.id.startPlay:
mAudioStartAsyncTask = new AudioStartAsyncTask();
mAudioStartAsyncTask.execute();
break;
case R.id.stopPlay:
isPlay = false;
break;
default:
break;
}
}
private boolean isAudioRecording = false;
private int sampleRateInHz = 8000;
private int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int bufferSizeInBytes;
private void prepareStartRecordAudio() {
bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
channelConfig, audioFormat);
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
// createAudioRecord();
mAudioRecord.startRecording();
isAudioRecording = true;
}
private File audioFile;
private class AudioRecordAsyncTask extends AsyncTask<Void, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
prepareStartRecordAudio();
}
@Override
protected String doInBackground(Void... params) {
String result = null;
try {
// 获取录制视频保存的文件
audioFile = new File(Environment.getExternalStorageDirectory(),
"/audiodatas/files/audioRecord.pcm");
if (!audioFile.exists()) {
audioFile.getParentFile().mkdirs();
}
DataOutputStream audioOutputStream = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(audioFile)));
// 建立一个AudioRecorder读入数据的缓冲区
short[] buffer = new short[bufferSizeInBytes / 4];
while (isAudioRecording) {
int readResult = mAudioRecord
.read(buffer, 0, buffer.length);
for (int i = 0; i < readResult; i++) {
audioOutputStream.writeShort(buffer[i]);
}
}
audioOutputStream.close();
mAudioRecord.stop();
result = "audio record end !!!";
} catch (Exception e) {
result = "sudio record exception !";
}
return result;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(Main02Activity.this, result, Toast.LENGTH_LONG).show();
}
}
private void createAudioRecord() {
for (int sampleRate : new int[] { 44100, 8000, 11025, 16000, 22050,
32000, 47250, 48000 }) {
for (short audioFormat : new short[] {
AudioFormat.ENCODING_PCM_16BIT,
AudioFormat.ENCODING_PCM_8BIT }) {
for (short channelConfig : new short[] {
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.CHANNEL_IN_STEREO }) {
// Try to initialize
try {
bufferSizeInBytes = AudioRecord.getMinBufferSize(
sampleRate, channelConfig, audioFormat);
if (bufferSizeInBytes < 0) {
continue;
}
mAudioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, sampleRate,
channelConfig, audioFormat, bufferSizeInBytes);
if (mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
return;
}
mAudioRecord.release();
mAudioRecord = null;
} catch (Exception e) {
// Do nothing
}
}
}
}
throw new IllegalStateException(
"getInstance() failed : no suitable audio configurations on this device.");
}
private AudioTrack mAudioTrack;
private int bufferSizePlay;
private boolean isPlay = false;
public void prepareStartingAudio() {
bufferSizePlay = AudioTrack.getMinBufferSize(sampleRateInHz,channelConfig, audioFormat);
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRateInHz,
channelConfig, audioFormat, bufferSizePlay,
AudioTrack.MODE_STREAM);
mAudioTrack.play();
isPlay = true;
}
public class AudioStartAsyncTask extends AsyncTask<Void, Void, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
prepareStartingAudio();
}
@Override
protected String doInBackground(Void... params) {
String result = null;
try {
DataInputStream fileInput = new DataInputStream(
new BufferedInputStream(new FileInputStream(audioFile)));
short[] buffer = new short[bufferSizePlay / 4];
while (isPlay && fileInput.available() > 0) {
for (int i = 0; fileInput.available() > 0
&& i < buffer.length; i++) {
buffer[i] = fileInput.readShort();
}
mAudioTrack.write(buffer, 0, buffer.length);
}
mAudioTrack.stop();
fileInput.close();
result = "success";
} catch (Exception e) {
e.printStackTrace();
result = "fail ";
}
return result;
}
@Override
protected void onPostExecute(String result) {
Toast.makeText(Main02Activity.this, result, Toast.LENGTH_LONG).show();
super.onPostExecute(result);
}
}
}
我把上面的代码给整理抽取了一个封装类,想看可以在这里下载:AudioRecord/AudioTractorDemo