< Summary

Class:DCL.Components.DCLAudioSource
Assembly:DCL.Components.Audio
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs
Covered lines:79
Uncovered lines:16
Coverable lines:95
Total lines:233
Line coverage:83.1% (79 of 95)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
Model()0%110100%
GetDataFromJSON(...)0%110100%
Awake()0%220100%
Initialize(...)0%110100%
InitDCLAudioClip(...)0%220100%
ApplyChanges()0%6.076087.5%
ApplyCurrentModel()0%6.496076.19%
OnAudioSettingsChanged(...)0%2100%
OnVirtualAudioMixerChangedValue(...)0%2100%
UpdateAudioSourceVolume()0%770100%
OnCurrentSceneChanged(...)0%4.034087.5%
OnDestroy()0%220100%
UpdateOutOfBoundariesState(...)0%2.032080%
DclAudioClip_OnLoadingFinished(...)0%12300%
ApplyLoadedAudioClip(...)0%880100%
GetClassId()0%110100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Components/Audio/DCLAudioSource.cs

#LineLine coverage
 1using DCL.Helpers;
 2using System.Collections;
 3using DCL.Controllers;
 4using UnityEngine;
 5using DCL.Models;
 6using DCL.SettingsCommon;
 7using AudioSettings = DCL.SettingsCommon.AudioSettings;
 8
 9namespace DCL.Components
 10{
 11    public class DCLAudioSource : BaseComponent, IOutOfSceneBoundariesHandler
 12    {
 13        [System.Serializable]
 14        public class Model : BaseModel
 15        {
 16            public string audioClipId;
 17            public bool playing = false;
 5018            public float volume = 1f;
 19            public bool loop = false;
 5020            public float pitch = 1f;
 21            public long playedAtTimestamp = 0;
 22
 1823            public override BaseModel GetDataFromJSON(string json) { return Utils.SafeFromJson<Model>(json); }
 24        }
 25
 126        public float playTime => audioSource.time;
 27        internal AudioSource audioSource;
 28        DCLAudioClip lastDCLAudioClip;
 29
 30        private bool isDestroyed = false;
 31        public long playedAtTimestamp = 0;
 32        private bool isOutOfBoundaries = false;
 33
 534        public override string componentName => "AudioSource";
 35
 36        private void Awake()
 37        {
 1538            audioSource = gameObject.GetOrCreateComponent<AudioSource>();
 1539            model = new Model();
 40
 1541            if (Settings.i != null)
 1542                Settings.i.audioSettings.OnChanged += OnAudioSettingsChanged;
 43
 1544            DataStore.i.virtualAudioMixer.sceneSFXVolume.OnChange += OnVirtualAudioMixerChangedValue;
 1545        }
 46
 47        public override void Initialize(IParcelScene scene, IDCLEntity entity)
 48        {
 1549            base.Initialize(scene, entity);
 1550            DataStore.i.sceneBoundariesChecker.Add(entity,this);
 1551        }
 52
 53        public void InitDCLAudioClip(DCLAudioClip dclAudioClip)
 54        {
 2855            if (lastDCLAudioClip != null)
 56            {
 1357                lastDCLAudioClip.OnLoadingFinished -= DclAudioClip_OnLoadingFinished;
 58            }
 59
 2860            lastDCLAudioClip = dclAudioClip;
 2861        }
 62
 263        public double volume => ((Model) model).volume;
 64
 65        public override IEnumerator ApplyChanges(BaseModel baseModel)
 66        {
 3667            yield return new WaitUntil(() => CommonScriptableObjects.rendererState.Get());
 68
 69            //If the scene creates and destroy an audiosource before our renderer has been turned on bad things happen!
 70            //TODO: Analyze if we can catch this upstream and stop the IEnumerator
 1871            if (isDestroyed)
 072                yield break;
 73
 1874            CommonScriptableObjects.sceneNumber.OnChange -= OnCurrentSceneChanged;
 1875            CommonScriptableObjects.sceneNumber.OnChange += OnCurrentSceneChanged;
 76
 1877            ApplyCurrentModel();
 78
 1879            yield return null;
 1780        }
 81
 82        private void ApplyCurrentModel()
 83        {
 1884            if (audioSource == null)
 85            {
 086                Debug.LogWarning("AudioSource is null!.");
 087                return;
 88            }
 89
 1890            Model model = (Model) this.model;
 1891            UpdateAudioSourceVolume();
 1892            audioSource.loop = model.loop;
 1893            audioSource.pitch = model.pitch;
 1894            audioSource.spatialBlend = 1;
 1895            audioSource.dopplerLevel = 0.1f;
 96
 1897            if (model.playing)
 98            {
 1399                DCLAudioClip dclAudioClip = scene.componentsManagerLegacy.GetSceneSharedComponent(model.audioClipId) as 
 100
 13101                if (dclAudioClip != null)
 102                {
 13103                    InitDCLAudioClip(dclAudioClip);
 104                    //NOTE(Brian): Play if finished loading, otherwise will wait for the loading to complete (or fail).
 13105                    if (dclAudioClip.loadingState == DCLAudioClip.LoadState.LOADING_COMPLETED)
 106                    {
 13107                        ApplyLoadedAudioClip(dclAudioClip);
 108                    }
 109                    else
 110                    {
 0111                        dclAudioClip.OnLoadingFinished -= DclAudioClip_OnLoadingFinished;
 0112                        dclAudioClip.OnLoadingFinished += DclAudioClip_OnLoadingFinished;
 113                    }
 114                }
 115                else
 116                {
 0117                    Debug.LogError("Wrong audio clip type when playing audiosource!!");
 118                }
 119            }
 120            else
 121            {
 5122                if (audioSource.isPlaying)
 123                {
 2124                    audioSource.Stop();
 125                }
 126            }
 5127        }
 128
 129        private void OnAudioSettingsChanged(AudioSettings settings)
 130        {
 0131            UpdateAudioSourceVolume();
 0132        }
 133
 134        private void OnVirtualAudioMixerChangedValue(float currentValue, float previousValue)
 135        {
 0136            UpdateAudioSourceVolume();
 0137        }
 138
 139        private void UpdateAudioSourceVolume()
 140        {
 19141            float newVolume = 0;
 142
 143            // isOutOfBoundaries will always be false for global scenes.
 19144            if (!isOutOfBoundaries)
 145            {
 19146                AudioSettings audioSettingsData =
 147                    Settings.i != null ? Settings.i.audioSettings.Data : new AudioSettings();
 19148                newVolume = ((Model) model).volume * Utils.ToVolumeCurve(
 149                    DataStore.i.virtualAudioMixer.sceneSFXVolume.Get() * audioSettingsData.sceneSFXVolume *
 150                    audioSettingsData.masterVolume);
 151            }
 152
 19153            bool isCurrentScene = scene.isPersistent || scene.sceneData.sceneNumber == CommonScriptableObjects.sceneNumb
 154
 19155            audioSource.volume = isCurrentScene ? newVolume : 0f;
 19156        }
 157
 158        private void OnCurrentSceneChanged(int currentSceneNumber, int previousSceneNumber)
 159        {
 3160            if (audioSource == null)
 0161                return;
 162
 3163            Model model = (Model) this.model;
 3164            float volume = 0;
 165
 3166            if (scene.isPersistent || scene.sceneData.sceneNumber == currentSceneNumber)
 167            {
 2168                volume = model.volume;
 169            }
 170
 3171            audioSource.volume = volume;
 3172        }
 173
 174        private void OnDestroy()
 175        {
 15176            isDestroyed = true;
 15177            CommonScriptableObjects.sceneNumber.OnChange -= OnCurrentSceneChanged;
 178
 179            //NOTE(Brian): Unsubscribe events.
 15180            InitDCLAudioClip(null);
 181
 15182            if (Settings.i != null)
 15183                Settings.i.audioSettings.OnChanged -= OnAudioSettingsChanged;
 184
 15185            DataStore.i.virtualAudioMixer.sceneSFXVolume.OnChange -= OnVirtualAudioMixerChangedValue;
 15186            DataStore.i.sceneBoundariesChecker.Remove(entity,this);
 187
 15188            lastDCLAudioClip = null;
 15189            audioSource = null;
 15190        }
 191
 192        public void UpdateOutOfBoundariesState(bool isInsideBoundaries)
 193        {
 1194            if (scene.isPersistent)
 0195                isInsideBoundaries = true;
 196
 1197            isOutOfBoundaries = !isInsideBoundaries;
 1198            UpdateAudioSourceVolume();
 1199        }
 200
 201        private void DclAudioClip_OnLoadingFinished(DCLAudioClip obj)
 202        {
 0203            if (obj.loadingState == DCLAudioClip.LoadState.LOADING_COMPLETED && audioSource != null)
 204            {
 0205                ApplyLoadedAudioClip(obj);
 206            }
 207
 0208            obj.OnLoadingFinished -= DclAudioClip_OnLoadingFinished;
 0209        }
 210
 211        private void ApplyLoadedAudioClip(DCLAudioClip clip)
 212        {
 13213            if (audioSource.clip != clip.audioClip)
 214            {
 13215                audioSource.clip = clip.audioClip;
 216            }
 217
 13218            Model model = (Model) this.model;
 13219            bool shouldPlay = playedAtTimestamp != model.playedAtTimestamp ||
 220                              (model.playing && !audioSource.isPlaying);
 221
 13222            if (audioSource.enabled && model.playing && shouldPlay)
 223            {
 224                //To remove a pesky and quite unlikely warning when the audiosource is out of scenebounds
 13225                audioSource.Play();
 226            }
 227
 13228            playedAtTimestamp = model.playedAtTimestamp;
 13229        }
 230
 1231        public override int GetClassId() { return (int) CLASS_ID_COMPONENT.AUDIO_SOURCE; }
 232    }
 233}