Exemplo n.º 1
0
 public static MusicSetting Clone(MusicSetting mus) {
     return new MusicSetting {
         alias = mus.alias,
         audLocation = mus.audLocation,
         clip = mus.clip,
         songName = mus.songName,
         resourceFileName = mus.resourceFileName,
         volume = mus.volume,
         pitch = mus.pitch,
         isExpanded = mus.isExpanded,
         isLoop = mus.isLoop,
         customStartTime = mus.customStartTime,
         songStartedEventExpanded = mus.songStartedEventExpanded,
         songStartedCustomEvent = mus.songStartedCustomEvent,
         songChangedEventExpanded = mus.songChangedEventExpanded,
         songChangedCustomEvent = mus.songChangedCustomEvent
     };
 }
Exemplo n.º 2
0
 public static MusicSetting Clone(MusicSetting mus)
 {
     return(new MusicSetting {
         alias = mus.alias,
         audLocation = mus.audLocation,
         clip = mus.clip,
         songName = mus.songName,
         resourceFileName = mus.resourceFileName,
         volume = mus.volume,
         pitch = mus.pitch,
         isExpanded = mus.isExpanded,
         isLoop = mus.isLoop,
         customStartTime = mus.customStartTime,
         songStartedEventExpanded = mus.songStartedEventExpanded,
         songStartedCustomEvent = mus.songStartedCustomEvent,
         songChangedEventExpanded = mus.songChangedEventExpanded,
         songChangedCustomEvent = mus.songChangedCustomEvent
     });
 }
Exemplo n.º 3
0
        public static MusicSetting Clone(MusicSetting mus, MasterAudio.Playlist aList)
        {
            var clone = new MusicSetting {
                alias                    = mus.alias,
                audLocation              = mus.audLocation,
                clip                     = mus.clip,
                songName                 = mus.songName,
                resourceFileName         = mus.resourceFileName,
                volume                   = mus.volume,
                pitch                    = mus.pitch,
                isExpanded               = mus.isExpanded,
                isLoop                   = mus.isLoop,
                isChecked                = mus.isChecked,
                customStartTime          = mus.customStartTime,
                songStartedEventExpanded = mus.songStartedEventExpanded,
                songStartedCustomEvent   = mus.songStartedCustomEvent,
                songChangedEventExpanded = mus.songChangedEventExpanded,
                songChangedCustomEvent   = mus.songChangedCustomEvent,
                metadataExpanded         = mus.metadataExpanded
            };

            SongMetadataProperty prop = null;

            for (var i = 0; i < mus.metadataStringValues.Count; i++)
            {
                var valToClone = mus.metadataStringValues[i];
                prop = aList.songMetadataProps.Find(delegate(SongMetadataProperty p) {
                    return(p.PropertyName == valToClone.PropertyName);
                });
                var sVal = new SongMetadataStringValue(prop);
                sVal.Value = valToClone.Value;
                clone.metadataStringValues.Add(sVal);
            }

            for (var i = 0; i < mus.metadataFloatValues.Count; i++)
            {
                var valToClone = mus.metadataFloatValues[i];
                prop = aList.songMetadataProps.Find(delegate(SongMetadataProperty p) {
                    return(p.PropertyName == valToClone.PropertyName);
                });
                var fVal = new SongMetadataFloatValue(prop);
                fVal.Value = valToClone.Value;
                clone.metadataFloatValues.Add(fVal);
            }

            for (var i = 0; i < mus.metadataBoolValues.Count; i++)
            {
                var valToClone = mus.metadataBoolValues[i];
                prop = aList.songMetadataProps.Find(delegate(SongMetadataProperty p) {
                    return(p.PropertyName == valToClone.PropertyName);
                });
                var bVal = new SongMetadataBoolValue(prop);
                bVal.Value = valToClone.Value;
                clone.metadataBoolValues.Add(bVal);
            }

            for (var i = 0; i < mus.metadataIntValues.Count; i++)
            {
                var valToClone = mus.metadataIntValues[i];
                prop = aList.songMetadataProps.Find(delegate(SongMetadataProperty p) {
                    return(p.PropertyName == valToClone.PropertyName);
                });
                var iVal = new SongMetadataIntValue(prop);
                iVal.Value = valToClone.Value;
                clone.metadataIntValues.Add(iVal);
            }

            return(clone);
            // ReSharper restore InconsistentNaming
        }
        public static IEnumerator PopulateAddressableSongToPlaylistControllerAsync(MusicSetting setting, AssetReference addressable,
                                                                                   PlaylistController playlistController, PlaylistController.AudioPlayType playType)
        {
            if (!IsAddressableValid(addressable))
            {
                yield break;
            }

            var addressableId = GetAddressableId(addressable);

            AsyncOperationHandle <AudioClip> loadHandle;
            AudioClip addressableClip;
            var       shouldReleaseLoadedAssetNow = false;

            if (AddressableTasksByAddressibleId.ContainsKey(addressableId))
            {
                loadHandle      = AddressableTasksByAddressibleId[addressableId].AssetHandle;
                addressableClip = loadHandle.Result;
            }
            else
            {
                loadHandle = addressable.LoadAssetAsync <AudioClip>();

                while (!loadHandle.IsDone)
                {
                    yield return(MasterAudio.EndOfFrameDelay);
                }

                addressableClip = loadHandle.Result;

                if (addressableClip == null || loadHandle.Status != AsyncOperationStatus.Succeeded)
                {
                    var errorText = "";
                    if (loadHandle.OperationException != null)
                    {
                        errorText = " Exception: " + loadHandle.OperationException.Message;
                    }
                    MasterAudio.LogError("Addressable file for PlaylistController '" + playlistController.name + "' could not be located." + errorText);
                    yield break;
                }

                lock (_syncRoot) {
                    if (!AddressableTasksByAddressibleId.ContainsKey(addressableId))
                    {
                        AddressableTasksByAddressibleId.Add(addressableId, new AddressableTracker <AudioClip>(loadHandle, 0));
                    }
                    else
                    {
                        // race condition reached. Another load finished before this one. Throw this away and use the other, to release memory.
                        shouldReleaseLoadedAssetNow = true;
                        addressableClip             = AddressableTasksByAddressibleId[addressableId].AssetHandle.Result;
                    }
                }
            }

            if (shouldReleaseLoadedAssetNow)
            {
                Addressables.Release(loadHandle);
            }

            if (!AudioUtil.AudioClipWillPreload(addressableClip))
            {
                MasterAudio.LogWarning("Audio Clip for Addressable file '" + addressableClip.name + "' of Playlist Controller '" + playlistController.name + "' has 'Preload Audio Data' turned off, which can cause audio glitches. Addressables should always Preload Audio Data. Please turn it on.");
            }

            // Figure out how to detect stop before loaded, if needed
            var stoppedBeforePlay = false;

            if (stoppedBeforePlay)
            {
                // do nothing, but don't call the delegate or set audio clip for sure!
            }
            else
            {
                playlistController.FinishLoadingNewSong(setting, addressableClip, playType);
            }
        }
        /// <summary>
        /// This method will Stop the Playlist. 
        /// </summary>
        public void StopPlaylist(bool onlyFadingClip = false) {
            if (!ControllerIsReady) {
                Debug.LogError(NotReadyMessage);
                return;
            }

            if (!Application.isPlaying) {
                return;
            }

            _currentSong = null;
            if (!onlyFadingClip) {
                CeaseAudioSource(_activeAudio);
            }

            CeaseAudioSource(_transitioningAudio);
        }
        private bool SongShouldLoop(MusicSetting setting) {
            if (_queuedSongs.Count > 0) {
                return false;
            }

            if (SongIsNonAdvancible) {
                return true;
            }

            return setting.isLoop;
        }
        /*! \endcond */

        #region Monobehavior events

        // ReSharper disable once UnusedMember.Local
        private void Awake() {
            useGUILayout = false;

            if (ControllerIsReady) {
                // already called by lazy load.
                return;
            }

            ControllerIsReady = false;

            // check for "extra" Playlist Controllers of the same name.
            // ReSharper disable once ArrangeStaticMemberQualifier
            var controllers = (PlaylistController[])GameObject.FindObjectsOfType(typeof(PlaylistController));
            var sameNameCount = 0;

            // ReSharper disable once ForCanBeConvertedToForeach
            for (var i = 0; i < controllers.Length; i++) {
                if (controllers[i].ControllerName == ControllerName) {
                    sameNameCount++;
                }
            }

            if (sameNameCount > 1) {
                Destroy(gameObject);
                Debug.Log(
                    "More than one Playlist Controller prefab exists in this Scene with the same name. Destroying the one called '" +
                    ControllerName + "'. You may wish to set up a Bootstrapper Scene so this does not occur.");
                return;
            }
            // end check

            _duckingMode = AudioDuckingMode.NotDucking;
            _currentSong = null;
            _songsPlayedFromPlaylist = 0;

            var audios = GetComponents<AudioSource>();
            if (audios.Length < 2) {
                Debug.LogError("This prefab should have exactly two Audio Source components. Please revert it.");
                return;
            }

            var ma = MasterAudio.SafeInstance;
            _willPersist = ma != null && ma.persistBetweenScenes;

            _audio1 = audios[0];
            _audio2 = audios[1];

            _audio1.clip = null;
            _audio2.clip = null;

            if (_audio1.playOnAwake || _audio2.playOnAwake) {
                Debug.LogWarning(
                    "One or more 'Play on Awake' checkboxes in the Audio Sources on Playlist Controller '" + name +
                    "' are checked. These are not used in Master Audio. Make sure to uncheck them before hitting Play next time. For Playlist Controllers, use the similarly named checkbox 'Start Playlist on Awake' in the Playlist Controller's Inspector.");
            }

            _activeAudio = _audio1;
            _transitioningAudio = _audio2;

#if UNITY_5
            _audio1.outputAudioMixerGroup = mixerChannel;
            _audio2.outputAudioMixerGroup = mixerChannel;

            SetSpatialBlend();
#endif

            _curFadeMode = FadeMode.None;
            _fadeCompleteCallback = null;
            _lostFocus = false;
        }
        /*! \cond PRIVATE */
        public void FinishLoadingNewSong(AudioClip clipToPlay, AudioPlayType playType) {
            _nextSongRequested = false;

            var shouldPopulateClip = playType == AudioPlayType.PlayNow || playType == AudioPlayType.Schedule;
            var clipWillBeAudibleNow = playType == AudioPlayType.PlayNow || playType == AudioPlayType.AlreadyScheduled;

            if (shouldPopulateClip) {
                _audioClip.clip = clipToPlay;
                _audioClip.pitch = _newSongSetting.pitch;
            }

            // set last known time for current song.
            if (_currentSong != null) {
                _currentSong.lastKnownTimePoint = _activeAudio.timeSamples;
            }

            if (clipWillBeAudibleNow) {
                if (CrossFadeTime == 0 || _transClip.clip == null) {
                    CeaseAudioSource(_transClip);
                    _audioClip.volume = _newSongSetting.volume * PlaylistVolume;

                    if (!ActiveAudioSource.isPlaying && _currentPlaylist != null &&
                        (_currentPlaylist.fadeInFirstSong && CrossFadeTime > 0f)) {
                        CrossFadeNow(_audioClip);
                    }
                } else {
                    CrossFadeNow(_audioClip);
                }

                SetDuckProperties();
            }

            switch (playType) {
                case AudioPlayType.AlreadyScheduled:
                    // start crossfading now	
                    _nextSongScheduled = false;
                    RemoveScheduledClip();
                    break;
                case AudioPlayType.PlayNow:
                    _audioClip.Play(); // need to play before setting time or it sometimes resets back to zero.
                    _songsPlayedFromPlaylist++;
                    break;
                case AudioPlayType.Schedule:
#if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5
					Debug.LogError("Master Audio cannot do gapless song transition on Unity 3. Please report this bug to Dark Tonic as it should not happen.");
					return;
#else
                    var scheduledPlayTime = CalculateNextTrackStartTime();

                    ScheduleClipPlay(scheduledPlayTime);

                    _nextSongScheduled = true;
                    _songsPlayedFromPlaylist++;
                    break;
#endif
            }

            var songTimeChanged = false;

            // ReSharper disable once PossibleNullReferenceException
            if (syncGroupNum > 0 &&
                _currentPlaylist.songTransitionType == MasterAudio.SongFadeInPosition.SynchronizeClips) {

                var firstMatchingGroupController = Instances.Find(delegate(PlaylistController obj) {
                    return obj != this &&
                           obj.syncGroupNum == syncGroupNum &&
                           obj.ActiveAudioSource != null &&
                           obj.ActiveAudioSource.isPlaying;
                });

                if (firstMatchingGroupController != null) {
                    var matchingTime = firstMatchingGroupController._activeAudio.timeSamples;
                    if (_audioClip.clip != null && matchingTime < _audioClip.clip.samples) {
                        _audioClip.timeSamples = matchingTime;
                    }

                    songTimeChanged = true;
                }
            }

            // this code will adjust the starting position of a song, but shouldn't do so when you first change Playlists.
            if (_currentPlaylist != null) {
                if (_songsPlayedFromPlaylist <= 1 && !songTimeChanged) {
                    _audioClip.timeSamples = 0;
                    // reset pointer so a new Playlist always starts at the beginning, but don't do it for synchronized! We need that first song to use the sync group.
                } else {
                    switch (_currentPlaylist.songTransitionType) {
                        case MasterAudio.SongFadeInPosition.SynchronizeClips:
                            if (!songTimeChanged) {
                                // otherwise the sync group code above will get defeated.
                                _transitioningAudio.timeSamples = _activeAudio.timeSamples;
                            }
                            break;
                        case MasterAudio.SongFadeInPosition.NewClipFromLastKnownPosition:
                            var thisSongInPlaylist = _currentPlaylist.MusicSettings.Find(delegate(MusicSetting obj) {
                                return
                                    obj ==
                                    _newSongSetting;
                            });

                            if (thisSongInPlaylist != null) {
                                _transitioningAudio.timeSamples = thisSongInPlaylist.lastKnownTimePoint;
                            }
                            break;
                        case MasterAudio.SongFadeInPosition.NewClipFromBeginning:
                            _audioClip.timeSamples = 0; // new song will start at beginning
                            break;
                    }
                }

                // account for custom start time.
                if (_currentPlaylist.songTransitionType == MasterAudio.SongFadeInPosition.NewClipFromBeginning &&
                    _newSongSetting.customStartTime > 0f) {
                    // ReSharper disable once PossibleNullReferenceException
                    _audioClip.timeSamples = (int)(_newSongSetting.customStartTime * _audioClip.clip.frequency);
                }
            }

            if (clipWillBeAudibleNow) {
                _activeAudio = _audioClip;
                _transitioningAudio = _transClip;

                // song changed
                if (songChangedCustomEvent != string.Empty && songChangedEventExpanded && songChangedCustomEvent != MasterAudio.NoGroupName) {
                    MasterAudio.FireCustomEvent(songChangedCustomEvent, Trans.position);
                }

                if (SongChanged != null) {
                    var clipName = String.Empty;
                    if (_audioClip != null) {
                        clipName = _audioClip.clip.name;
                    }
                    SongChanged(clipName);
                }
                // song changed end
            }

            _activeAudioEndVolume = _newSongSetting.volume * PlaylistVolume;
            var transStartVol = _transitioningAudio.volume;
            if (_currentSong != null) {
                transStartVol = _currentSong.volume;
            }

            _transitioningAudioStartVolume = transStartVol * PlaylistVolume;
            _currentSong = _newSongSetting;

            if (clipWillBeAudibleNow && _currentSong.songStartedEventExpanded && _currentSong.songStartedCustomEvent != string.Empty && _currentSong.songStartedCustomEvent != MasterAudio.NoGroupName) {
                MasterAudio.FireCustomEvent(_currentSong.songStartedCustomEvent, Trans.position);
            }

            if (CanSchedule && playType != AudioPlayType.Schedule && !_currentSong.isLoop) {
                ScheduleNextSong();
            }
        }
        private void PlaySong(MusicSetting setting, AudioPlayType playType) {
            _newSongSetting = setting;

            if (_activeAudio == null) {
                Debug.LogError("PlaylistController prefab is not in your scene. Cannot play a song.");
                return;
            }

            AudioClip clipToPlay = null;

            var clipWillBeAudibleNow = playType == AudioPlayType.PlayNow || playType == AudioPlayType.AlreadyScheduled;
            if (clipWillBeAudibleNow && _currentSong != null && !CanSchedule) {
                if (_currentSong.songChangedEventExpanded && _currentSong.songChangedCustomEvent != string.Empty &&
                    _currentSong.songChangedCustomEvent != MasterAudio.NoGroupName) {
                    MasterAudio.FireCustomEvent(_currentSong.songChangedCustomEvent, Trans.position);
                }
            }

            if (playType != AudioPlayType.AlreadyScheduled) {
                if (_activeAudio.clip != null) {
                    var newSongName = string.Empty;
                    switch (setting.audLocation) {
                        case MasterAudio.AudioLocation.Clip:
                            if (setting.clip != null) {
                                newSongName = setting.clip.name;
                            }
                            break;
                        case MasterAudio.AudioLocation.ResourceFile:
                            newSongName = setting.resourceFileName;
                            break;
                    }

                    if (string.IsNullOrEmpty(newSongName)) {
                        Debug.LogWarning(
                            "The next song has no clip or Resource file assigned. Please fix. Ignoring song change request.");
                        return;
                    }
                }

                if (_activeAudio.clip == null) {
                    _audioClip = _activeAudio;
                    _transClip = _transitioningAudio;
                } else if (_transitioningAudio.clip == null) {
                    _audioClip = _transitioningAudio;
                    _transClip = _activeAudio;
                } else {
                    // both are busy!
                    _audioClip = _transitioningAudio;
                    _transClip = _activeAudio;
                }

                if (setting.clip != null) {
                    _audioClip.clip = setting.clip;
                    _audioClip.pitch = setting.pitch;
                }

                _audioClip.loop = SongShouldLoop(setting);

                switch (setting.audLocation) {
                    case MasterAudio.AudioLocation.Clip:
                        if (setting.clip == null) {
                            MasterAudio.LogWarning(
                                "MasterAudio will not play empty Playlist clip for PlaylistController '" +
                                ControllerName + "'.");
                            return;
                        }

                        clipToPlay = setting.clip;
                        break;
                    case MasterAudio.AudioLocation.ResourceFile:
                        if (MasterAudio.HasAsyncResourceLoaderFeature() && ShouldLoadAsync) {
                            StartCoroutine(AudioResourceOptimizer.PopulateResourceSongToPlaylistControllerAsync(
                                    setting.resourceFileName, CurrentPlaylist.playlistName, this, playType));
                        } else {
                            clipToPlay = AudioResourceOptimizer.PopulateResourceSongToPlaylistController(
                                ControllerName, setting.resourceFileName, CurrentPlaylist.playlistName);
                            if (clipToPlay == null) {
                                return;
                            }
                        }

                        break;
                }
            } else {
                FinishLoadingNewSong(null, AudioPlayType.AlreadyScheduled);
            }

            if (clipToPlay != null) {
                FinishLoadingNewSong(clipToPlay, playType);
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// This method will allow you to add a song to a Playlist by code.
        /// </summary>
        /// <param name="playlistName">The name of the Playlist to add the song to.</param>
        /// <param name="song">The Audio clip of the song.</param>
        /// <param name="loopSong">Optional - whether or not to loop the song.</param>
        /// <param name="songPitch">Optional - the pitch of the song.</param>
        /// <param name="songVolume">Optional - The volume of the song.</param>
        public static void AddSongToPlaylist(string playlistName, AudioClip song, bool loopSong = false,
            float songPitch = 1f, float songVolume = 1f) {
            var pl = GrabPlaylist(playlistName);

            if (pl == null) {
                return;
            }

            var newSong = new MusicSetting() {
                clip = song,
                isExpanded = true,
                isLoop = loopSong,
                pitch = songPitch,
                volume = songVolume
            };

            pl.MusicSettings.Add(newSong);
        }