private IEnumerator LoadAndPlayRoutine(IntroloopAudio music) { string musicName = music.audioClip.name; float startLoadingTime = Time.time; float endLoadingTime; music.audioClip.LoadAudioData(); while (music.audioClip.loadState != AudioDataLoadState.Loaded && music.audioClip.loadState != AudioDataLoadState.Failed) { yield return(null); } if (music.audioClip.loadState == AudioDataLoadState.Loaded) { endLoadingTime = Time.time; if (music.audioClip.loadInBackground) { IntroloopLogger.Log(musicName + " loading successful. (Took " + (endLoadingTime - startLoadingTime) + " seconds loading in background.)"); } else { IntroloopLogger.Log(musicName + " loading successful."); } SetupPlayingSchedule(music); } else { IntroloopLogger.LogError(musicName + " loading failed!"); } }
private void SetupPlayingSchedule(IntroloopAudio music) { IntroloopLogger.Log("Playing \"" + music.audioClip.name + "\""); musicAboutToPlay = music; musicAboutToPlay = null; this.music = music; ApplyVolume(); nextSourceToPlay = 0; isPausing = false; twoSources[0].clip = music.audioClip; twoSources[1].clip = music.audioClip; //Essential to cancel the Pause Stop(); //PlayScheduled does not reset the playhead! twoSources[0].time = 0; twoSources[1].time = music.LoopBeginning; //Waiting at the intro part so it will go looping.. double absoluteTimeNow = AudioSettings.dspTime; if (music.nonLooping) { PlayScheduled(0, absoluteTimeNow); IntroloopLogger.Log("Type : Non-looping"); } else if (music.loopWholeAudio) { PlayScheduled(0, absoluteTimeNow); SetScheduledEndTime(0, absoluteTimeNow + music.ClipLength); introFinishDspTime = absoluteTimeNow + music.ClipLength; PlayScheduled(1, absoluteTimeNow + music.ClipLength); nextScheduleTime = absoluteTimeNow + music.ClipLength * 2; IntroloopLogger.Log("Type : Loop whole audio"); } else { PlayScheduled(0, absoluteTimeNow); SetScheduledEndTime(0, absoluteTimeNow + music.IntroLength); introFinishDspTime = absoluteTimeNow + music.IntroLength; //Followed by looping track //If has intro but no looping, music will end and won't loop //But in this case it goes to looping track PlayScheduled(1, absoluteTimeNow + music.IntroLength); nextScheduleTime = (absoluteTimeNow + music.IntroLength) + (music.LoopingLength); IntroloopLogger.Log("Type : Introloop"); } playDspTimestamp = absoluteTimeNow; pauseDspTimestamp = 0; pauseDspTotal = 0; isPlaying = true; }
internal bool Resume() { if (!isPausing) { return(false); } int sourceToContinuePlaying = playingSourceBeforePause; //Rescheduling! double absoluteTimeNow = AudioSettings.dspTime; pauseDspTotal += absoluteTimeNow - pauseDspTimestamp; float remainingTime; if (!music.nonLooping && !music.loopWholeAudio) //If contain intro { if (isPausingOnIntro) { remainingTime = music.IntroLength - (twoSources[sourceToContinuePlaying].time / music.Pitch); } else { remainingTime = music.IntroLength + music.LoopingLength - (twoSources[sourceToContinuePlaying].time / music.Pitch); } } else { remainingTime = music.ClipLength - (twoSources[sourceToContinuePlaying].time / music.Pitch); } //For current track SetScheduledEndTime(sourceToContinuePlaying, absoluteTimeNow + remainingTime); //Intro has no tail! //Order does not matter but both must exist. SetScheduledStartTime(sourceToContinuePlaying, absoluteTimeNow); PlayScheduled(sourceToContinuePlaying, absoluteTimeNow); if (!music.nonLooping) { //For next track SetScheduledStartTime((sourceToContinuePlaying + 1) % 2, absoluteTimeNow + remainingTime); PlayScheduled((sourceToContinuePlaying + 1) % 2, absoluteTimeNow + remainingTime); } if (isPausingOnIntro) { //For the case of pausing on intro too long (so long that the previously scheduled intro has finished) introFinishDspTime = absoluteTimeNow + remainingTime; } nextScheduleTime = AudioSettings.dspTime + rememberHowFarFromNextScheduleTime; isPlaying = true; isPausing = false; IntroloopLogger.Log("\"" + music.audioClip.name + "\" resumed."); return(true); }
internal void Pause() { if (!isPlaying) { return; } //Determining which one is playing? if (twoSources[0].isPlaying && twoSources[1].isPlaying) { //hard case, which one is not actually playing but scheduled? //(Scheduled audio reports isPlaying as true) if (AudioSettings.dspTime < source1WillPlay) { playingSourceBeforePause = 1; } else { playingSourceBeforePause = 0; } } else { //easy case if (twoSources[0].isPlaying) { playingSourceBeforePause = 0; } else { playingSourceBeforePause = 1; } } twoSources[0].Pause(); twoSources[1].Pause(); double pausingDspTime = AudioSettings.dspTime; rememberHowFarFromNextScheduleTime = nextScheduleTime - pausingDspTime; pauseDspTimestamp = pausingDspTime; if (!music.nonLooping && !music.loopWholeAudio) //If contain intro { if (pausingDspTime >= introFinishDspTime) { isPausingOnIntro = false; } else { isPausingOnIntro = true; } } //So the schedule won't cancel the stop by itself isPlaying = false; isPausing = true; IntroloopLogger.Log("\"" + music.audioClip.name + "\" paused."); }
internal void Unload() { music.Unload(); IntroloopLogger.Log(String.Format("Unloaded \"{0}\" from memory.", music.audioClip.name)); twoSources[0].clip = null; twoSources[1].clip = null; music = null; musicAboutToPlay = null; }
internal void Play(IntroloopAudio music, bool isFade) { pauseDspTimestamp = 0; pauseDspTotal = 0; AudioDataLoadState loadState = music.audioClip.loadState; string musicName = music.audioClip.name; FadeVolume = isFade ? 0 : 1; if (loadState != AudioDataLoadState.Loaded) { IntroloopLogger.Log("\"" + musicName + "\" not loaded yet. Loading into memory..."); StartCoroutine(LoadAndPlayRoutine(music)); } else { IntroloopLogger.Log("\"" + musicName + "\" already loaded in memory."); SetupPlayingSchedule(music); } }