unity-game-enginewebrtchololensturn

Hearing the remote audio track twice using WebRTC with a TURN server on the HoloLens 2


I'm developing a TeamViewer like application for the HoloLens 2 using: https://github.com/microsoft/MixedReality-WebRTC

I'm connecting a WebApp (Webcam) with the HoloLens 2 (ArCam) via signaling server.

Now everything worked fine locally all the time, just using the PeerToPeer connection. But after I switched to a TURN server for the communication, I hear the remote audio (from WebApp) twice on the HoloLens 2, like a an echo. It feels like there are two audio tracks playing at the same time with a minimal delay of .1 sec. Only one AudioSource and one remote audiotrack are present, when this happens. The weird part is, that this only occurs on the HoloLens. Running the same application inside the unity editor also works fine.

Does anyone have a suggetion, why this is happening?

Using: Unity 2022.3.7f1

MS-WebRTC: 2.0.2

MRTK: 2.8.3

PS: I'm aware that Microsoft WebRTC is deprecated, but that's fine for me at the moment.


Solution

  • Ok, I found the problem. Turns out this is a bug in the Ms-WebRTC library that they could not fix before the project was iced:

    https://github.com/microsoft/MixedReality-WebRTC/issues/717

    If you run into this problem, make sure to uncomment everyting inside the method "OnAudioFilterRead(...)" of the class AudioRenderer. I just made sure that the code is not compiled outside the unity editor unsing platform specific code

    (#if UNITY_EDITOR ... #endif)

            protected void OnAudioFilterRead(float[] data, int channels)
            {
    #if UNITY_EDITOR
                // Don't do this outside the editor becuase it causes AudioTack to render twice on HoloLens
                var behavior = PadWithSine ?
                    AudioTrackReadBuffer.PadBehavior.PadWithSine :
                    AudioTrackReadBuffer.PadBehavior.PadWithZero;
                bool hasRead = false;
                bool hasOverrun = false;
                bool hasUnderrun = false;
    
                lock (_readBufferLock)
                {
                    // Read and use buffer under lock to prevent disposal while in use.
                    if (_readBuffer != null)
                    {
                        _readBuffer.Read(_audioSampleRate, channels, data,
                            out int numSamplesRead, out hasOverrun, behavior);
                        hasRead = true;
                        hasUnderrun = numSamplesRead < data.Length;
                    }
                }
    
                if (hasRead)
                {
                    // Uncomment for debugging.
                    //if (hasOverrun)
                    //{
                    //    Debug.LogWarning($"Overrun in track {Track.Name}");
                    //}
                    //if (hasUnderrun)
                    //{
                    //    Debug.LogWarning($"Underrun in track {Track.Name}");
                    //}
    
                    return;
                }
    
                // If there is no track/buffer, fill array with 0s.
                for (int i = 0; i < data.Length; ++i)
                {
                    data[i] = 0.0f;
                }
    #endif
            }