Files
Prageeth Monasha 48a28457e4 [main] voice added;
2026-02-22 14:21:56 +01:00

224 lines
7.9 KiB
C#

namespace Photon.Voice.Unity.Demos.DemoVoiceUI
{
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
using UnityEngine.UI;
public enum MicType
{
Unity,
Photon,
FMOD
}
public struct MicRef
{
public readonly MicType MicType;
public readonly DeviceInfo Device;
public MicRef(MicType micType, DeviceInfo device)
{
this.MicType = micType;
this.Device = device;
}
public override string ToString()
{
return string.Format("Mic reference: {0}", this.Device.Name);
}
}
public class MicrophoneSelector : VoiceComponent
{
public class MicrophoneSelectorEvent: UnityEvent<MicType, DeviceInfo>
{}
public MicrophoneSelectorEvent onValueChanged = new MicrophoneSelectorEvent();
private List<MicRef> micOptions;
#pragma warning disable 649
[SerializeField]
private Dropdown micDropdown;
[SerializeField]
private Slider micLevelSlider;
[SerializeField]
private Recorder recorder;
[SerializeField]
[FormerlySerializedAs("RefreshButton")]
private GameObject refreshButton;
private Image fillArea;
private Color defaultFillColor = Color.white;
private Color speakingFillColor = Color.green;
#pragma warning restore 649
private IDeviceEnumerator unityMicEnum;
private IDeviceEnumerator photonMicEnum;
#if PHOTON_VOICE_FMOD_ENABLE
private IDeviceEnumerator fmodMicEnum;
// set along with Recorder.InputFactory when switching to FMOD mic and then used for checking if the Recorder.InputFactory is FMOD mic
private System.Func<IAudioDesc> fmodInputFactory;
#endif
protected override void Awake()
{
base.Awake();
// All enumerators trigger refresh automatically in constructor.
unityMicEnum = new Unity.AudioInEnumerator(this.Logger);
#if PHOTON_VOICE_FMOD_ENABLE
// referenced in SetupMicDropdown() called in photonMicEnum initialization
this.fmodMicEnum = new Photon.Voice.FMOD.AudioInEnumerator(FMODUnity.RuntimeManager.CoreSystem, this.Logger);
#endif
photonMicEnum = Platform.CreateAudioInEnumerator(this.Logger);
photonMicEnum.OnReady = () => // refreshes asynchronously on WebGL
{
this.SetupMicDropdown();
this.SetCurrentValue();
};
this.refreshButton.GetComponentInChildren<Button>().onClick.AddListener(RefreshMicrophones);
this.fillArea = this.micLevelSlider.fillRect.GetComponent<Image>();
this.defaultFillColor = this.fillArea.color;
}
private void Update()
{
if (this.recorder != null)
{
this.micLevelSlider.value = this.recorder.LevelMeter.CurrentPeakAmp;
this.fillArea.color = this.recorder.IsCurrentlyTransmitting ? this.speakingFillColor : this.defaultFillColor;
}
}
private void OnEnable()
{
UtilityScripts.MicrophonePermission.MicrophonePermissionCallback += this.OnMicrophonePermissionCallback;
}
private void OnMicrophonePermissionCallback(bool granted)
{
this.RefreshMicrophones();
}
private void OnDisable()
{
UtilityScripts.MicrophonePermission.MicrophonePermissionCallback -= this.OnMicrophonePermissionCallback;
}
private void SetupMicDropdown()
{
this.micDropdown.ClearOptions();
this.micOptions = new List<MicRef>();
List<string> micOptionsStrings = new List<string>();
// using non-breaking spaces in menu items to avoid loosing text after the break
this.micOptions.Add(new MicRef(MicType.Unity, DeviceInfo.Default));
micOptionsStrings.Add(string.Format("[Unity]\u00A0[Default]"));
foreach (var d in this.unityMicEnum)
{
this.micOptions.Add(new MicRef(MicType.Unity, d));
micOptionsStrings.Add(string.Format("[Unity]\u00A0{0}", d));
}
this.micOptions.Add(new MicRef(MicType.Photon, DeviceInfo.Default));
micOptionsStrings.Add(string.Format("[Photon]\u00A0[Default]"));
foreach (var d in this.photonMicEnum)
{
this.micOptions.Add(new MicRef(MicType.Photon, d));
micOptionsStrings.Add(string.Format("[Photon]\u00A0{0}", d));
}
#if PHOTON_VOICE_FMOD_ENABLE
foreach (var d in this.fmodMicEnum)
{
this.micOptions.Add(new MicRef(MicType.FMOD, d));
micOptionsStrings.Add(string.Format("[FMOD]\u00A0{0}", d));
}
#endif
this.micDropdown.AddOptions(micOptionsStrings);
this.micDropdown.onValueChanged.RemoveAllListeners();
this.micDropdown.onValueChanged.AddListener( (x) => this.SwitchToSelectedMic() );
}
public void SwitchToSelectedMic()
{
MicRef mic = this.micOptions[this.micDropdown.value];
switch (mic.MicType)
{
case MicType.Unity:
this.recorder.SourceType = Recorder.InputSourceType.Microphone;
this.recorder.MicrophoneType = Recorder.MicType.Unity;
this.recorder.MicrophoneDevice = mic.Device;
break;
case MicType.Photon:
this.recorder.SourceType = Recorder.InputSourceType.Microphone;
this.recorder.MicrophoneType = Recorder.MicType.Photon;
this.recorder.MicrophoneDevice = mic.Device;
break;
#if PHOTON_VOICE_FMOD_ENABLE
case MicType.FMOD:
this.recorder.SourceType = Recorder.InputSourceType.Factory;
this.recorder.InputFactory = fmodInputFactory = () => new Photon.Voice.FMOD.AudioInReader<short>(FMODUnity.RuntimeManager.CoreSystem, mic.Device.IsDefault ? 0 : mic.Device.IDInt,
(int)recorder.SamplingRate, this.Logger);
break;
#endif
}
onValueChanged?.Invoke(mic.MicType, mic.Device);
}
private void SetCurrentValue()
{
if (this.micOptions == null)
{
Debug.LogWarning("micOptions list is null");
return;
}
this.micDropdown.gameObject.SetActive(true);
this.refreshButton.SetActive(true);
for (int valueIndex = 0; valueIndex < this.micOptions.Count; valueIndex++)
{
MicRef mic = this.micOptions[valueIndex];
if (mic.MicType == MicType.Unity && this.recorder.SourceType == Recorder.InputSourceType.Microphone && this.recorder.MicrophoneType == Recorder.MicType.Unity
|| mic.MicType == MicType.Photon && this.recorder.SourceType == Recorder.InputSourceType.Microphone && this.recorder.MicrophoneType == Recorder.MicType.Photon
#if PHOTON_VOICE_FMOD_ENABLE
|| mic.MicType == MicType.FMOD && this.recorder.SourceType == Recorder.InputSourceType.Factory && this.recorder.InputFactory == fmodInputFactory
#endif
)
{
this.micDropdown.value = valueIndex;
return;
}
}
}
public void RefreshMicrophones()
{
// the result is processed in photonMicEnum.OnReady
this.unityMicEnum.Refresh();
this.photonMicEnum.Refresh();
#if PHOTON_VOICE_FMOD_ENABLE
this.fmodMicEnum.Refresh();
#endif
}
// sync. UI in case a change happens from the Unity Editor Inspector
private void PhotonVoiceCreated()
{
this.RefreshMicrophones();
}
}
}