Xamarin.iOS上的回声消除(AEC)

时间:2018-11-20 21:42:05

标签: c# xamarin.ios voip echo-cancellation

我目前正在基于Xamarin.iOS平台进行跨平台Voip应用程序开发。我确实搜索过iOS上的AEC实现,但大多数主题都与Objective-C有关。 我现在已经实现的是:我可以使用Audiotoolbox(音频队列)从麦克风获取输入的原始声音数据,并通过套接字将其发送出去。但是在使用其他设备进行测试期间,我在电话上遇到了非常清晰的回声。这是代码:

private void SetupInputQueue()
    {
        inputQueue = new InputAudioQueue(audioStreamBasicDescription);
        //sendbuffer initialization
        heading = Encoding.ASCII.GetBytes("msg ");
        sendBuffer = new byte[CountAudioBuffers][];
        for (int i = 0; i < CountAudioBuffers; i++)
        {
            sendBuffer[i] = new byte[516];
            for (int j = 0; j < heading.Length; j++)
            {
                sendBuffer[i][j] = heading[j];
            }
        }

        for (int count = 0; count < CountAudioBuffers; count++)
        {
            IntPtr bufferpointer;
            inputQueue.AllocateBuffer(AudioBufferLength, out bufferpointer);
            inputQueue.EnqueueBuffer(bufferpointer, AudioBufferLength, null);
        }
        inputQueue.InputCompleted += HandleInputCompleted;
    }

    private void HandleInputCompleted(object sender, InputCompletedEventArgs e)
    {
        unsafe
        {
            byte* shortPtr = (byte*)e.UnsafeBuffer->AudioData;
            for (int count = heading.Length; count < sendBuffer[sendOutIndex].Length; count++)
            {
                sendBuffer[sendOutIndex][count] = *shortPtr;
                shortPtr++;
            }
        }
        socket.SendTo(sendBuffer[sendOutIndex], master);
        this.inputQueue.EnqueueBuffer(e.IntPtrBuffer, AudioBufferLength, null);
        sendOutIndex = (sendOutIndex + 1) % CountAudioBuffers;
    }

根据AEC on OSX using AudioQueue,我了解到有关将原始声音数据传递到I / O单元(音频单元?)的提示。但是由于Xamarin.iOS(c#)中缺少示例,因此我无法弄清楚如何详细实现此过程。熟悉Xamarin平台上的Voip应用程序开发的任何人都可以给我一些示例进行研究吗?非常感谢对此的任何帮助或提示。

(2018年11月21日)我发现了一些相关的帖子:Record audio with audio unit Audio unit Callbacks An audio unit example

2 个答案:

答案 0 :(得分:0)

我建议分析系统中回波的性质(例如test the echo path)。也许这超出了内置回声消除的功能。

答案 1 :(得分:0)

最后,我们弄清楚了如何在Xamarin.iOS平台上打开iOS内置AEC。 here文档对音频单元(即使该文档适用于iOS本机开发环境)的详细信息和工作机制有很多帮助。如果要精确控制每个音频单元并了解功能中的参数,则必须阅读本文档。

作品here为在Audio Unit上进行实验提供了一个很好的起点。我在本文的第2步中做了一些修改。关键部分是我们必须使用AudioTypeOutput.VoiceProcessingIO,这将启用AEC。

public void prepareAudioUnit()
    {

        var _audioComponent =   AudioComponent.FindComponent(AudioTypeOutput.VoiceProcessingIO);

        audioUnit = new AudioUnit.AudioUnit(_audioComponent);

        audioUnit.SetEnableIO(true,
            AudioUnitScopeType.Input,
            1 // Remote Input
        );

        // setting audio format
        audioUnit.SetAudioFormat(audioStreamBasicDesc,
            AudioUnitScopeType.Output,
            1
        );                                    

        audioUnit.SetInputCallback(input_CallBack, AudioUnitScopeType.Input, 1);

        audioUnit.SetRenderCallback(render_CallBack, AudioUnitScopeType.Global, 0);


        audioUnit.Initialize();
        audioUnit.Start();
    }