Files
Infratest/Assets/Code/Infrastructure/Audio/AudioService.cs
T

133 lines
5.4 KiB
C#

using System.Collections.Generic;
using System.Threading;
using Code.Infrastructure.EventBus;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Audio;
namespace Code.Infrastructure.Audio
{
public interface IAudioService
{
AudioClip GetClip(AudioNames groupName, int id);
void PlayTest();
UniTaskVoid PlayOneShot(AudioNames groupName, int id, Vector3 position = new Vector3(),
AudioSourceType sourceType = AudioSourceType.NoBlend,
AudioSource audioSource = null);
UniTaskVoid PlayRepeatedly(AudioNames groupName, int id,
AudioSourceType sourceType = AudioSourceType.NoBlend, AudioSource audioSource = null, CancellationTokenSource cancellationTokenSource = null);
bool CheckClip(AudioNames groupName, int id);
void CancelMusic(AudioNames groupName, int id);
void ReleaseCancellationSource(AudioNames groupName, int id);
}
public partial class AudioService : IAudioClipsEventHandle, IAudioService
{
private EventBus.EventBus _eventBus;
private IAudioFactory _audioFactory;
private IAudioSourcePool _pool;
private Dictionary<AudioNames, Dictionary<int, AudioClip>> _audioClips = new();
private AudioMixer _mixer;
private Dictionary<AudioGroupType, AudioMixerGroup> _audioMixerGroups = new();
public AudioService(EventBus.EventBus eventBus, IAudioFactory audioFactory, IAudioSourcePool pool)
{
_eventBus = eventBus;
_audioFactory = audioFactory;
_pool = pool;
_eventBus.Subscribe(this);
for (int i = 0; i < typeof(AudioNames).GetEnumValues().Length; i++)
_audioClips.Add((AudioNames)i, new Dictionary<int, AudioClip>());
//InitializeMixer();
}
private partial void InitializeMixer();
public void PlayTest()
{
_pool.GetSource(AudioSourceType.NoBlend).PlayOneShot(GetClip(AudioNames.UISounds, 0));
}
public async UniTaskVoid PlayOneShot(AudioNames groupName, int id, Vector3 position = new Vector3(),
AudioSourceType sourceType = AudioSourceType.NoBlend,
AudioSource audioSource = null)
{
if (!CheckClip(groupName, id)) return;
if (!audioSource) audioSource = _pool.GetSource(sourceType);
audioSource.transform.position = position;
audioSource.PlayOneShot(GetClip(groupName, id));
await UniTask.NextFrame();
await UniTask.WaitUntilValueChanged(audioSource, _ => !audioSource.isPlaying);
_pool.ReleaseSource(audioSource);
}
private Dictionary<KeyValuePair<AudioNames, int>, CancellationTokenSource> _cancellationTokenSources = new();
public void CancelMusic(AudioNames groupName, int id) => _cancellationTokenSources[new KeyValuePair<AudioNames, int>(groupName, id)].Cancel();
public void ReleaseCancellationSource(AudioNames groupName, int id) => _cancellationTokenSources[new KeyValuePair<AudioNames, int>(groupName, id)] = null;
public async UniTaskVoid PlayRepeatedly(AudioNames groupName, int id,
AudioSourceType sourceType = AudioSourceType.NoBlend, AudioSource audioSource = null, CancellationTokenSource cancellationTokenSource = null)
{
if (!CheckClip(groupName, id)) return;
if(cancellationTokenSource == null)
{
cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSources[new KeyValuePair<AudioNames, int>(groupName, id)] = cancellationTokenSource;
}
if (!audioSource) audioSource = _pool.GetSource(sourceType);
if(!audioSource.resource) audioSource.resource = GetClip(groupName, id);
audioSource.Play();
await UniTask.NextFrame();
var (isCanceled, _) = await UniTask.WaitUntilValueChanged(audioSource,
_ => !audioSource.isPlaying,
cancellationToken: cancellationTokenSource.Token).SuppressCancellationThrow();
UnityEngine.Debug.LogError("Music skipping");
if (isCanceled)
{
cancellationTokenSource.Dispose();
_pool.ReleaseSource(audioSource);
ReleaseCancellationSource(groupName,id);
return;
}
PlayRepeatedly(groupName, id, sourceType, audioSource, cancellationTokenSource).Forget();
}
public AudioClip GetClip(AudioNames groupName, int id) => _audioClips[groupName][id];
public bool CheckClip(AudioNames groupName, int id) => _audioClips[groupName].ContainsKey(id);
public void AudioClipsLoaded(AudioNames groupname, Dictionary<int, AudioClip> clips)
{
_audioClips[groupname] = clips;
_eventBus.RaiseEvent<IReadyToPlayHandle>(x => x.OnReadyToPlay(groupname));
}
public void AudioClipsUnLoaded(AudioNames groupName)
{
_audioClips[groupName].Clear();
_audioClips[groupName] = null;
}
}
public interface IReadyToPlayHandle : IGlobalSubscriber
{
void OnReadyToPlay(AudioNames groupName);
}
}