/// <summary> Updates clip list if it changed. (Call from within Update() function) </summary> public void UpdateClips() { if (m_sequence == null) { return; } List <AudioClip> allClips = new List <AudioClip>(m_sequence.Clips.Length); foreach (Sequence.ClipData clip in m_sequence.Clips) { if (clip.m_clip != null) { allClips.Add(clip.m_clip); } } if (allClips.Count == 0) { Debug.LogWarning("No audio clips found in Sequence '" + m_name + "'!"); } bool changed = false; if (allClips.Count != DirectClipData.Length) { //length changed so it definitly changed. changed = true; } else { for (int c = 0; c < DirectClipData.Length; ++c) { if (DirectClipData[c] != allClips[c]) { changed = true; break; } } } if (changed) //update current raw clip list then select our current track if it still exists. { RawAudioData[] newRawClipData = new RawAudioData[allClips.Count]; AudioClip curClip = m_isOutputDirect ? DirectClipData[currentClipIdx] : RawClipData[currentClipIdx].BaseClip; int newClipIdx = -1; for (int c = 0; c < allClips.Count; ++c) { if (allClips[c] == curClip) { newClipIdx = c; } newRawClipData[c] = AmbienceManager.GetAudioData(allClips[c]); } NextClipIdx = -1; if (newClipIdx < 0) { PlayToFade = RawClipData[currentClipIdx]; RawClipData = newRawClipData; newClipIdx = NextClipIdx; DirectFadeOut = true; } else { RawClipData = newRawClipData; } currentClipIdx = newClipIdx; DirectClipData = allClips.ToArray(); if (m_sequence.RandomizeVolume) { curVolumeMod = Helpers.GetRandom(m_sequence.MinMaxVolume); } else { curVolumeMod = 1f; } if (!isSynced && m_sequence.RandomizePlaybackSpeed) { curPlaybackSpeedMod = Helpers.GetRandom(m_sequence.MinMaxPlaybackSpeed); } else { curPlaybackSpeedMod = 1f; } if (MySyncGroup != null) { MySyncGroup.UpdateLength(); } } }
/// <summary> /// Gets a single audio frame with passed number of audio channels /// </summary> /// <param name="step">Time in seconds to add to track time</param> /// <param name="volume">Volume level to multiply audio data by</param> /// <param name="ret">Array to fill with audio data</param> /// <param name="startOffset">Starting offset of Array to begin writing data</param> /// <param name="numChannels">Number of audio channels to create (will duplicate data if numChannels exceeds channel count in clip)</param> public void GetFrame(double step, float volume, float[] ret, int startOffset, int numChannels) { if (m_isOutputDirect || RawClipData.Length == 0) { return; } //advance time for this frame trackTime += step * CurPlaybackSpeed; //ensure we are within the bounds of the clips if (currentClipIdx < 0) { currentClipIdx = 0; } else if (currentClipIdx >= RawClipData.Length) { currentClipIdx = RawClipData.Length - 1; } RawAudioData currentClipData = PlayToFade ?? RawClipData[currentClipIdx]; if (!currentClipData.IsLoaded) //wait for it to finish loading { return; } if (IsPlayOnce && trackTime >= currentClipData.Length) { isDelaying = true; return; } if (PlayToFade != null) { if (m_sequence != null && m_sequence.m_trackFadeTime > 0) { CurFade = Mathf.MoveTowards(CurFade, 0f, (float)step / m_sequence.m_trackFadeTime); } else { CurFade = 0f; } if (CurFade > 0f) { if (m_sequence == null || !m_sequence.m_forceMuted) { PlayToFade.GetFrame(trackTime, CurVolume * volume, ret, startOffset, numChannels); } return; } else { StoppedPlaying = PlayToFade.BaseClip; //Debug.Log("PlayToFade ended."); PlayToFade = null; if (IsPlayOnce) { isDelaying = true; } trackTime = 0.0; } } if (m_sequence != null && isDelaying) { if (trackTime >= m_sequence.TrackDelayTime) { trackTime -= m_sequence.TrackDelayTime; //Debug.Log("Ending delay of " + m_clipData.TrackDelayTime + " seconds."); isDelaying = false; lock (m_sequence.ClipsLockHandle) StartedPlaying = m_sequence.Clips[currentClipIdx].m_clip; m_sequence.TrackDelayTime = -1; } else { return; } } //check for end of track and skip to next if needed while (trackTime >= currentClipData.Length) { lock (m_sequence.ClipsLockHandle) StoppedPlaying = m_sequence.Clips[currentClipIdx].m_clip; if (m_sequence != null) { if (!isSynced && m_sequence.TrackDelayTime > 0f) { isDelaying = true; m_outputNeedsMovedDelay = (float)(trackTime - lastTrackTime) + m_sequence.TrackDelayTime; m_outputNeedsMoved = true; //Debug.Log("Starting delay of " + m_clipData.TrackDelayTime + " seconds."); trackTime -= currentClipData.Length; currentClipIdx = NextClipIdx; if (m_sequence.RandomizeVolume) { curVolumeMod = Helpers.GetRandom(m_sequence.MinMaxVolume); } else { curVolumeMod = 1f; } if (!isSynced && m_sequence.RandomizePlaybackSpeed) { curPlaybackSpeedMod = Helpers.GetRandom(m_sequence.MinMaxPlaybackSpeed); } else { curPlaybackSpeedMod = 1f; } //reset our property values to get a new value for next check NextClipIdx = -1; crossFadeFlag = false; } else { if (isSynced && NextClipIdx < 0) //can't repeat so make sure we don't try to go past the end { return; } m_outputNeedsMovedDelay = (float)(trackTime - lastTrackTime); m_outputNeedsMoved = true; float crossFadeValue = Mathf.Min(m_sequence.m_crossFade, Mathf.Min(currentClipData.Length / 2.0f, RawClipData[NextClipIdx].Length / 2.0f)); trackTime -= currentClipData.Length - crossFadeValue; currentClipIdx = NextClipIdx; if (m_sequence.RandomizeVolume) { curVolumeMod = Helpers.GetRandom(m_sequence.MinMaxVolume); } else { curVolumeMod = 1f; } if (!isSynced && m_sequence.RandomizePlaybackSpeed) { curPlaybackSpeedMod = Helpers.GetRandom(m_sequence.MinMaxPlaybackSpeed); } else { curPlaybackSpeedMod = 1f; } //reset our property values to get a new value for next check NextClipIdx = -1; m_sequence.TrackDelayTime = -1f; if (!crossFadeFlag) { lock (m_sequence.ClipsLockHandle) StartedPlaying = m_sequence.Clips[currentClipIdx].m_clip; } else { crossFadeFlag = false; } } } else //end of track but we don't have any base data { return; } } //see if we need to do a cross-fade if (m_sequence != null && m_sequence.m_forceMuted) { return; } if (!IsPlayOnce && ((isSynced && NextClipIdx >= 0) || m_sequence.TrackDelayTime <= 0f) && m_sequence != null && m_sequence.m_crossFade > 0f) { float crossFadeValue = Mathf.Min(m_sequence.m_crossFade, Mathf.Min(currentClipData.Length / 2.0f, RawClipData[NextClipIdx].Length / 2.0f)); //don't want cross-fade to last longer than half of either track. float timeLeft = currentClipData.Length - (float)trackTime; if (timeLeft <= crossFadeValue) { if (!crossFadeFlag) { lock (m_sequence.ClipsLockHandle) StartedPlaying = m_sequence.Clips[NextClipIdx].m_clip; crossFadeFlag = true; } float crossFadeTime = crossFadeValue - timeLeft; float crossFadeAmount = (float)Helpers.Interpolate(crossFadeTime, 0.0, 1.0, crossFadeValue, true, true); currentClipData.GetFrame(trackTime, CurVolume * (1f - crossFadeAmount) * volume, ret, startOffset, numChannels); RawClipData[NextClipIdx].GetFrame(crossFadeTime, CurVolume * crossFadeAmount * volume, ret, startOffset, numChannels); return; } else { crossFadeFlag = false; } } //generate the data for this frame float Fade = 1f; if (!isSynced && !IsPlayOnce && m_sequence.TrackDelayTime > 0 && m_sequence != null && m_sequence.m_delayFadeTime > 0f) //no crossfade but we need to fade out to delay { float timeLeft = currentClipData.Length - (float)trackTime; if (timeLeft <= m_sequence.m_delayFadeTime) { Fade = (timeLeft - m_sequence.m_delayFadeTime) / m_sequence.m_delayFadeTime; } } currentClipData.GetFrame(trackTime, CurVolume * Fade * volume, ret, startOffset, numChannels); }