Placeholder-Software / Dissonance

Unity Voice Chat Asset
69 stars 5 forks source link

AEC not work in the situation of two audiosource.play() #272

Closed jackyetz closed 1 year ago

jackyetz commented 1 year ago

hi,

Unity 2021.3.16. I have two audiosource components established within respective gameobject. One records the microphone and play it immediately, the other one play audioclip received from a remote server. The c# code is as follows, where the remote audioclip is replaced with a local ogg file for the sake of simplicity. Here seems the AEC ( acoustic echo cancellation) not work. There is heavy echo problems. Could u help me more given the following code?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class AudioManager : MonoBehaviour
{
        public AudioSource audioLocal;
    public AudioSource audioRemote;

    private bool isWiredUp = false;
    private IEnumerator coroWire;
    private IEnumerator coroWaitMic;
    // Start is called before the first frame update
    void Start()
        {
        StartCoroWireUp();
        StartCoroutine(PlayRemoteClip());
    }

    private void StartCoroWireUp()
    {
        if (coroWire != null)
            StopCoroutine(coroWire);
        coroWire = Wireup();
        StartCoroutine(coroWire);
    }

    public void StartMicrophone(string mic)
    {

        if (audioLocal != null)
        {
            if (!isWiredUp)
            {
                if (coroWaitMic != null)
                    StopCoroutine(coroWaitMic);
                coroWaitMic = WaitForMic(mic);
                StartCoroutine(coroWaitMic);
            }
        }

    } // end StartMicrophone()

    public void StopMicrophone(string mic = null)
    {
        if (isWiredUp)
        {
            // Stop the Microphone playback.
            Microphone.End(mic);

            if (audioLocal != null)
            {
                // Stop the AudioSource.
                audioLocal.Stop();
                audioLocal.clip = null;
            }

            // The AudioSource will be disconnected, flag it.
            isWiredUp = false;
        }
    } // end StopMicrophone()

     IEnumerator WaitForMic(string mic)
    {
        float timeCheck = Time.time;
        audioLocal.loop = true;
        audioLocal.mute = false;

        var loopLength = 5;

        audioLocal.clip = Microphone.Start(mic, true, loopLength, 16000);

        // Let the Microphone start filling the buffer prior to activating the AudioSource.
        while (!(Microphone.GetPosition(mic) > 0))
        {
            if (Time.time - timeCheck > 5f)
            {
                Debug.Log("[WaitForMic()] - is waiting for the mic to record.");
                timeCheck = Time.time;
            }

            // Wait for Microphone to start gathering data.
            yield return null;
        }

        // If the AudioSource was successfully assigned, play(activate) the AudioSource.
        if (audioLocal.clip)
        {
            audioLocal.Play();
            isWiredUp = true;
        }
        else
        {
            Debug.LogError("[WaitForMic()] ERROR: AudioSource has no clip assigned.");
        }
    } // end WaitForMic()
    IEnumerator Wireup()
    {
        float timeCheck = Time.time;

        // confirm an AudioSource is available && give Unity Microphone systems
        // time to instantiate.
        while (audioLocal == null || Time.time - timeCheck < .1f)
        {
            if (Time.time - timeCheck > 5f)
            {
                Debug.Log("[Wireup()] - is waiting for an AudioSource.");
                timeCheck = Time.time;
            }

            // no AudioSource found? look for an AudioSource attached to this GameObject
            if (audioLocal == null)
                audioLocal = GetComponent<AudioSource>();

            yield return null;
        }

        StartMicrophone(null);

    } // end Wireup()

    IEnumerator PlayRemoteClip()
    {
        WWW www;
        audioRemote = GameObject.Find("remoteClip").GetComponent<AudioSource>();
        yield return www = new WWW(@"D:\mil.moves.ogg");
        audioRemote.clip = www.GetAudioClip();
        audioRemote.loop = true;
        audioRemote.Play();
    }

        // Update is called once per frame
        void Update()
    {

    }
}
martindevans commented 1 year ago

This doesn't appear to be using Dissonance at all?

jackyetz commented 1 year ago

Hi, mart

thank u for reply.

The above is the function I am going to realize, playing the microphone recording and play a remote-return audioclip simultaneously. Without Dissonance I encountered heavy echo problem. Now what I need is how to supress the echo by using Dissonance AEC. I followed the direction https://placeholder-software.co.uk/dissonance/docs/Tutorials/Acoustic-Echo-Cancellation.html, but failed.

I'm here asking help given the above situation.

BTW 1, Without Dissonance AEC, there is not echo problem in PC (win10 & unity 2021.3.16), yet heavy echo in android mobile phone. BTW 2, With Dissonance AEC, I got the msg as in sreenshot.

jackyetz commented 1 year ago

I have two gameobjects (GA and GB). Two AudioSources are established in them, respectively. The above c# code is in a separate script file and is attached in one (for example GA). And the "Dissonance Comms" is also attached in GA.

martindevans commented 1 year ago

I'm not completely sure I undestand what you're trying to do, but as shown this script can't work. The Dissonance AEC system applies to the audio stream which Dissonance records, by using the Microphone class yoursef you're taking control of the microphone away from Dissonance and preventing it from doing anything (such as applying AEC). That's actually what the error message is saying: the audio preprocessor is ready and waiting to process audio, but there's no microphone data flowing in (because you've taken control of it).

If you want to use AEC for recording you'll need to hook up to the Dissonance recorded audio stream. See these docs for information on that.

jackyetz commented 1 year ago

I'm not completely sure I undestand what you're trying to do, but as shown this script can't work. The Dissonance AEC system applies to the audio stream which Dissonance records, by using the Microphone class yoursef you're taking control of the microphone away from Dissonance and preventing it from doing anything (such as applying AEC). That's actually what the error message is saying: the audio preprocessor is ready and waiting to process audio, but there's no microphone data flowing in (because you've taken control of it).

If you want to use AEC for recording you'll need to hook up to the Dissonance recorded audio stream. See these docs for information on that.

Thank martin. I will make a try following your direction. If encountering any further issue I will initiate another thread.