NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/Audio/AudioUnity.cs

603 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using PhxhSDK;
using UnityEngine;
using UnityEngine.Networking;
public class AudioUnity: AudioBase
{
public static float GlobalVolume = 1f;
public static float GlobalMusicVolume = 1f;
public static float GlobalSoundVolume = 1f;
public static float GlobalSpeakVolume = 1f;
private float normalizeVolume = 1f;
private GameObject _posGo;
protected AudioSource _audioSource;
private bool _isSpeak;
private bool _isStory;
private static long _curPlayID;
private long _playID = -1; //播放ID越小越早
private AudioClip _clip;
private long _playTime; //最近一次播放的时间戳
public static Dictionary<string, int> LoadedPath = new();
public long playTime => _playTime;
public AudioClip Clip => _clip;
public long PlayID => _playID;
//public CriAtomExPlayback CriAtomExPlayback;
public bool IsSpeak => _isSpeak;
public bool IsStory => _isStory;
public float Volume => _audioSource.volume;
private float _playPassTime = 0f;
private float _stopPassTime = 0f;
private float _fadeValue = 1f;
private float _fadeInTime = 4f;
private float _fadeOutTime = 4f;
private bool _isInFadeIn; //Fade过程中
private bool _isInFadeOut; //Fade过程中
private bool _isFadeIn;
private bool _isFadeOut;
private float _clipVolume = 1f;
private bool _isPlayEnd
{
get
{
if (!_audioSource || !_clip)
{
return false;
}
if (_audioSource.isPlaying)
return _audioSource.time > _clip.length;
else
return true;
}
}
public enum VolumeType
{
Music,
Sound,
Speak
}
#region Construct
public AudioUnity(AudioType audioType, GameObject rootGo, GameObject posGo, AudioInfo audioInfo,
bool loop = false, bool is3D = false)
{
this.audioType = audioType;
_rootGo = rootGo;
_posGo = posGo;
_audioSource = _GetSource();
_audioSource.volume = GlobalVolume;
targetVolume = 1f;
_isSpeak = audioInfo.isSpeak;
}
private AudioSource _GetSource()
{
var source = _rootGo.GetComponent<AudioSource>();
if (!source)
{
source = _rootGo.AddComponent<AudioSource>();
}
// 挂载到 AudioSource 所在物体
// AudioLowPassFilter lowPass = _rootGo.AddComponent<AudioLowPassFilter>();
// lowPass.cutoffFrequency = 10000f; // 12 kHz 截止
// lowPass.lowpassResonanceQ = 1.0f; // 避免共振
// var audioMixerGroup = AudioManager.Instance.masterMixer.FindMatchingGroups("Master");
// source.outputAudioMixerGroup = audioMixerGroup[0];
return source;
}
private void SetSourceData(AudioInfo audioInfo)
{
}
#endregion
#region Inherit
public override void Update()
{
}
public override void Update(float dt)
{
if (!_audioSource || !_clip)
{
return;
}
if (_isFadeIn || _isFadeOut)
{
_UpdateFade(dt);
return;
}
_fadeValue = 1f;
//SetVolume
if (playState == PlayState.Playing || _audioSource.isPlaying)
{
//渐入渐出
//_UpdateFadeValue(dt);
switch (audioType)
{
case (AudioType.Music):
{
_SetMusicVolume();
break;
}
case (AudioType.Sound):
{
if (_isSpeak)
{
_SetSpeakVolume();
}
else
{
_SetSoundVolume();
}
break;
}
default:
break;
}
}
if (playState == PlayState.Paused)
{
return;
}
if (_audioSource.isPlaying == false)
{
_audioSource.Stop();
Stop();
}
if (_posGo && playState == PlayState.Playing)
{
_rootGo.transform.position = _posGo.transform.position;
}
//Update Play Status
if (_isPlayEnd || playState == PlayState.Stopped)
{
Stop();
}
}
private void _UpdateFade(float dt)
{
if (playState == PlayState.Playing || _audioSource.isPlaying)
{
//渐入渐出
_UpdateFadeValue(dt);
switch (audioType)
{
case (AudioType.Music):
{
_SetMusicVolume();
break;
}
case (AudioType.Sound):
{
if (_isSpeak)
{
_SetSpeakVolume();
}
else
{
_SetSoundVolume();
}
break;
}
default:
break;
}
}
if (_posGo && playState == PlayState.Playing)
{
_rootGo.transform.position = _posGo.transform.position;
}
//Update Play Status
if (_isPlayEnd)
{
if (_stopPassTime > _fadeOutTime)
{
Stop();
}
}
}
public override void Pause()
{
_audioSource.Pause();
playState = PlayState.Paused;
}
public override void Resume()
{
_audioSource.UnPause();
playState = PlayState.Playing;
}
public override void Play(float volume = 1f)
{
playState = PlayState.Playing;
_isFadeOut = false;
//_criAtomSource.player?.DetachFader();
targetVolume = 1f;
_audioSource.Play();
_playID = _GenPlayID();
_playTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
}
public void PlayWithFade(float volume = 1f)
{
playState = PlayState.Playing;
//_criAtomSource.player?.AttachFader();
_audioSource.Play();
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.RemovePlaying(audioType, audioID);
}
public void Stop()
{
_isFadeOut = false;
_isFadeIn = false;
_isInFadeIn = false;
_isInFadeOut = false;
_playPassTime = 0;
_stopPassTime = 0;
AudioManager.Instance.AudioMgrObj.RemovePlaying(audioType, audioID);
if (_isPlayEnd)
{
playState = PlayState.Stopped;
return;
}
if (_audioSource)
{
_audioSource.Stop();
}
//_criAtomSource.player?.DetachFader();
base.Stop();
}
public void StopWithFade(float fadeOutTime = 1f)
{
if (_isInFadeOut)
return;
_isFadeOut = true;
_playPassTime = 0f;
_isInFadeOut = true;
_stopPassTime = 0f;
_fadeOutTime = fadeOutTime;
//AudioManager.Instance.AudioMgrObj.RemovePlaying(audioID);
}
#endregion
#region Utils
private long _GenPlayID()
{
return ++_curPlayID;
}
public static void ResetPlayID()
{
_curPlayID = 0;
}
private void _SetMusicVolume()
{
_audioSource.volume = _fadeValue * GlobalMusicVolume * GlobalVolume * targetVolume * normalizeVolume;
}
private void _SetSoundVolume()
{
_audioSource.volume = _fadeValue * GlobalSoundVolume * GlobalVolume * targetVolume * normalizeVolume;
}
private void _SetSpeakVolume()
{
_audioSource.volume = _fadeValue * GlobalSpeakVolume * GlobalVolume * targetVolume * normalizeVolume;
}
private void _SetIs3D(bool is3D)
{
_audioSource.spatialBlend = is3D ? 1f : 0f;
_audioSource.dopplerLevel = 0;
_audioSource.rolloffMode = AudioRolloffMode.Linear;
_audioSource.maxDistance = 150;
}
private void _UpdateFadeValue(float dt)
{
if (_playPassTime > _fadeInTime)
{
_isInFadeIn = false;
_isFadeIn = false;
}
if (_isFadeOut)
{
if(_isFadeIn)
{
targetVolume = _fadeValue;
_isFadeIn = false;
}
}
if (_isFadeIn)
{
if (_playPassTime < _fadeInTime)
{
_isInFadeIn = true;
}
else
{
_isInFadeIn = false;
}
}
if (_isFadeOut)
{
if (_isInFadeOut)
{
_stopPassTime += dt;
}
}
_playPassTime += dt;
_SetCurFadeValue();
}
private void _SetCurFadeValue()
{
if (!_isInFadeIn && !_isInFadeOut)
{
_fadeValue = 1f;
return;
}
if (_isInFadeOut)
{
_fadeValue = (1 - _stopPassTime / _fadeInTime);
if (_fadeValue < 0)
{
_fadeValue = 0;
Stop();
}
return;
}
if (_isInFadeIn && _playPassTime < _fadeInTime)
{
_fadeValue = _playPassTime / _fadeInTime;
if (_fadeValue > 1)
_fadeValue = 1;
}
//_fadeValue = 1f;
}
#endregion
#region API
public void Play(string cueName, AudioInfo audioInfo, bool isLoop = false)
{
_playPassTime = 0f;
targetVolume = 1f;
_isFadeOut = false;
_isFadeIn = false;
playState = PlayState.Playing;
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
}
public async void Play(string path)
{
_clip = await AssetManager.Instance.LoadAssetAsync<AudioClip>(path, null, true);
if (LoadedPath.ContainsKey(path))
{
++LoadedPath[path];
}
else
{
LoadedPath.TryAdd(path, 1);
}
if (!_clip)
{
playState = PlayState.Stopped;
return;
}
_audioSource.clip = _clip;
//_audioSource.cueName = cueName;
_playPassTime = 0f;
_stopPassTime = 0f;
_isFadeOut = false;
_isFadeIn = false;
targetVolume = 1f;
//_criAtomSource.player?.DetachFader();
playState = PlayState.Playing;
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
_audioSource.Play();
}
public async void PlayWithFade(string path, float fadeInTime = 4f, float fadeOutTime = 4f)
{
_clip = await AssetManager.Instance.LoadAssetAsync<AudioClip>(path, null, true);
if (LoadedPath.ContainsKey(path))
{
++LoadedPath[path];
}
else
{
LoadedPath.TryAdd(path, 1);
}
if (!_clip)
{
return;
}
_audioSource.clip = _clip;
_playPassTime = 0f;
_stopPassTime = 0f;
_isFadeOut = false;
_isFadeIn = true;
SetVolume(0);
_audioSource.volume = 0f;
_fadeInTime = fadeInTime;
_fadeOutTime = fadeOutTime;
//_criAtomSource.player?.AttachFader();
playState = PlayState.Playing;
_playID = _GenPlayID();
AudioManager.Instance.AudioMgrObj.Add2Playing(audioType, audioID, _isSpeak);
_audioSource.Play();
}
public void SetIs3D(bool is3D = false)
{
_SetIs3D(is3D);
}
public void SetPosObj(GameObject go = null)
{
if (go)
{
_posGo = go;
if (_rootGo)
{
_rootGo.transform.position = _posGo.transform.position;
_SetIs3D(true);
}
return;
}
_posGo = null;
_SetIs3D(false);
}
public void SetPos(Vector3 position)
{
_rootGo.transform.position = position;
}
public void SetIsLoop(bool isLoop)
{
loop = isLoop;
_audioSource.loop = isLoop;
//DebugUtil.LogError($"audioID:{audioID}, , name:{_criAtomSource.cueName}, isLoop:{isLoop}");
}
public void SetIsSpeak(bool isSpeak)
{
_isSpeak = isSpeak;
}
public void SetNormalizeVolume(float vol = 1f)
{
normalizeVolume = vol;
}
public void SetIsStory(bool isStory)
{
_isStory = isStory;
}
public void SetIsFadeIn(bool isFadeIn)
{
_isFadeIn = isFadeIn;
}
public string GetCueSheetName()
{
if (_audioSource)
{
return _clip.name;
}
return "";
}
public float GetCurPlayLength()
{
if (_audioSource)
{
return _audioSource.time;
}
return -1;
}
public float GetTime()
{
if (!_audioSource)
return -1;
return _audioSource.time;
}
public static void ReleaseLoadedAssets()
{
foreach (var kv in LoadedPath)
{
var key = kv.Key;
var count = kv.Value;
while (count > 0)
{
AssetManager.Instance.Unload(key, false, true);
--count;
}
}
}
#endregion
}
public class AudioConstant
{
/// <summary>
/// 最大音乐播放数
/// </summary>
public const int MaxMusicCount = 1;
/// <summary>
/// 最大音频播放数
/// </summary>
public const int MaxSoundCount = 100;
/// <summary>
/// 最大语音播放数
/// </summary>
public const int MaxSpeakCount = 1;
/// <summary>
/// 优先级
/// </summary>
public const int MaxPriority = 99;
public const int MinPriority = 0;
public const int DefaultPriority = 29;
public const int LowPriority = 30;
}