在我的Android应用程序中,我想从智能手机的麦克风中取出一些音频并立即播放,像麦克风一样直播,没有延迟。我目前正在考虑使用AudioRecord
和AudioTrack
类(根据我所读过的内容),但我不太清楚如何继续。
我查看了Stack Overflow上的其他一些问题,但他们并没有完全回答我想做的事情。大部分都来自2012年。
那么如何使用这些类同时输入和输出音频呢?
还:我查看了MediaRecorder API
,但根据我的阅读,这需要您将音频保存到文件中,我不想这样做做。可以通过tweek来满足我的要求吗?或者我最好只使用AudioRecord
?
由于
修改
以下是我在@Pradip Pramanick建议的更新代码:
final Thread record = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
MediaRecorder microphone = new MediaRecorder();
microphone.setAudioSource(MediaRecorder.AudioSource.MIC);
microphone.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
microphone.setOutputFile(filename);
microphone.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
microphone.prepare();
} catch (IOException e) {
e.printStackTrace();
}
microphone.start();
}
}
});
final Thread play = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
player = new MediaPlayer();
try {
player.setDataSource(filename);
player.prepare();
player.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
我得到Illegal State Exception | Start failed: -38
。但我在microphone.start
之后打电话给microphone.prepare
......这似乎是什么问题?我搜索了其他线程,说可能有其他后台应用程序使用麦克风。我搜索了我的设备:Moto X Play(第三代)并没有找到。 (我甚至关闭了#34; Ok Google"语音识别,但错误仍然存在)。
错误日志:
以下是显示最新错误的log-cat:
01-31 09:37:21.064 344-3339/? E/MediaPlayerService: offset error
01-31 09:37:21.065 1835-1922/com.synerflow.testapp E/MediaPlayer: Unable to create media player
01-31 09:37:21.065 1835-1922/com.synerflow.testapp I/Player: player.prepare() has failed
01-31 09:37:21.065 1835-1922/com.synerflow.testapp W/System.err: java.io.IOException: setDataSourceFD failed.: status=0x80000000
IO异常似乎在player.setDataSource(filename)
,文件名变量是一个字符串:Environment.getExternalStorageDirectory().getAbsolutePath() + "\voice.3gp"
答案 0 :(得分:3)
据我所知,它可以用一种非常简单的方式完成。我还没试过,但是你试试看。我认为它会起作用:
创建两个线程,用于录制另一个线程进行播放。 假设线程是TRecord和TPlay。
在TRecord的run方法中执行以下操作:
public void run(){
MediaRecorder mRecorder = null;
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(mFileName);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
mRecorder.prepare();
} catch (IOException e) {
//todo
}
mRecorder.start();
}
TPlay的run方法可以做到这一点:
public void run() {
MediaPlayer mPlayer = null;
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mFileName);
mPlayer.prepare();
mPlayer.start();
} catch (IOException e) {
//todo
}
}
现在,在mainactivity上只需创建两个线程。首先启动TRecord线程,然后启动Tplay。试试吧。
这是文件扩展名的代码:
mFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
mFileName += "/audiorecordtest.3gp";
答案 1 :(得分:2)
这在Android上实际上非常棘手。谷歌自己有一个很好的(但稍长)video来解释这些问题。
他们对各种设备也有a page explaining their latency testing methods and benchmarks。
从本质上讲,股票Android不能做零延迟音频,但没有什么能阻止硬件合作伙伴添加所需的硬件和平台扩展。
答案 2 :(得分:1)
您可以尝试使用Google Oboe。
Oboe是一个C ++库,可轻松在Android上构建高性能音频应用。
Oboe已经有一个“即时音频输入和输出Android”的示例
LiveEffect样本
此示例仅将音频从输入流循环到输出流以 演示两个流接口的用法。
https://github.com/google/oboe/tree/master/samples/LiveEffect
答案 3 :(得分:0)
试试这个。我没有跑过这个。
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize * BytesPerElement);
recorder.startRecording();
isRecording = true;
recordingThread = new Thread(new Runnable() {
public void run() {
try {
int intSize = android.media.AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,AudioFormat.CHANNEL_OUT_MONO , RECORDER_AUDIO_ENCODING);
byte[] sData = new byte[bufferSize];
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, RECORDER_SAMPLERATE, AudioFormat.CHANNEL_OUT_MONO, RECORDER_AUDIO_ENCODING, intSize, AudioTrack.MODE_STREAM);
while(isRecording){
recorder.read(sData, 0, bufferSize); //isRecording = false; onStop button
if (at!=null) {
at.play();
// Write the byte array to the track
at.write(sData, 0, sData.length);
at.stop();
at.release();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}, "AudioRecorder Thread");
recordingThread.start();