AudioRecord
The project achieved pcm multi-configuration (sample rate, file format optional) recording and playback tool, users can record audio.
Project code: https: //github.com/worson/AudioRecord.git
Recording parameters
Andrews applications, the use AudioRecord can achieve a more flexible configuration of recording, the recording is AudioRecord raw pcm data.
AudioRecord configuration as follows:
AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
audioSource: original sound audio recording, as follows
MediaRecorder.AudioSource.CAMCORDER
设定录音来源于同方向的相机麦克风相同,若相机无内置相机或无法识别,则使用预设的麦克风
MediaRecorder.AudioSource.DEFAULT 默认音频源
MediaRecorder.AudioSource.MIC
设定录音来源为主麦克风。
MediaRecorder.AudioSource.VOICE_CALL
设定录音来源为语音拨出的语音与对方说话的声音
MediaRecorder.AudioSource.VOICE_COMMUNICATION
摄像头旁边的麦克风
MediaRecorder.AudioSource.VOICE_DOWNLINK
下行声音
MediaRecorder.AudioSource.VOICE_RECOGNITION
语音识别
MediaRecorder.AudioSource.VOICE_UPLINK
上行声音
sampleRateInHz: audio sample rate, per second to the number of audio data collection
channelConfig: recording channels, a single channel is AudioFormat.CHANNEL_CONFIGURATION_MONO, dual channels AudioFormat.CHANNEL_CONFIGURATION_STEREO
audioFormat: the number of bits per audio sampling point, i.e., the accuracy of audio channel selection can AudioFormat.ENCODING_PCM_16BIT i.e. bit pcm 16
bufferSizeInBytes: the total number of audio data written to the buffer, the buffer by obtaining the minimum AudioRecord.getMinBufferSize.
Calculated on the amount of audio data
For a sampling rate of 16k bits 16bit deep recording parameters, the number of byte per second is: 2 * 16000 = 32000, i.e., per minute: the amount of data 32000 * 60 byte / min = 1.875 MB / min of
Recording Process
Creating recorder
public PcmRecorder(int audioSource, int sampleRate, int channelCnt, Context context, RecordListener listener) {
mListener = listener;
int channelConfig = channelCnt == 1 ? AudioFormat.CHANNEL_CONFIGURATION_MONO : AudioFormat.CHANNEL_CONFIGURATION_STEREO;
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, AUDIO_FORMAT);
mBufSize = minBufSize;
int bufferSizeInBytes = minBufSize;
AILog.i(TAG, "PcmRecorder: bufferSizeInBytes " + bufferSizeInBytes);
mAudioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, AUDIO_FORMAT, bufferSizeInBytes);
AILog.d(TAG, "state: " + mAudioRecord.getState());
}
start recording
Start recording, and create the data read thread
public void start() {
AILog.d(TAG, "onStartRecord");
mAudioRecord.startRecording();
mRecording = true;
mRecordThread = new RecordThread("RecordThread");
mRecordThread.start();
if (mListener != null) {
mListener.onStartRecord();
} else {
AILog.w(TAG, "start: mListener is null");
}
}
Reads the audio data
Buffer continue reading sound data, and callback upper layer application processing
class RecordThread extends Thread {
public RecordThread(String name) {
super(name);
}
@Override
public void run() {
AILog.v(TAG, "thread run");
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);
if (mAudioRecord.getState() == AudioRecord.STATE_UNINITIALIZED) {
AILog.d(TAG, "unInit");
return;
}
byte[] buffer = new byte[mBufSize];
while (!mStopFlag) {
int len = mAudioRecord.read(buffer, 0, buffer.length);
if (len != mBufSize) {
AILog.e(TAG, "record read error:" + len);
}
if (mListener != null) {
mListener.onRecordData(buffer);
continue;
}
}
AILog.v(TAG, "thread end");
}
}
Stop recording
Stop recording and release resources
public void stop() {
AILog.d(TAG, "stopRecord");
mStopFlag = true;
mRecording = false;
try {
mRecordThread.join();
} catch (InterruptedException e) {
AILog.d(TAG, "InterruptedException " + e.getMessage());
} finally {
if (mListener != null) {
mListener.onStopRecord();
} else {
AILog.d(TAG, "stop: mListener is null");
}
mAudioRecord.stop();
mAudioRecord.release();
}
mListener = null;
}
The upper application call
private void startRecord() {
AILog.i(TAG, "startRecord: ");
checkEnvirement();
if (rb_channel_dual.isChecked()) {
mRecorder = new PcmRecorder(getAudioSource(), getAudioFrequecy(), 2);
} else {
mRecorder = new PcmRecorder(getAudioSource(), getAudioFrequecy(), 1);
}
try {
mOutputStream = new FileOutputStream(mTempRecordFile);
mRecorder.setRecordListener(mRecordListener);
mRecorder.start();
tv_tips.setText("正在录音...");
bt_recorder.setText("结束录音");
bt_play.setVisibility(View.INVISIBLE);
bt_delete.setVisibility(View.INVISIBLE);
} catch (FileNotFoundException e) {
e.printStackTrace();
tv_tips.setText("录音启动失败...");
}
}
private RecordListener mRecordListener = new RecordListener() {
@Override
public void onStartRecord() {
AILog.i(TAG, "onStartRecord: ");
}
@Override
public void onRecordData(byte[] bytes) {
try {
mOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onStopRecord() {
AILog.i(TAG, "onStopRecord: ");
//保存文件
}
};