我正在尝试开发像iRig for android这样的应用程序,所以第一步是捕获麦克风输入并同时播放它。
我有它,但问题是我得到一些延迟使得这个无法使用,如果我开始处理缓冲区,我担心它会完全无法使用。
我像这样使用audiorecord和audiotrack:
new Thread(new Runnable() {
public void run() {
while(mRunning){
mRecorder.read(mBuffer, 0, mBufferSize);
//Todo: Apply filters here into the buffer and then play it modified
mPlayer.write(mBuffer, 0, mBufferSize);
//Log.v("MY AMP","ARA");
}
以这种方式表达:
// ==================== INITIALIZE ========================= //
public void initialize(){
mBufferSize = AudioRecord.getMinBufferSize(mHz,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
mBufferSize2 = AudioTrack.getMinBufferSize(mHz,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
mBuffer = new byte[mBufferSize];
Log.v("MY AMP","Buffer size:" + mBufferSize);
mRecorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
mHz,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
mBufferSize);
mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,
mHz,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
mBufferSize2,
AudioTrack.MODE_STREAM);
}
你知道如何获得更快的回复吗? 谢谢!
答案 0 :(得分:8)
由于最小缓冲区大小,Android的AudioTrack \ AudioRecord类具有高延迟。 这些缓冲区大小的原因是为了最大限度地减少GC发生GC时的丢失(在我看来,这是一个错误的决定,你可以优化自己的内存管理)。
您要做的是使用OpenSL,它可以从2.3获得。它包含用于流式音频的本机API。 这是一些文档: http://mobilepearls.com/labs/native-android-api/opensles/index.html
答案 1 :(得分:1)
只是一个想法,但你不应该阅读< mBufferSize
答案 2 :(得分:0)
我的第一个建议是建议将AudioTrack导入静态模式而不是流模式,因为静态模式的延迟明显较小。但是,静态模式更适合完全适合内存的短音,而不是您从其他地方捕获的声音。但是,如同一个疯狂的猜测,如果您将AudioTrack设置为静态模式并为其提供输入音频的离散块,该怎么办?
如果您想要更严格地控制音频,我建议您查看适用于Android的 OpenSL ES 。学习曲线会更加陡峭,但您可以获得更精细的控制和更低的延迟。
答案 3 :(得分:0)
正如mSparks指出的那样,应该使用较小的读取大小进行流式传输:您不需要读取完整的缓冲区来传输数据!
int read = mRecorder.read(mBuffer, 0, 256); /* Or any other magic number */
if (read>0) {
mPlayer.write(mBuffer, 0, read);
}
这将大大减少您的延迟。如果mHz是44100并且你处于256的MONO配置,你的延迟将不小于1000 * 256/44100毫秒= ~5.8 ms。 256/44100是从样本到秒的转换,因此乘以1000会得到毫秒。 问题是玩家的内部实施。你无法从java控制它。希望这有助于某人:)