实现录音功能:
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initAudioRecordBtn();
}
//Mic audio record function
private static final int PLAY_END = 1;
private static final int RECORD_END = 2;
private TextView mRecordTimeTv;
private Button mStartRecordBtn;
private Button mPlayBtn;
private String mFileName = null;// 存储录音文件的路径
private AudioRecord mAudioRecord;
private volatile boolean mIsRecording = false;
private AudioFormat.Builder mAudioFormat;
private AudioAttributes mPlaybackAttributes;
private boolean mIsPlay;
private AudioTrack mAudio = null;
private RecorderHandler mHandler;
private class RecorderHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case PLAY_END:
stopPlayBack();
mPlayBtn.setText("播放录音");
mStartRecordBtn.setEnabled(true);
mIsPlay = false;
break;
case RECORD_END:
mRecordTimeTv.setText("");
mAudioRecord.stop();
mStartRecordBtn.setText("开始录音");
mPlayBtn.setEnabled(true);
mIsRecording = false;
mTimer.cancel();
break;
default:
break;
}
}
}
private CountDownTimer mTimer = new CountDownTimer(30 * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
long time = (30 * 1000 - millisUntilFinished) / 1000;
mRecordTimeTv.setText(String.format("00:%s", time < 10 ? "0" + time : time));
}
@Override
public void onFinish() {
mHandler.sendEmptyMessage(RECORD_END);
}
};
private void initAudioRecordBtn() {
mRecordTimeTv = findViewById(R.id.audio_record_time);
mStartRecordBtn = findViewById(R.id.audio_record_start);
mPlayBtn = findViewById(R.id.audio_record_play);
}
public String getSDPath() {
String path = null;
boolean sdCardExist = Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED);
if (sdCardExist) {
path = Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
}
return path;
}
private void setListener() {
// 开始录音
mStartRecordBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mAudioRecord == null || mAudioRecord.getState() == AudioRecord.STATE_UNINITIALIZED) {
return;
}
if (!mIsRecording) {
mIsRecording = true;
mStartRecordBtn.setText("结束录音");
mPlayBtn.setEnabled(false);
new Thread() {
@Override
public void run() {
super.run();
mTimer.start();
writeAudioDataToFile();
}
}.start();
} else {
mHandler.sendEmptyMessage(RECORD_END);
}
}
});
// 播放录音
mPlayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//play();
// return;
// String name = pcm2();
if (mIsPlay) {
stopPlayBack();
mPlayBtn.setText("播放录音");
mStartRecordBtn.setEnabled(true);
mIsPlay = false;
} else {
mIsPlay = true;
mPlayBtn.setText("停止播放");
mStartRecordBtn.setEnabled(false);
new Thread() {
@Override
public void run() {
super.run();
playBackNow();
}
}.start();
}
}
});
}
public void stopPlayBack() {
if (mAudio != null && mIsPlay && mAudio.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
mAudio.stop();
}
}
public void playBackNow() {
int length = 0;
Log.d(TAG, " before mAudio track");
mPlaybackAttributes = new AudioAttributes.Builder()
// .setUsage(AudioAttributes.USAGE_ASSISTANT)
.setUsage(AudioAttributes.USAGE_MEDIA)
// .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
.build();
mAudioFormat = new AudioFormat.Builder();
// mAudioFormat.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO);
mAudioFormat.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO); //CHANNEL_IN_STEREO
mAudioFormat.setSampleRate(32000);
mAudioFormat.setEncoding(AudioFormat.ENCODING_PCM_16BIT);
// int bufferSize = AudioRecord.getMinBufferSize(64000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
if (mAudio == null) {
mAudio = new AudioTrack(mPlaybackAttributes, // attributes
// AudioManager.STREAM_TTS,
//48000, // sample rate
mAudioFormat.build(),
AudioTrack.getMinBufferSize(32000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT) * 2,
AudioTrack.MODE_STREAM,
AudioManager.AUDIO_SESSION_ID_GENERATE
);
}
Log.d(TAG, " after mAudio track");
Log.d(TAG, "bufrer size:" + AudioTrack.getMinBufferSize(32000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT));
FileInputStream fis = null;
try {
Log.d(TAG, " get stream in");
// fis = new FileInputStream(getSDPath()+"/20190525_035557voice.pcm");
Log.d(TAG, "PALY - > " + mFileName);
fis = new FileInputStream(mFileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
length = fis.available();
} catch (IOException e) {
e.printStackTrace();
}
Log.d(TAG, "wav file readlen_1:" + length);
byte buffer[] = new byte[length];
try {
while (fis.available() > 0) {
length = fis.read(buffer);
if (length == AudioTrack.ERROR_INVALID_OPERATION || length == AudioTrack.ERROR_BAD_VALUE) {
continue;
}
if (length != 0 && length != -1) {
mAudio.play();
mAudio.write(buffer, 0, length);
}
Log.d(TAG, "play length --> " + length);
}
} catch (IOException e) {
e.printStackTrace();
}
mHandler.sendEmptyMessage(PLAY_END);
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setBtnAudioRecord() {
int bufferSize = AudioRecord.getMinBufferSize(64000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
final AudioFormat audioFormat = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(64000)
.setChannelMask(AudioFormat.CHANNEL_IN_STEREO)
.build();
mAudioRecord = new AudioRecord.Builder()
.setAudioSource(MediaRecorder.AudioSource.MIC)
.setBufferSizeInBytes(bufferSize)
.setAudioFormat(audioFormat)
.build();
Log.d(TAG, "record bufferSize=(" + bufferSize + ")");
}
@Override
public void onStart() {
super.onStart();
mHandler = new RecorderHandler();
Log.d(TAG, "start --");
}
@Override
public void onResume() {
super.onResume();
if (mAudioRecord == null) {
setBtnAudioRecord();
}
mPlayBtn.setEnabled(false);
setListener();
Log.d(TAG, "onResume --");
}
@Override
public void onStop() {
super.onStop();
Log.d(TAG, "stop --");
if (mTimer != null) {
mTimer.cancel();
}
if (mAudioRecord != null && mAudioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
mAudioRecord.stop();
mAudioRecord.release();
mAudioRecord = null;
}
mStartRecordBtn.setText("开始录音");
mPlayBtn.setEnabled(true);
mIsRecording = false;
mRecordTimeTv.setText("");
if (mAudio != null) {
if (mAudio.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) {
mAudio.stop();
}
mAudio.release();
mAudio = null;
}
}
/**
* write sound file
*/
private void writeAudioDataToFile() {
int bytesRecord = 0;
String filePath = getSDPath() + "/" + new SimpleDateFormat("yyyyMMdd_hhmmss").format(new Date()) + "voice.pcm";
mFileName = filePath;
File file = new File(filePath);
if (file.exists()) {
} else {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
int bufferSize = AudioRecord.getMinBufferSize(64000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
//int bufferSize = AudioRecord.getMinBufferSize(128000, AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
Log.d(TAG, "record bufferSize=(" + bufferSize + ")");
byte[] tempBuffer = new byte[bufferSize];
OutputStream os = null;
try {
os = new FileOutputStream(filePath);
Log.d(TAG, "after recorder create file");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
mAudioRecord.startRecording();
while (mIsRecording) {
// gets the voice output from microphone to byte format
bytesRecord = mAudioRecord.read(tempBuffer, 0, bufferSize);
Log.d(TAG, "record byte=(" + bytesRecord + ")");
if (bytesRecord == AudioRecord.ERROR_INVALID_OPERATION || bytesRecord == AudioRecord.ERROR_BAD_VALUE) {
Log.d(TAG, " Audio record read err");
}
if (bytesRecord != 0 && bytesRecord != -1) {
try {
os.write(splitStereoPcm(tempBuffer), 0, bytesRecord / 2);
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "$$$record byte=0");
}
}
Log.d(TAG, "after writer record");
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private byte[] splitStereoPcm(byte[] data) {
int monoLength = data.length / 2;
byte[] pcmData = new byte[monoLength];
for (int i = 0; i < monoLength; i++) {
if (i % 2 == 0) {
System.arraycopy(data, i * 2, pcmData, i, 2);
} else {
System.arraycopy(data, i * 2, pcmData, i - 1, 2);
}
}
return pcmData;
}
}