1

我正在两个设备之间传输麦克风音频,一切正常,但回声很差。

这是我在做什么

阅读线程

int sampleFreq = 22050; 
        int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
        int minBuffer = 2*AudioTrack.getMinBufferSize(sampleFreq, channelConfig, audioFormat);

        AudioTrack atrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                        sampleFreq,
                        channelConfig,
                        audioFormat,
                        minBuffer,
                        AudioTrack.MODE_STREAM);
        atrack.play();

        byte[] buffer = new byte[minBuffer];
        while (true) {
            try {                
                // Read from the InputStream                
                bytes = mmInStream.read(buffer);                    
                atrack.write(buffer, 0, buffer.length);
                atrack.flush();                         
            } catch (IOException e) {
                Log.e(TAG, "disconnected", e);
                break;
            }
        }

这里是录音线程

int sampleRate = 22050; 
    int channelMode = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    int buffersize = 2*AudioTrack.getMinBufferSize(sampleRate, channelMode, audioFormat);

    AudioRecord arec = new AudioRecord(MediaRecorder.AudioSource.MIC,
            sampleRate, channelMode,
            AudioFormat.ENCODING_PCM_16BIT, buffersize);

    buffer = new byte[buffersize];
    arec.startRecording();

    while (true) {  
        arec.read(buffer, 0, buffersize);
        new Thread( new Runnable(){
            @Override
            public void run() {
                try {               
                    mOutputStream.write(buffer);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }                   
            }               
        }).start();
    }

难道我做错了什么?

4

2 回答 2

2

您需要回声消除逻辑。这是我在 Arm5 (WM8650) 处理器 (Android 2.2) 上所做的以消除回声。

  1. 我用 JNI 包装了 Speex,并在将 PCM 帧发送到编码器之前调用了回声处理例程。无论我尝试什么 Speex 设置,都没有取消回声。

  2. 因为 Speex 对播放和回显帧之间的延迟非常敏感,所以我实现了一个队列并将所有发送到 AudioTrack 的数据包排队。队列的大小应该大致等于内部 AudioTrack 缓冲区的大小。当 AudioTrack 将数据包从其内部缓冲区发送到声卡时,数据包被发送到 echo_playback。使用这种方法消除了延迟,但仍然没有取消回声

  3. 我用 JNI 包装了 WebRtc 回声消除部分,并在将数据包发送到编码器之前调用了它的方法。回声仍然存在,但图书馆显然正试图取消它。

  4. 我应用了 P2 中描述的缓冲技术,它终于开始起作用了。但是,需要为每个设备调整延迟。另请注意,WebRtc 具有移动版和完整版回声消除功能。完整版大大减慢了处理器的速度,应该只能在 ARM7 上运行。移动版可以工作,但质量较低

我希望这会对某人有所帮助。

于 2011-08-19T17:11:11.040 回答
2

可能是这样的:

bytes = mmInStream.read(buffer);                    
atrack.write(buffer, 0, buffer.length);

如果缓冲区从上一次调用中保持满并且新的未满(所以bytes < buffer.length)你重新播放保留部分曲目。

于 2011-08-23T22:26:09.893 回答