Unity Gvoice to TRTC研究

https://github.com/LiteAVSDK/TRTC_Unity/tree/main/TRTC-Simple-Demo/Assets/TRTCSDK/Demo

ビデオ解析度、fps
```c#
"120 x 120",
"160 x 160",
"270 x 270",
"480 x 480",
"160 x 120",
"240 x 180",
"280 x 210",
"320 x 240",
"400 x 300",
"480 x 360",
"640 x 480",
"960 x 720",
"320 x 180",
"480 x 270",
"640 x 360",
"960 x 540",
"1280 x 720",
"1920 x 1080"

"15 fps",
"20 fps",
"24 fps"

// TRTC-Simple-Demo\Assets\TRTCSDK\Demo\SettingScript.cs
SetUpResolution()
SetUpFps()

// Directionもある、これはすごい
SetUpDirection()
"Horizontal screen mode", "Vertical screen mode"

ResolutionDropDownValueChanged（）
```

# GCloud Gvoice Code
```c#
using System;
using UnityEngine;

using GCloud.GVoice;
private IGCloudVoiceEngine sVoiceEngine; // The instance of the gcloud voice engine.
```

この辺調整下さい

```c#
private string UserID = string.Empty;
private const string serverJP = "udp://jp.voice.gcloudcs.com:8700";
private const string serverUS = "udp://us.voice.gcloudcs.com:8700";
private const string AppID = "appid";
private const string AppKey = "appkey";
```

### Awake
```c#
public void Awake(long uid)
{
    if (sVoiceEngine == null)
    {
        Log.Info("Start getting the gvoice engine!");
        sVoiceEngine = GCloudVoice.GetEngine();
    }
    SetEngineAppInfo(uid.ToString());
}

private void SetEngineAppInfo(string userID)
{
    UserID = userID;

    ErrorNo result = sVoiceEngine.SetAppInfo(AppID, AppKey, UserID);
    if (ErrorNo.Succ == result)
    {
        Log.Info("GVoice SetAppInfo success");
    }
    else
    {
        Log.Info("GVoice SetAppInfo fail");
    }

    Log.Info("Start initializing the gvoice engine!");
    ErrorNo ret = sVoiceEngine.Init();
    if (ErrorNo.Succ == ret)
    {
        Log.Info("GVoice Init success");
        IsInited = true;
    }
    else
    {
        Log.Info("GVoice Init fail");
        IsInited = false;
    }
}
```

### Life Cycle
```C#
public void Start()
{
    sVoiceEngine.OnJoinRoomCompleteEvent += OnJoinRoomComplete;
    sVoiceEngine.OnQuitRoomCompleteEvent += OnQuitRoomComplete;
}

public void OnDestroy()
{
    sVoiceEngine.OnJoinRoomCompleteEvent -= OnJoinRoomComplete;
    sVoiceEngine.OnQuitRoomCompleteEvent -= OnQuitRoomComplete;
}

// Update is called once per frame, so you can call the Poll function in this method.
public void Update()
{
    if (sVoiceEngine != null && IsInited)
    {
        sVoiceEngine.Poll();
    }
}
```

### JoinRoom
```
sVoiceEngine.SetServerInfo(serverJP);
sVoiceEngine.JoinTeamRoom(roomName, timeout);
```

### LeaveRoom
```
sVoiceEngine.QuitRoom(mRoomName, mTimeOut);
```

## Full Code
```C#
using System;
using UnityEngine;
using GCloud.GVoice;

public class GVoiceComponent : Component
{
    public static GVoiceComponent Instance { private set; get; }

    public int SpeakerVolume { get; private set; } = 0;
    public int MicrophoneVolume { get; private set; } = 0;

    private const string AppID = "appid";
    private const string AppKey = "appkey";
    private const string foreignAddressJp = "udp://jp.voice.gcloudcs.com:8700";
    private const string foreignAddressUs = "udp://us.voice.gcloudcs.com:8700";
    private string UserID = string.Empty;

    private IGCloudVoiceEngine sVoiceEngine; // The instance of the gcloud voice engine.
    private Mode sCurMode;
    private bool IsGamePaused = true;         // A bool variable used for recording the state of the game.

    private bool IsInited = false;                 // The voice engine has been successfully initialized or not.

    private int _mJoinRoomType; // 0: Initial state 1:TeamRoom 2:NationalRoom

    private MemberRole SCurrentRole;

    private int lastSpeakerVolume = 0;

    private int lastMicrophoneVolume = 0;

    public bool isSpeakerMuted
    {
        private set;
        get;
    }

    public bool isMicrophoneMuted
    {
        private set;
        get;
    }

    public void Awake(long uid)
    {
        Instance = this;

        // Initialize the gcloud voice engine.
        if (sVoiceEngine == null)
        {
            Log.Info("Start getting the gvoice engine!");
            sVoiceEngine = GCloudVoice.GetEngine();
        }

        if (sVoiceEngine != null)
        {
            Log.Info("GVoice GetEngine success");
            Log.Info("GVoice SetAppInfo");
        }
        else
        {
            Log.Info("GVoice GetEngine fail");
        }

        SetEngineAppInfo(uid.ToString());
    }

    private void SetEngineAppInfo(string userID)
    {
        UserID = userID;

        ErrorNo result = sVoiceEngine.SetAppInfo(AppID, AppKey, UserID);
        if (ErrorNo.Succ == result)
        {
            Log.Info("GVoice SetAppInfo success");
        }
        else
        {
            Log.Info("GVoice SetAppInfo fail");
        }

        Log.Info("Start initializing the gvoice engine!");
        ErrorNo ret = sVoiceEngine.Init();
        if (ErrorNo.Succ == ret)
        {
            Log.Info("GVoice Init success");
            IsInited = true;
        }
        else
        {
            Log.Info("GVoice Init fail");
            IsInited = false;
        }
    }

    public void Start()
    {
        sVoiceEngine.OnJoinRoomCompleteEvent += OnJoinRoomComplete;
        sVoiceEngine.OnQuitRoomCompleteEvent += OnQuitRoomComplete;
    }

    public void OnDestroy()
    {
        sVoiceEngine.OnJoinRoomCompleteEvent -= OnJoinRoomComplete;
        sVoiceEngine.OnQuitRoomCompleteEvent -= OnQuitRoomComplete;
    }

    // Update is called once per frame, so you can call the Poll function in this method.
    public void Update()
    {
        if (sVoiceEngine != null && IsInited)
        {
            sVoiceEngine.Poll();
        }
    }

    public bool GotoRealTime()
    {
        Log.Info("GVoice SetMode(GCloudVoiceMode.RealTime)");
        ErrorNo ret = sVoiceEngine.SetMode(Mode.RealTime);
        if (ErrorNo.Succ == ret)
        {
            Log.Info("GVoice SetMode success");
            sCurMode = Mode.RealTime;
            return true;
        }
        else
        {
            Log.Info("GVoice SetMode fail with code " + ret);
            return false;
        }
    }

    // When MessageBtn clicked, this method will be called.
    public void GotoOfflineMessage()
    {
        Debug.Log("GVoice SetMode(GCloudVoiceMode.Messages)");
        ErrorNo ret = sVoiceEngine.SetMode(Mode.Messages);
        if (ErrorNo.Succ == ret)
        {
            Log.Info("GVoice SetMode success");
            sCurMode = Mode.Messages;
        }
        else
        {
            Log.Info("GVoice SetMode fail with code " + ret);
        }
    }

    public void GotoVoice2Text()
    {
        Log.Info("GVoice SetMode(GCloudVoiceMode.RSTT)");
        ErrorNo ret = sVoiceEngine.SetMode(Mode.RSTT);
        if (ErrorNo.Succ == ret)
        {
            Log.Info("GVoice SetMode success");
            sCurMode = Mode.RSTT;
        }
        else
        {
            Log.Info("GVoice SetMode fail with code " + ret);
        }
    }

    /**
     * A function for starting of the game,
     * you should call the GCloudVoiceEngine's Resume function in this method.
     * The specific complentation steps should be completed by youself.
     */
    public void ResumeGVoice()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("Game start");
            sVoiceEngine.Resume();
        }
    }

    /**
     * A function for pausing of the game,
     * you should call the GCloudVoiceEngine's Pause function in this method.
     * The specific complentation steps should be completed by youself.
     */
    public void PauseGVoice()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("Game pause");
            sVoiceEngine.Pause();
        }
    }

    private void OnJoinRoomComplete(CompleteCode code, string roomName, int memberID)
    {
        Log.Info("OnJoinRoomComplete " + code);
        if (CompleteCode.JoinRoomSucc == code)
        {
            if (_mJoinRoomType == 1)
            {
                Log.Info("Join team room success.\t Room name is " + roomName + ".\t Member ID is " + memberID);
            }
            else if (_mJoinRoomType == 2)
            {
                Log.Info("Join national room success.\t Room name is " + roomName + ".\t Member ID is " + memberID);
            }
        }
        else
        {
            Log.Info("Join room fail.\t Room name is " + roomName);
        }
    }

    private void OnQuitRoomComplete(CompleteCode code, string roomName, int memberID)
    {
        if (code == CompleteCode.QuitRoomSucc)
        {
            Log.Info("Quit room success.\t Room name is " + roomName);
            quitRoomCompleteTask.SetResult(true);
        }
        else
        {
            Log.Info("Quit room fail.\t Room name is " + roomName + ".\tCode is " + code);
            quitRoomCompleteTask.SetResult(false);
        }
    }

    public void JoinAnchorNationalRoom()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("GVoice JoinNationalRoom as Anchor");

            // The name of the room which you want to join in,
            // you should specific it by yourself.
            string mRoomName = "abc";
            int mTimeOut = 10000;
            sVoiceEngine.JoinNationalRoom(mRoomName, MemberRole.Anchor,
                mTimeOut);
            _mJoinRoomType = 2;
            SCurrentRole = MemberRole.Anchor;
            // The result of JoinTeamRoom needs to be obtained from callback method
            // -- OnJoinRoomComplete
        }
    }

    public void JoinAudienceNationalRoom()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("GVoice JoinNationalRoom as Audience");

            // The name of the room which you want to join in,
            // you should specific it by yourself.
            string mRoomName = "abc";
            int mTimeOut = 10000;
            sVoiceEngine.JoinNationalRoom(mRoomName, MemberRole.Audience, mTimeOut);
            _mJoinRoomType = 2;
            SCurrentRole = MemberRole.Audience;
            // The result of JoinTeamRoom needs to be obtained from callback method
            // -- OnJoinRoomComplete
        }
    }

    /// <summary>
    /// open mic
    /// </summary>
    /// <returns></returns>
    public bool OpenMicrophone()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("GVoice OpenMic");
            ErrorNo ret = sVoiceEngine.OpenMic();
            if (ErrorNo.Succ == ret)
            {
                Log.Info("GVoice OpenMic success");
                sVoiceEngine.SetMicVolume(MicrophoneVolume);
                return true;
            }
            else
            {
                Log.Info("GVoice OpenMic fail with error code " + ret);
                return false;
            }
        }
        return false;
    }

    /// <summary>
    /// close mic
    /// </summary>
    /// <returns></returns>
    public bool CloseMicrophone()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("GVoice CloseMic");
            ErrorNo ret = sVoiceEngine.CloseMic();
            if (ErrorNo.Succ == ret)
            {
                Log.Info("GVoice CloseMic success");
                return true;
            }
            else
            {
                Log.Info("GVoice CloseMic fail with error code " + ret);
                return false;
            }
        }
        return true;
    }

    /// <summary>
    /// open speaker
    /// </summary>
    /// <returns></returns>
    public bool OpenSpeaker()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("GVoice OpenSpeaker");
            ErrorNo ret = sVoiceEngine.OpenSpeaker();
            if (ErrorNo.Succ == ret)
            {
                Log.Info("GVoice OpenSpeaker success");
                sVoiceEngine.SetSpeakerVolume(SpeakerVolume);
                return true;
            }
            else
            {
                Log.Info("GVoice OpenSpeaker fail with error code " + ret);
                return false;
            }
        }
        return false;
    }

    /// <summary>
    /// close speaker
    /// </summary>
    /// <returns></returns>
    public bool CloseSpeaker()
    {
        if (sVoiceEngine != null)
        {
            Log.Info("GVoice CloseSpeaker");
            ErrorNo ret = sVoiceEngine.CloseSpeaker();
            if (ErrorNo.Succ == ret)
            {
                Log.Info("GVoice CloseSpeaker success");
                return true;
            }
            else
            {
                Log.Info("GVoice CloseSpeaker fail with error code " + ret);
                return false;
            }
        }
        return false;
    }

    /// <summary>
    /// set speaker volume
    /// Timing: Before Open Speaker
    /// windows 0-100, other 0-150
    /// </summary>
    /// <param name="vol"></param>
    public void SetSpeakerVolume(float normalizeVol)
    {
        normalizeVol = Mathf.Clamp01(normalizeVol);
        int vol = 0;
#if UNITY_STANDALONE_WIN
        vol = (int)(normalizeVol * 100);
#else
        vol = (int)(normalizeVol * 150);
#endif
        lastSpeakerVolume = vol;
        SpeakerVolume = vol;
        sVoiceEngine.SetSpeakerVolume(vol);
    }

    /// <summary>
    /// get speaker volume
    /// Timing: After Open Speaker
    /// </summary>
    /// <returns></returns>
    public float GetSpeakerVolume()
    {
        float vol = SpeakerVolume;
#if UNITY_STANDALONE_WIN
        vol = Mathf.Clamp01(vol / 100f);
#else
        vol = Mathf.Clamp01(vol / 150f);
#endif
        return vol;
    }

    /// <summary>
    /// set mic volume
    /// windows：-1000～1000；android, ios：-150～150
    /// </summary>
    /// <param name="vol"></param>
    public void SetMicrophoneVolume(float normalizeVol)
    {
        normalizeVol = Mathf.Clamp01(normalizeVol);
        int vol = 0;
#if UNITY_STANDALONE_WIN
        vol = (int)(normalizeVol * 1000);
#else
        vol = (int)(normalizeVol * 150);
#endif
        lastMicrophoneVolume = vol;
        MicrophoneVolume = vol;
        sVoiceEngine.SetMicVolume(vol);
    }

    /// <summary>
    /// get mic volume
    /// Timing: After Open Mic
    /// </summary>
    /// <returns></returns>
    public float GetMicrophoneVolume()
    {
        float vol = MicrophoneVolume;
#if UNITY_STANDALONE_WIN
        vol = Mathf.Clamp01(vol * 0.001f);
#else
        vol = Mathf.Clamp01(vol * 0.006666f);
#endif
        return vol;
    }

    /// <summary>
    /// mute speaker
    /// </summary>
    /// <param name="muted"></param>
    public void EnableSpeakerVolumeMuted(bool muted)
    {
        if (muted)
        {
            SpeakerVolume = 0;
            sVoiceEngine.SetSpeakerVolume(0);
        }
        else
        {
            SpeakerVolume = lastSpeakerVolume;
            sVoiceEngine.SetSpeakerVolume(lastSpeakerVolume);
        }
        isSpeakerMuted = muted;
    }

    /// <summary>
    /// mute mic
    /// </summary>
    /// <param name="muted"></param>
    public void EnableMicrophoneVolumeMuted(bool muted)
    {
        int vol = 0;
#if UNITY_STANDALONE_WIN
        vol = -1000;
#else
        vol = -150;
#endif
        if (muted)
        {
            MicrophoneVolume = vol;
            sVoiceEngine.SetMicVolume(vol);
        }
        else
        {
            MicrophoneVolume = lastMicrophoneVolume;
            sVoiceEngine.SetMicVolume(lastMicrophoneVolume);
        }
        isMicrophoneMuted = muted;
    }

    public void SaveSetting()
    {
        float spk = GetSpeakerVolume();
        float mic = GetMicrophoneVolume();
        PlayerPrefs.SetInt("SpeakerMute", isSpeakerMuted ? 1 : 0);
        PlayerPrefs.SetInt("MicrophoneMute", isMicrophoneMuted ? 1 : 0);
        PlayerPrefs.SetFloat("SpeakerVolume", spk);
        PlayerPrefs.SetFloat("MicrophoneVolume", mic);
        PlayerPrefs.Save();
    }

    public void LoadSetting()
    {
        bool isSpk = PlayerPrefs.GetInt("SpeakerMute") == 1;
        bool isMic = PlayerPrefs.GetInt("MicrophoneMute") == 1;
        float spk = PlayerPrefs.GetFloat("SpeakerVolume", 0.5f);
        float mic = PlayerPrefs.GetFloat("MicrophoneVolume", 0.5f);

        SetSpeakerVolume(spk);
        SetMicrophoneVolume(mic);
        EnableSpeakerVolumeMuted(isSpk);
        EnableMicrophoneVolumeMuted(isMic);
    }
}
```