public void Clear() { state = AudioSourceState.FREE; audioSource.Stop(); transform.localPosition = new Vector3(0, 0, 0); targetTransform = null; }
public IEnumerator Reset() { Debug.Log("Reset"); yield return(new WaitForSeconds(1)); state = AudioSourceState.Stop; PreLoad(); }
void INativeAudioSource.ApplyState(ref AudioSourceState state) { lock (this.strLock) { ALSourceState nativeState = AL.GetSourceState(this.handle); bool looped = state.Looped && !this.isStreamed; if (this.isFirstUpdate || this.lastState.RelativeToListener != state.RelativeToListener) { AL.Source(handle, ALSourceb.SourceRelative, state.RelativeToListener); } if (this.isFirstUpdate || this.lastState.Position != state.Position) { AL.Source(handle, ALSource3f.Position, state.Position.X, -state.Position.Y, -state.Position.Z * 0.5f); } if (this.isFirstUpdate || this.lastState.Velocity != state.Velocity) { AL.Source(handle, ALSource3f.Velocity, state.Velocity.X, -state.Velocity.Y, -state.Velocity.Z); } if (this.isFirstUpdate || this.lastState.MaxDistance != state.MaxDistance) { AL.Source(handle, ALSourcef.MaxDistance, state.MaxDistance); } if (this.isFirstUpdate || this.lastState.MinDistance != state.MinDistance) { AL.Source(handle, ALSourcef.ReferenceDistance, state.MinDistance); } if (this.isFirstUpdate || this.lastState.Looped != looped) { AL.Source(handle, ALSourceb.Looping, looped); } if (this.isFirstUpdate || this.lastState.Volume != state.Volume) { AL.Source(handle, ALSourcef.Gain, state.Volume); } if (this.isFirstUpdate || this.lastState.Pitch != state.Pitch) { AL.Source(handle, ALSourcef.Pitch, state.Pitch); } if (state.Paused && nativeState == ALSourceState.Playing) { AL.SourcePause(handle); } else if (!state.Paused && nativeState == ALSourceState.Paused) { AL.SourcePlay(handle); } this.lastState = state; this.lastState.Looped = looped; this.isFirstUpdate = false; } }
void INativeAudioSource.ApplyState(ref AudioSourceState state) { // ToDo: Implement velocity // ToDo: Implement pitch // ToDo: Implement lowpass // ToDo: Implement pause if (isFirstUpdate || LastState.RelativeToListener != state.RelativeToListener || LastState.Position != state.Position || LastState.MaxDistance != state.MaxDistance || LastState.MinDistance != state.MinDistance || LastState.Volume != state.Volume) { Vector3 distance; if (state.RelativeToListener) { distance = state.Position; } else { distance = state.Position - AudioBackend.ActiveInstance.ListenerPosition; } float maxDistance = (state.MaxDistance - state.MinDistance); float distanceRatio = (Math.Max(distance.Length - state.MinDistance, 0) / maxDistance); distanceRatio = state.Volume * (1f - distanceRatio * distanceRatio); float distanceSideRatio = MathF.Sign(distance.X) * Math.Max(Math.Abs(distance.X) - state.MinDistance * 0.5f, 0) / maxDistance; if (Math.Abs(distanceSideRatio) < 0.00001f) { VolumeLeft = VolumeRight = 1f; } else { const float stereoSeparation = 0.5f; float ratio = MathF.Clamp(distanceSideRatio * 8f, -stereoSeparation, stereoSeparation); VolumeLeft = stereoSeparation - ratio; VolumeRight = stereoSeparation + ratio; } VolumeLeft *= distanceRatio; VolumeRight *= distanceRatio; } LastState = state; LastState.Looped = state.Looped && !IsStreamed; isFirstUpdate = false; }
/// <summary> /// Updates the SoundInstance /// </summary> public void Update() { // Check existence of attachTo object if (this.attachedTo != null && this.attachedTo.Disposed) { this.attachedTo = null; } // Retrieve sound resource values Sound soundRes = this.sound.Res; AudioData audioDataRes = this.audioData.Res; if (soundRes == null || audioDataRes == null) { this.Dispose(); return; } // Set up local variables for state calculation Vector3 listenerPos = DualityApp.Sound.ListenerPos; bool attachedToListener = this.attachedTo != null && ((this.attachedTo == DualityApp.Sound.Listener) || this.attachedTo.IsChildOf(DualityApp.Sound.Listener)); float optVolFactor = this.GetTypeVolFactor(); float priorityTemp = 1000.0f; AudioSourceState nativeState = AudioSourceState.Default; nativeState.MinDistance = soundRes.MinDist; nativeState.MaxDistance = soundRes.MaxDist; nativeState.Volume = optVolFactor * soundRes.VolumeFactor * this.vol * this.curFade * this.pauseFade; nativeState.Pitch = soundRes.PitchFactor * this.pitch; nativeState.Lowpass = soundRes.LowpassFactor * this.lowpass; priorityTemp *= nativeState.Volume; // Calculate 3D source values, distance and priority nativeState.Position = this.pos; nativeState.Velocity = this.vel; if (this.is3D) { Components.Transform attachTransform = this.attachedTo != null ? this.attachedTo.Transform : null; // Attach to object if (this.attachedTo != null) { MathF.TransformCoord(ref nativeState.Position.X, ref nativeState.Position.Y, attachTransform.Angle); MathF.TransformCoord(ref nativeState.Velocity.X, ref nativeState.Velocity.Y, attachTransform.Angle); nativeState.Position += attachTransform.Pos; nativeState.Velocity += attachTransform.Vel; } // Distance check float dist = MathF.Sqrt( (nativeState.Position.X - listenerPos.X) * (nativeState.Position.X - listenerPos.X) + (nativeState.Position.Y - listenerPos.Y) * (nativeState.Position.Y - listenerPos.Y) + (nativeState.Position.Z - listenerPos.Z) * (nativeState.Position.Z - listenerPos.Z) * 0.25f); if (dist > nativeState.MaxDistance) { this.Dispose(); return; } else { priorityTemp *= Math.Max(0.0f, 1.0f - (dist - nativeState.MinDistance) / (nativeState.MaxDistance - nativeState.MinDistance)); } } if (this.notYetAssigned) { // Grab a native audio source if (this.GrabNativeSource()) { this.RegisterPlaying(); } // If there is none available, just stop right there. else { this.Dispose(); return; } } // If the source is stopped / finished, dispose and return if (this.native == null || this.native.IsFinished) { this.Dispose(); return; } // Fading in and out bool fadeOut = this.fadeTarget <= 0.0f; if (!this.paused) { if (this.fadeTarget != this.curFade) { float fadeTemp = Time.TimeMult * Time.SPFMult / Math.Max(0.05f, this.fadeTimeSec); if (this.fadeTarget > this.curFade) { this.curFade += fadeTemp; } else { this.curFade -= fadeTemp; } if (Math.Abs(this.curFade - this.fadeTarget) < fadeTemp * 2.0f) { this.curFade = this.fadeTarget; } } } // Special paused-fading if (this.paused && this.pauseFade > 0.0f) { this.pauseFade = MathF.Max(0.0f, this.pauseFade - Time.TimeMult * Time.SPFMult * 5.0f); } else if (!this.paused && this.pauseFade < 1.0f) { this.pauseFade = MathF.Min(1.0f, this.pauseFade + Time.TimeMult * Time.SPFMult * 5.0f); } // Apply the sounds state to its internal native audio source if (this.native != null) { if (this.is3D) { nativeState.RelativeToListener = attachedToListener; if (attachedToListener) { nativeState.Position -= listenerPos; } // Convert from Duality units to (physical) audio backend units. nativeState.Position *= AudioUnit.LengthToPhysical; nativeState.Velocity *= AudioUnit.VelocityToPhysical; nativeState.MinDistance *= AudioUnit.LengthToPhysical; nativeState.MaxDistance *= AudioUnit.LengthToPhysical; // Post-process sound instance data in listener space float listenerAngle = DualityApp.Sound.ListenerAngle; Vector3 adjustedPos = nativeState.RelativeToListener ? nativeState.Position : nativeState.Position - listenerPos * AudioUnit.LengthToPhysical; MathF.TransformCoord(ref adjustedPos.X, ref adjustedPos.Z, -listenerAngle); // Flatten depth position a little, so far away sounds that can still be seen appear louder adjustedPos.Z *= 0.5f; // Normalize audio position for smooth panning when near. Do it in physical // units, so this remains constant regardless of unit changes. float smoothPanRadius = 5.0f; float listenerSpaceDist = adjustedPos.Length; if (listenerSpaceDist < smoothPanRadius) { float panningActive = listenerSpaceDist / smoothPanRadius; adjustedPos = Vector3.Lerp( new Vector3(0.0f, 0.0f, 1.0f + (smoothPanRadius - 1.0f) * panningActive), adjustedPos, panningActive); } MathF.TransformCoord(ref adjustedPos.X, ref adjustedPos.Z, listenerAngle); nativeState.Position = nativeState.RelativeToListener ? adjustedPos : adjustedPos + listenerPos * AudioUnit.LengthToPhysical; } else { // We'll do a +/- 30° panning for 2D audio Vector2 localPos = Vector2.FromAngleLength( MathF.DegToRad(30.0f * this.panning), 1.0f); nativeState.RelativeToListener = true; nativeState.Position = new Vector3(localPos.X, 0.0f, -localPos.Y); nativeState.Velocity = Vector3.Zero; } nativeState.Looped = this.looped; nativeState.Paused = this.paused && this.pauseFade == 0.0f; this.native.ApplyState(ref nativeState); } // Update play time if (!this.paused) { this.playTime += MathF.Max(0.5f, nativeState.Pitch) * Time.TimeMult * Time.SPFMult; if (this.sound.Res.FadeOutAt > 0.0f && this.playTime >= this.sound.Res.FadeOutAt) { this.FadeOut(this.sound.Res.FadeOutTime); } } // Finish priority calculation this.curPriority = (int)Math.Round(priorityTemp / Math.Sqrt(DualityApp.Sound.GetNumPlaying(this.sound))); // Initially play the source if (this.native.IsInitial && !this.paused) { if (audioDataRes.IsStreamed) { this.native.Play(this); } else if (audioDataRes.Native != null) { this.native.Play(audioDataRes.Native); } } // Remove faded out sources if (fadeOut && nativeState.Volume <= 0.0f) { this.fadeWaitEnd += Time.TimeMult * Time.MsPFMult; // After fading out entirely, wait 50 ms before actually stopping the source to prevent unpleasant audio tick / glitch noises if (this.fadeWaitEnd > 50.0f) { this.Dispose(); return; } } else { this.fadeWaitEnd = 0.0f; } }
public void Update() { AudioSourceState nativeState = AudioSourceState.Default; nativeState.Volume = SettingsCache.MusicVolume * curFade; nativeState.Lowpass = this.lowpass; bool fadeOut = this.fadeTarget <= 0.0f; if (this.fadeTarget != this.curFade) { float fadeTemp = Time.TimeMult * Time.SecondsPerFrame / Math.Max(0.05f, this.fadeTimeSec); if (this.fadeTarget > this.curFade) { this.curFade += fadeTemp; } else { this.curFade -= fadeTemp; } if (Math.Abs(this.curFade - this.fadeTarget) < fadeTemp * 2.0f) { this.curFade = this.fadeTarget; } } if (this.notYetAssigned) { this.notYetAssigned = false; // Grab a native audio source if (openmpt_module == IntPtr.Zero) { this.Dispose(); return; } native = DualityApp.AudioBackend.CreateSource(); native.Play(this); } // If the source is stopped / finished, dispose and return if (this.native == null || this.native.IsFinished) { this.Dispose(); return; } if (fadeOut && nativeState.Volume <= 0.0f) { this.fadeWaitEnd += Time.TimeMult * Time.MillisecondsPerFrame; // After fading out entirely, wait 50 ms before actually stopping the source to prevent unpleasant audio tick / glitch noises if (this.fadeWaitEnd > 50.0f) { this.Dispose(); return; } } else { this.fadeWaitEnd = 0.0f; } native.ApplyState(ref nativeState); }
void INativeAudioSource.ApplyState(ref AudioSourceState state) { lock (this.strLock) { ALSourceState nativeState = AL.GetSourceState(this.handle); bool looped = state.Looped && !this.isStreamed; if (this.isFirstUpdate || this.lastState.RelativeToListener != state.RelativeToListener) { AL.Source(handle, ALSourceb.SourceRelative, state.RelativeToListener); } if (this.isFirstUpdate || this.lastState.Position != state.Position) { AL.Source(handle, ALSource3f.Position, state.Position.X, -state.Position.Y, -state.Position.Z * 0.5f); } if (this.isFirstUpdate || this.lastState.Velocity != state.Velocity) { AL.Source(handle, ALSource3f.Velocity, state.Velocity.X, -state.Velocity.Y, -state.Velocity.Z); } if (this.isFirstUpdate || this.lastState.MaxDistance != state.MaxDistance) { AL.Source(handle, ALSourcef.MaxDistance, state.MaxDistance); } if (this.isFirstUpdate || this.lastState.MinDistance != state.MinDistance) { AL.Source(handle, ALSourcef.ReferenceDistance, state.MinDistance); } if (this.isFirstUpdate || this.lastState.Looped != looped) { AL.Source(handle, ALSourceb.Looping, looped); } if (this.isFirstUpdate || this.lastState.Volume != state.Volume) { AL.Source(handle, ALSourcef.Gain, state.Volume); } if (this.isFirstUpdate || this.lastState.Pitch != state.Pitch) { AL.Source(handle, ALSourcef.Pitch, state.Pitch); } // Update lowpass settings requires Effects extension if (this.isFirstUpdate || this.lastState.Lowpass != state.Lowpass) { var fx = AudioBackend.ActiveInstance.EffectsExtension; if (fx != null) { // If there is no filter, create one when required. if (this.filterHandle == 0 && state.Lowpass < 1.0f) { this.filterHandle = fx.GenFilter(); fx.Filter(this.filterHandle, EfxFilteri.FilterType, (int)EfxFilterType.Lowpass); fx.Filter(this.filterHandle, EfxFilterf.LowpassGain, 1); } // If there is a filter, keep it up-to-date if (this.filterHandle != 0) { fx.Filter(this.filterHandle, EfxFilterf.LowpassGainHF, MathF.Clamp(state.Lowpass, 0.0f, 1.0f)); fx.BindFilterToSource(this.handle, this.filterHandle); } } } if (state.Paused && nativeState == ALSourceState.Playing) { AL.SourcePause(handle); } else if (!state.Paused && nativeState == ALSourceState.Paused) { AL.SourcePlay(handle); } this.lastState = state; this.lastState.Looped = looped; this.isFirstUpdate = false; } }
void INativeAudioSource.ApplyState(ref AudioSourceState state) { lock (this.strLock) { ALSourceState nativeState = AL.GetSourceState(this.handle); bool looped = state.Looped && !this.isStreamed; if (this.isFirstUpdate || this.lastState.RelativeToListener != state.RelativeToListener) AL.Source(handle, ALSourceb.SourceRelative, state.RelativeToListener); if (this.isFirstUpdate || this.lastState.Position != state.Position) AL.Source(handle, ALSource3f.Position, state.Position.X, -state.Position.Y, -state.Position.Z * 0.5f); if (this.isFirstUpdate || this.lastState.Velocity != state.Velocity) AL.Source(handle, ALSource3f.Velocity, state.Velocity.X, -state.Velocity.Y, -state.Velocity.Z); if (this.isFirstUpdate || this.lastState.MaxDistance != state.MaxDistance) AL.Source(handle, ALSourcef.MaxDistance, state.MaxDistance); if (this.isFirstUpdate || this.lastState.MinDistance != state.MinDistance) AL.Source(handle, ALSourcef.ReferenceDistance, state.MinDistance); if (this.isFirstUpdate || this.lastState.Looped != looped) AL.Source(handle, ALSourceb.Looping, looped); if (this.isFirstUpdate || this.lastState.Volume != state.Volume) AL.Source(handle, ALSourcef.Gain, state.Volume); if (this.isFirstUpdate || this.lastState.Pitch != state.Pitch) AL.Source(handle, ALSourcef.Pitch, state.Pitch); // Update lowpass settings requires Effects extension if (this.isFirstUpdate || this.lastState.Lowpass != state.Lowpass) { var fx = AudioBackend.ActiveInstance.EffectsExtension; if (fx != null) { // If there is no filter, create one when required. if (this.filterHandle == 0 && state.Lowpass < 1.0f) { this.filterHandle = fx.GenFilter(); fx.Filter(this.filterHandle, EfxFilteri.FilterType, (int)EfxFilterType.Lowpass); fx.Filter(this.filterHandle, EfxFilterf.LowpassGain, 1); } // If there is a filter, keep it up-to-date if (this.filterHandle != 0) { fx.Filter(this.filterHandle, EfxFilterf.LowpassGainHF, MathF.Clamp(state.Lowpass, 0.0f, 1.0f)); fx.BindFilterToSource(this.handle, this.filterHandle); } } } if (state.Paused && nativeState == ALSourceState.Playing) AL.SourcePause(handle); else if (!state.Paused && nativeState == ALSourceState.Paused) AL.SourcePlay(handle); this.lastState = state; this.lastState.Looped = looped; this.isFirstUpdate = false; } }
void INativeAudioSource.ApplyState(ref AudioSourceState state) { this.finished = true; }
void INativeAudioSource.ApplyState(ref AudioSourceState state) { lock (this.strLock) { ALSourceState nativeState = AL.GetSourceState(this.handle); bool looped = state.Looped && !this.isStreamed; if (this.isFirstUpdate || this.lastState.RelativeToListener != state.RelativeToListener) AL.Source(handle, ALSourceb.SourceRelative, state.RelativeToListener); if (this.isFirstUpdate || this.lastState.Position != state.Position) AL.Source(handle, ALSource3f.Position, state.Position.X, -state.Position.Y, -state.Position.Z * 0.5f); if (this.isFirstUpdate || this.lastState.Velocity != state.Velocity) AL.Source(handle, ALSource3f.Velocity, state.Velocity.X, -state.Velocity.Y, -state.Velocity.Z); if (this.isFirstUpdate || this.lastState.MaxDistance != state.MaxDistance) AL.Source(handle, ALSourcef.MaxDistance, state.MaxDistance); if (this.isFirstUpdate || this.lastState.MinDistance != state.MinDistance) AL.Source(handle, ALSourcef.ReferenceDistance, state.MinDistance); if (this.isFirstUpdate || this.lastState.Looped != looped) AL.Source(handle, ALSourceb.Looping, looped); if (this.isFirstUpdate || this.lastState.Volume != state.Volume) AL.Source(handle, ALSourcef.Gain, state.Volume); if (this.isFirstUpdate || this.lastState.Pitch != state.Pitch) AL.Source(handle, ALSourcef.Pitch, state.Pitch); if (state.Paused && nativeState == ALSourceState.Playing) AL.SourcePause(handle); else if (!state.Paused && nativeState == ALSourceState.Paused) AL.SourcePlay(handle); this.lastState = state; this.lastState.Looped = looped; this.isFirstUpdate = false; } }
/// <summary> /// Updates the SoundInstance /// </summary> public void Update() { // Check existence of attachTo object if (this.attachedTo != null && this.attachedTo.Disposed) { this.attachedTo = null; } // Retrieve sound resource values Sound soundRes = this.sound.Res; AudioData audioDataRes = this.audioData.Res; if (soundRes == null || audioDataRes == null) { this.Dispose(); return; } // Set up local variables for state calculation Vector3 listenerPos = DualityApp.Sound.ListenerPos; bool attachedToListener = this.attachedTo != null && ((this.attachedTo == DualityApp.Sound.Listener) || this.attachedTo.IsChildOf(DualityApp.Sound.Listener)); float optVolFactor = this.GetTypeVolFactor(); float priorityTemp = 1000.0f; AudioSourceState nativeState = AudioSourceState.Default; nativeState.MinDistance = soundRes.MinDist; nativeState.MaxDistance = soundRes.MaxDist; nativeState.Volume = optVolFactor * soundRes.VolumeFactor * this.vol * this.curFade * this.pauseFade; nativeState.Pitch = soundRes.PitchFactor * this.pitch; nativeState.Lowpass = soundRes.LowpassFactor * this.lowpass; priorityTemp *= nativeState.Volume; // Calculate 3D source values, distance and priority nativeState.Position = this.pos; nativeState.Velocity = this.vel; if (this.is3D) { Components.Transform attachTransform = this.attachedTo != null ? this.attachedTo.Transform : null; // Attach to object if (this.attachedTo != null) { MathF.TransformCoord(ref nativeState.Position.X, ref nativeState.Position.Y, attachTransform.Angle); MathF.TransformCoord(ref nativeState.Velocity.X, ref nativeState.Velocity.Y, attachTransform.Angle); nativeState.Position += attachTransform.Pos; nativeState.Velocity += attachTransform.Vel; } // Distance check float dist = MathF.Sqrt( (nativeState.Position.X - listenerPos.X) * (nativeState.Position.X - listenerPos.X) + (nativeState.Position.Y - listenerPos.Y) * (nativeState.Position.Y - listenerPos.Y) + (nativeState.Position.Z - listenerPos.Z) * (nativeState.Position.Z - listenerPos.Z) * 0.25f); if (dist > nativeState.MaxDistance) { this.Dispose(); return; } else { priorityTemp *= Math.Max(0.0f, 1.0f - (dist - nativeState.MinDistance) / (nativeState.MaxDistance - nativeState.MinDistance)); } } if (this.notYetAssigned) { // Grab a native audio source if (this.GrabNativeSource()) { this.RegisterPlaying(); } // If there is none available, just stop right there. else { this.Dispose(); return; } } // If the source is stopped / finished, dispose and return if (this.native == null || this.native.IsFinished) { this.Dispose(); return; } // Fading in and out bool fadeOut = this.fadeTarget <= 0.0f; if (!this.paused) { if (this.fadeTarget != this.curFade) { float fadeTemp = Time.TimeMult * Time.SPFMult / Math.Max(0.05f, this.fadeTimeSec); if (this.fadeTarget > this.curFade) { this.curFade += fadeTemp; } else { this.curFade -= fadeTemp; } if (Math.Abs(this.curFade - this.fadeTarget) < fadeTemp * 2.0f) { this.curFade = this.fadeTarget; } } } // Special paused-fading if (this.paused && this.pauseFade > 0.0f) { this.pauseFade = MathF.Max(0.0f, this.pauseFade - Time.TimeMult * Time.SPFMult * 5.0f); } else if (!this.paused && this.pauseFade < 1.0f) { this.pauseFade = MathF.Min(1.0f, this.pauseFade + Time.TimeMult * Time.SPFMult * 5.0f); } // Apply the sounds state to its internal native audio source if (this.native != null) { if (this.is3D) { nativeState.RelativeToListener = attachedToListener; if (attachedToListener) { nativeState.Position -= listenerPos; } } else { nativeState.RelativeToListener = true; nativeState.Position = new Vector3(this.panning, 0.0f, 0.0f); nativeState.Velocity = Vector3.Zero; } nativeState.Looped = this.looped; nativeState.Paused = this.paused && this.pauseFade == 0.0f; this.native.ApplyState(ref nativeState); } // Update play time if (!this.paused) { this.playTime += MathF.Max(0.5f, nativeState.Pitch) * Time.TimeMult * Time.SPFMult; if (this.sound.Res.FadeOutAt > 0.0f && this.playTime >= this.sound.Res.FadeOutAt) { this.FadeOut(this.sound.Res.FadeOutTime); } } // Finish priority calculation this.curPriority = (int)Math.Round(priorityTemp / Math.Sqrt(DualityApp.Sound.GetNumPlaying(this.sound))); // Initially play the source if (this.native.IsInitial && !this.paused) { if (audioDataRes.IsStreamed) { this.native.Play(this); } else if (audioDataRes.Native != null) { this.native.Play(audioDataRes.Native); } } // Remove faded out sources if (fadeOut && nativeState.Volume <= 0.0f) { this.fadeWaitEnd += Time.TimeMult * Time.MsPFMult; // After fading out entirely, wait 50 ms before actually stopping the source to prevent unpleasant audio tick / glitch noises if (this.fadeWaitEnd > 50.0f) { this.Dispose(); return; } } else { this.fadeWaitEnd = 0.0f; } }