import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.os.Process;
import android.util.Log;
/**
* Created by wangfei on 2018/7/1.
*/
public class RadioInVoice {
private static final String TAG = "RadioInVoice";
private int bufferReadResult;
private boolean isRecording = false;//是否录放的标记
static final int frequencyCap = 48000;
static final int frequencyPlay = 24000;
static final int channelConfigurationCap = AudioFormat.CHANNEL_IN_MONO;
static final int channelConfigurationPlay = AudioFormat.CHANNEL_OUT_STEREO;
static final int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
int recBufSize, playBufSize;
AudioRecord audioRecord;
AudioTrack audioTrack;
public void start() {
LogUtil.info(TAG, "RadioInVoice start");
// 获取每一帧的字节流大小
// 第一个参数sampleRateInHz 采样率(赫兹),只能在4000到192000的范围内取值
// 第二个参数channelConfig 声道配置 描述音频声道的配置,例如左声道/右声道/前声道/后声道。
// 第三个参数audioFormat 音频格式 表示音频数据的格式。注意!一般的手机设备可能只支持 16位PCM编码,如果其他的都会报错为坏值.
recBufSize = AudioRecord.getMinBufferSize(frequencyCap, channelConfigurationCap, audioEncoding);
playBufSize = AudioTrack.getMinBufferSize(frequencyPlay, channelConfigurationPlay, audioEncoding);
// -----------------------------------------
// 第一个参数audioSource 音频源
// 第二个参数sampleRateInHz 采样率(赫兹) 与前面初始化获取每一帧流的Size保持一致
// 第三个参数channelConfig 声道配置 描述音频声道的配置,例如左声道/右声道/前声道/后声道。 与前面初始化获取每一帧流的Size保持一致
// 第四个参数audioFormat 音频格式 表示音频数据的格式。 与前面初始化获取每一帧流的Size保持一致
// 第五个参数缓存区大小,基本就是上面我们配置的AudioRecord.getMinBufferSize
// 1998 MediaRecorder.AudioSource.RADIO_TUNER(此处需底层适配)
audioRecord = new AudioRecord(1998, frequencyCap,
channelConfigurationCap, audioEncoding, recBufSize * 10);
// 第一个参数 streamType:音频流类型 STREAM_ALARM、STREAM_MUSIC、STREAM_RING、STREAM_SYSTEM、STREAM_VOICE_CALL、STREAM_NOTIFICATION、STREAM_BLUETOOTH_SCO、STREAM_BLUETOOTH_SCO
// 第二个参数 采样率 在4000到48000之间
// 第三个参数 channelConfig:音频声道
// 第四个参数 音频格式
// 第五个参数 bufferSizeInBytes缓冲区大小:
// 第六个参数 mode:音频数据载入模式
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frequencyPlay, channelConfigurationPlay, audioEncoding,
playBufSize, AudioTrack.MODE_STREAM);
audioTrack.setStereoVolume(0.7f, 0.7f);// 设置当前音量大小
isRecording = true;
new RecordPlayThread().start();// 开一条线程边录边放
}
public void stop() {
LogUtil.info(TAG, "RadioInVoice stop");
if (isRecording) {
try {
isRecording = false;
while (audioRecord != null) {
Log.d(TAG, "wait audioRecord release");
Thread.sleep(1000);
}
} catch (Throwable t) {
Log.e(TAG, "wait audioRecord Thread exit" + t.getMessage());
}
}
}
/**
* 是否正在录音中
*
* @return 录音状态
*/
public boolean isRunning() {
return isRecording;
}
class RecordPlayThread extends Thread {
private boolean succStart = false;
public void run() {
Process.setThreadPriority(1000);
try {
byte[] buffer = new byte[recBufSize];
while (!succStart && isRecording) {
audioRecord.startRecording();// 开始录制
if (audioRecord.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING) {
LogUtil.info(TAG, "RadioInVoice RecordPlayThread run startRecording fail");
succStart = false;
} else {
LogUtil.info(TAG, "RadioInVoice RecordPlayThread run startRecording true");
succStart = true;
}
Thread.sleep(1000);
}
audioTrack.play();// 开始播放
while (isRecording && RadioConstants.isRadioPlay) {
// 添加录音条件显示 不是终止录音状态、静音状态、音源不在收音机状态
if (RadioConstants.isRadioPlaying) {
if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) {
audioRecord.startRecording();
}
// 从MIC保存数据到缓冲区
bufferReadResult = audioRecord.read(buffer, 0, recBufSize);
if (bufferReadResult > 0) {
// 写入数据即播放
audioTrack.write(buffer, 0, bufferReadResult);
} else {
LogUtil.error(TAG, "RadioInVoice audioRecord.read error : " + bufferReadResult);
}
} else {
if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
// 不允许录音时,要stop,清空缓存,否则再次播放时会播一段之前的。
audioRecord.stop();
}
}
}
if (audioTrack != null) {
audioTrack.stop();
audioTrack.release();
audioTrack = null;
}
if (audioRecord != null) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
} catch (Exception e) {
LogUtil.error(TAG, "RecordPlayThread RadioInVoice:" + e.getMessage());
} finally {
if (audioTrack != null && audioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
audioTrack.stop();
audioTrack.release();
audioTrack = null;
}
if (audioRecord != null && audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
audioRecord.stop();
audioRecord.release();
audioRecord = null;
}
}
}
}
}
/**
* 开始收音机录音
*/
private void startRadioVoice() {
if (null != mRadioCommonView) {
if (null == mRadioInVoice) {
mRadioInVoice = new RadioInVoice();
mRadioInVoice.start();
} else if (null != mRadioInVoice && !mRadioInVoice.isRunning()) {
mRadioInVoice.start();
}
}
}
/**
* 停止录音
*/
private void stopRadioVoice() {
if (null != mRadioInVoice) {
if (mRadioInVoice.isRunning()) {
new Thread(new Runnable() {
@Override
public void run() {
try {
mRadioInVoice.stop();
} catch (Exception e) {
e.printStackTrace();
LogUtil.error(TAG, "RecordPlayThread stopVoiceCall()" + e.getMessage());
}
}
}).start();
}
}
}