在Android上初始化AudioTrack是否有明显延迟?

在Android上初始化AudioTrack是否有明显延迟?,android,audio,Android,Audio,我正试图通过录音和音轨将从麦克风获得的音频样本传递给扬声器。代码如下: public class MainActivity extends Activity { AudioManager am = null; AudioRecord record =null; AudioTrack track =null; final int SAMPLE_FREQUENCY = 44100; final int SIZE_OF_RECORD_ARRAY = 1024;

我正试图通过录音和音轨将从麦克风获得的音频样本传递给扬声器。代码如下:

public class MainActivity extends Activity {
    AudioManager am = null;
    AudioRecord record =null;
    AudioTrack track =null;
    final int SAMPLE_FREQUENCY = 44100;
    final int SIZE_OF_RECORD_ARRAY = 1024;  // 1024 ORIGINAL
    final int WAV_SAMPLE_MULTIPLICATION_FACTOR = 1;
    int i= 0;
    boolean isPlaying = true;
    class MyThread extends Thread{
        private volatile boolean passThroughMode = true;
        // /*
        MyThread(){
            super();
        }

        MyThread(boolean newPTV){
            this.passThroughMode = newPTV;
        }
        // */

        // /*
        @Override
        public void run(){
            short[] lin = new short[SIZE_OF_RECORD_ARRAY];
            int num = 0;
            // am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); // -> MOVED THESE TO init()
            // am.setMode(AudioManager.MODE_IN_COMMUNICATION);
            record.startRecording();
            track.play();
            while (passThroughMode) {
            // while (!isInterrupted()) {
                num = record.read(lin, 0, SIZE_OF_RECORD_ARRAY);
                for(i=0;i<lin.length;i++)
                    lin[i] *= WAV_SAMPLE_MULTIPLICATION_FACTOR; 
                track.write(lin, 0, num);
            }
            // /*
            record.stop();
            track.stop();
            record.release();
            track.release();
            // */
        }
        // */

        // /*
        public void stopThread(){
            passThroughMode = false;
        }
        // */
    }

    MyThread newThread;

    private void init() {
        int min = AudioRecord.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        record = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_IN_MONO,
                                 AudioFormat.ENCODING_PCM_16BIT, min);
        int maxJitter = AudioTrack.getMinBufferSize(SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
        track = new AudioTrack(AudioManager.MODE_IN_COMMUNICATION, SAMPLE_FREQUENCY, AudioFormat.CHANNEL_OUT_MONO,
                               AudioFormat.ENCODING_PCM_16BIT, maxJitter, AudioTrack.MODE_STREAM);
        am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
        am.setMode(AudioManager.MODE_IN_COMMUNICATION);

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setVolumeControlStream(AudioManager.MODE_IN_COMMUNICATION);
        // init(); // -> Moved this to onResume();
        Log.d("MYLOG", "onCreate() called");
    }

    @Override
    protected void onResume(){
        super.onResume();
        // newThread.stopThread();
        Log.d("MYLOG", "onResume() called");
        init();
        newThread = new MyThread(true);
        newThread.start(); 
    }

    @Override
    protected void onPause(){
        super.onPause();
        Log.d("MYLOG", "onPause() called");
        newThread.stopThread();
        // android.os.Process.killProcess(android.os.Process.myPid());
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void passStop(View view){
        Button playBtn = (Button) findViewById(R.id.playBtn);  
        // /*
        if(!isPlaying){
            record.startRecording();
            track.play();
            isPlaying = true;
            playBtn.setText("Pause");
        }
        else{
           record.stop();
           track.pause();
           isPlaying=false;
           playBtn.setText("Pass through");
        }
        // */
    }

    // /*
    @Override
    protected void onDestroy() {
        super.onDestroy();
        newThread.stopThread();
        // android.os.Process.killProcess(android.os.Process.myPid());
        // killProcess(android.os.Process.myPid());
        // newThread.interrupt();
         Log.d("MYLOG", "onDestroy() called");
    }
    // */
}  
公共类MainActivity扩展活动{
AudioManager am=null;
录音记录=空;
AudioTrack track=null;
最终int样本_频率=44100;
记录数组的最终整数大小=1024;//1024原始
最终整数波形样本乘法因子=1;
int i=0;
布尔值isplay=true;
类MyThread扩展线程{
私有易失性布尔passThroughMode=true;
// /*
神话读物(){
超级();
}
MyThread(布尔newPTV){
this.passThroughMode=newPTV;
}
// */
// /*
@凌驾
公开募捐{
short[]lin=新的short[记录数组的大小];
int num=0;
//am=(AudioManager)this.getSystemService(Context.AUDIO_SERVICE);//->将它们移动到init()中
//am.setMode(AudioManager.MODE_IN_通信);
record.startRecording();
track.play();
while(passThroughMode){
//而(!isInterrupted()){
num=record.read(lin,0,记录数组的大小);
对于(i=0;我将其移动到onResume();
d(“MYLOG”,“onCreate()被调用”);
}
@凌驾
受保护的void onResume(){
super.onResume();
//newThread.stopThread();
d(“MYLOG”,“onResume()被调用”);
init();
newThread=newmythread(true);
newThread.start();
}
@凌驾
受保护的void onPause(){
super.onPause();
d(“MYLOG”,“onPause()调用”);
newThread.stopThread();
//android.os.Process.killProcess(android.os.Process.myPid());
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(R.menu.main,menu);
返回true;
}
公共无效通行证(视图){
按钮playBtn=(按钮)findviewbyd(R.id.playBtn);
// /*
如果(!显示){
record.startRecording();
track.play();
isplay=true;
playBtn.setText(“暂停”);
}
否则{
record.stop();
track.pause();
isplay=false;
playBtn.setText(“传递”);
}
// */
}
// /*
@凌驾
受保护的空onDestroy(){
super.ondestory();
newThread.stopThread();
//android.os.Process.killProcess(android.os.Process.myPid());
//killProcess(android.os.Process.myPid());
//newThread.interrupt();
d(“MYLOG”,“onDestroy()被调用”);
}
// */
}  

程序应该启动一个执行传递的线程。该线程从应用程序的onResume()开始,因此应该立即启动。但在开始时总是有1.5~2秒的延迟。我认为这可能是因为onCreate()和其他初始化在onResume()中线程开始之前发生,但如果我将
lin
数组的内容打印到文件中,它总是在开始处写入一个长的0行,这表明延迟可能不是由于初始化所需的时间造成的。那么这里看到的延迟是什么?跟踪.play()吗需要很长的时间才能开始播放?

我正在调试一个类似的延迟,虽然我还没有完整的答案,但AudioManager似乎在设置模式调用(am.setMode(AudioManager.MODE\u in_COMMUNICATION))中引入了延迟。

user13267,您发现过这个问题的答案吗?