|
| 1 | +using RocketSoundEnhancement.AudioFilters; |
| 2 | +using RocketSoundEnhancement.Unity; |
| 3 | +using System; |
| 4 | +using System.Collections.Generic; |
| 5 | +using System.IO; |
| 6 | +using System.Linq; |
| 7 | +using System.Text; |
| 8 | +using System.Threading.Tasks; |
| 9 | +using UnityEngine; |
| 10 | + |
| 11 | +namespace RocketSoundEnhancement.EffectBehaviours |
| 12 | +{ |
| 13 | + [EffectDefinition("RSE_AUDIO_LOOP")] |
| 14 | + public class RSE_AudioEffectsLoop : RSE_AudioEffects |
| 15 | + { |
| 16 | + public override void OnLoad(ConfigNode node) |
| 17 | + { |
| 18 | + loop = true; |
| 19 | + base.OnLoad(node); |
| 20 | + } |
| 21 | + } |
| 22 | + |
| 23 | + [EffectDefinition("RSE_AUDIO")] |
| 24 | + public class RSE_AudioEffects : EffectBehaviour |
| 25 | + { |
| 26 | + [Persistent] public AudioFX.AudioChannel channel; |
| 27 | + [Persistent] public string clip = ""; |
| 28 | + [Persistent] public bool loop; |
| 29 | + [Persistent] public float spread; |
| 30 | + |
| 31 | + [Persistent] public bool EnableCombFilter = false; |
| 32 | + [Persistent] public bool EnableLowpassFilter = false; |
| 33 | + [Persistent] public bool EnableWaveShaperFilter = false; |
| 34 | + [Persistent] public float DopplerFactor = 0.5f; |
| 35 | + [Persistent] public AirSimulationUpdate AirSimUpdateMode = AirSimulationUpdate.Full; |
| 36 | + [Persistent] public float FarLowpass = 2500; |
| 37 | + [Persistent] public float AngleHighpass = 0; |
| 38 | + [Persistent] public float MaxCombDelay = 20; |
| 39 | + [Persistent] public float MaxCombMix = 0.25f; |
| 40 | + [Persistent] public float MaxDistortion = 0.5f; |
| 41 | + |
| 42 | + public FXCurve volume = new FXCurve("volume", 1f); |
| 43 | + public FXCurve pitch = new FXCurve("pitch", 1f); |
| 44 | + |
| 45 | + public System.Random random = new System.Random(); |
| 46 | + public GameObject audioParent; |
| 47 | + public AudioSource audioSource; |
| 48 | + public AirSimulationFilter airSimFilter; |
| 49 | + public AudioClip audioClip; |
| 50 | + |
| 51 | + bool isActiveVessel; |
| 52 | + bool markForPlay; |
| 53 | + bool playOneShot; |
| 54 | + int slowUpdate; |
| 55 | + float control; |
| 56 | + float distance; |
| 57 | + float lastDistance; |
| 58 | + float doppler = 1; |
| 59 | + float angle = 0; |
| 60 | + float machPass = 1; |
| 61 | + float mach = 0; |
| 62 | + float machAngle = 0; |
| 63 | + |
| 64 | + public override void OnInitialize() |
| 65 | + { |
| 66 | + audioParent = hostPart != null ? AudioUtility.CreateAudioParent(hostPart, hostPart.name) : this.gameObject; |
| 67 | + |
| 68 | + audioClip = GameDatabase.Instance.GetAudioClip(clip); |
| 69 | + while (audioClip == null) |
| 70 | + { |
| 71 | + clip = Path.ChangeExtension(clip, null); |
| 72 | + audioClip = GameDatabase.Instance.GetAudioClip(clip); |
| 73 | + if (audioClip == null) |
| 74 | + { |
| 75 | + Debug.Log($"[RSE]: RSE_AUDIO: {clip} clip cannot be found"); |
| 76 | + break; |
| 77 | + } |
| 78 | + } |
| 79 | + |
| 80 | + audioSource = AudioUtility.CreateSource(audioParent, volume, pitch, loop, spread); |
| 81 | + audioSource.enabled = false; |
| 82 | + audioSource.clip = audioClip; |
| 83 | + |
| 84 | + if (hostPart != null && (EnableCombFilter || EnableLowpassFilter || EnableWaveShaperFilter)) |
| 85 | + { |
| 86 | + airSimFilter = audioParent.AddComponent<AirSimulationFilter>(); |
| 87 | + airSimFilter.enabled = false; |
| 88 | + |
| 89 | + airSimFilter.EnableCombFilter = EnableCombFilter; |
| 90 | + airSimFilter.EnableLowpassFilter = EnableLowpassFilter; |
| 91 | + airSimFilter.EnableWaveShaperFilter = EnableWaveShaperFilter; |
| 92 | + airSimFilter.SimulationUpdate = hostPart != null ? AirSimUpdateMode : AirSimulationUpdate.Basic; |
| 93 | + airSimFilter.FarLowpass = FarLowpass; |
| 94 | + airSimFilter.AngleHighPass = AngleHighpass; |
| 95 | + airSimFilter.MaxCombDelay = MaxCombDelay; |
| 96 | + airSimFilter.MaxCombMix = MaxCombMix; |
| 97 | + airSimFilter.MaxDistortion = MaxDistortion; |
| 98 | + } |
| 99 | + |
| 100 | + GameEvents.onGamePause.Add(OnGamePaused); |
| 101 | + GameEvents.onGameUnpause.Add(OnGameUnpaused); |
| 102 | + } |
| 103 | + |
| 104 | + public override void OnLoad(ConfigNode node) |
| 105 | + { |
| 106 | + ConfigNode.LoadObjectFromConfig(this, node); |
| 107 | + volume.Load("volume", node); |
| 108 | + pitch.Load("pitch", node); |
| 109 | + } |
| 110 | + |
| 111 | + public override void OnEvent() |
| 112 | + { |
| 113 | + Play(1); |
| 114 | + playOneShot = true; |
| 115 | + } |
| 116 | + |
| 117 | + public override void OnEvent(float power) |
| 118 | + { |
| 119 | + Play(power); |
| 120 | + } |
| 121 | + |
| 122 | + public void Play(float power) |
| 123 | + { |
| 124 | + markForPlay = true; |
| 125 | + control = power; |
| 126 | + } |
| 127 | + |
| 128 | + public virtual void LateUpdate() |
| 129 | + { |
| 130 | + if (audioSource == null || audioClip == null || !HighLogic.LoadedSceneIsFlight) return; |
| 131 | + |
| 132 | + isActiveVessel = hostPart != null && hostPart.vessel == FlightGlobals.ActiveVessel; |
| 133 | + |
| 134 | + if (markForPlay) |
| 135 | + { |
| 136 | + float finalVolume = volume.Value(control); |
| 137 | + |
| 138 | + if (finalVolume < float.Epsilon) |
| 139 | + { |
| 140 | + if (audioSource.volume == 0 && loop) |
| 141 | + audioSource.Stop(); |
| 142 | + |
| 143 | + if (audioSource.isPlaying && loop) |
| 144 | + audioSource.volume = 0; |
| 145 | + |
| 146 | + goto end; |
| 147 | + } |
| 148 | + |
| 149 | + if (Settings.MufflerQuality > AudioMufflerQuality.Normal) |
| 150 | + { |
| 151 | + if (airSimFilter != null && Settings.MufflerQuality == AudioMufflerQuality.AirSim) |
| 152 | + { |
| 153 | + airSimFilter.enabled = true; |
| 154 | + airSimFilter.Distance = distance; |
| 155 | + airSimFilter.Mach = mach; |
| 156 | + airSimFilter.Angle = angle; |
| 157 | + airSimFilter.MachAngle = machAngle; |
| 158 | + airSimFilter.MachPass = machPass; |
| 159 | + } |
| 160 | + else |
| 161 | + { |
| 162 | + finalVolume *= Mathf.Log(Mathf.Lerp(1, 10, machPass), 10); |
| 163 | + } |
| 164 | + } |
| 165 | + |
| 166 | + AudioFX.SetSourceVolume(audioSource, finalVolume, channel); |
| 167 | + audioSource.pitch = pitch.Value(control) * (loop ? doppler : 1); |
| 168 | + audioSource.outputAudioMixerGroup = AudioUtility.GetMixerGroup(FXChannel.Exterior, isActiveVessel); |
| 169 | + |
| 170 | + audioSource.enabled = true; |
| 171 | + if (!audioSource.isPlaying && loop) |
| 172 | + { |
| 173 | + if (audioSource.clip == null) audioSource.clip = audioClip; |
| 174 | + |
| 175 | + audioSource.time = audioClip.length * (float)random.NextDouble(); |
| 176 | + audioSource.Play(); |
| 177 | + } |
| 178 | + |
| 179 | + if (playOneShot) |
| 180 | + { |
| 181 | + audioSource.PlayOneShot(audioClip); |
| 182 | + playOneShot = false; |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + end: |
| 187 | + |
| 188 | + if (airSimFilter != null && airSimFilter.enabled && Settings.MufflerQuality != AudioMufflerQuality.AirSim) |
| 189 | + airSimFilter.enabled = false; |
| 190 | + |
| 191 | + slowUpdate++; |
| 192 | + if (slowUpdate >= 60) |
| 193 | + { |
| 194 | + slowUpdate = 0; |
| 195 | + if (!audioSource.enabled && airSimFilter != null) |
| 196 | + { |
| 197 | + airSimFilter.enabled = false; |
| 198 | + airSimFilter.Distance = distance; |
| 199 | + airSimFilter.Mach = mach; |
| 200 | + airSimFilter.Angle = angle; |
| 201 | + airSimFilter.MachAngle = machAngle; |
| 202 | + airSimFilter.MachPass = machPass; |
| 203 | + } |
| 204 | + |
| 205 | + if (audioSource.isPlaying || !audioSource.enabled) return; |
| 206 | + |
| 207 | + audioSource.enabled = false; |
| 208 | + markForPlay = false; |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + public void FixedUpdate() |
| 213 | + { |
| 214 | + if (Settings.EnableAudioEffects && HighLogic.LoadedSceneIsFlight) |
| 215 | + { |
| 216 | + distance = Vector3.Distance(CameraManager.GetCurrentCamera().transform.position, transform.position); |
| 217 | + var relativeSpeed = (lastDistance - distance) / TimeWarp.fixedDeltaTime; |
| 218 | + lastDistance = distance; |
| 219 | + |
| 220 | + if (hostPart == null) return; |
| 221 | + |
| 222 | + float speedOfSound = hostPart.vessel.speedOfSound > 0 ? (float)hostPart.vessel.speedOfSound : 340.29f; |
| 223 | + float dopplerRaw = Mathf.Clamp((speedOfSound + ((relativeSpeed) * DopplerFactor)) / speedOfSound, 1 - (DopplerFactor * 0.5f), 1 + DopplerFactor); |
| 224 | + doppler = Mathf.MoveTowards(doppler, dopplerRaw, 0.5f * TimeWarp.fixedDeltaTime); |
| 225 | + |
| 226 | + angle = (1 + Vector3.Dot(hostPart.vessel.GetComponent<ShipEffects>().MachTipCameraNormal, (transform.up + hostPart.vessel.velocityD).normalized)) * 90; |
| 227 | + machPass = 1f - Mathf.Clamp01(angle / hostPart.vessel.GetComponent<ShipEffects>().MachAngle) * Mathf.Clamp01(hostPart.vessel.GetComponent<ShipEffects>().Mach); |
| 228 | + |
| 229 | + if (hostPart.vessel.isActiveVessel && (InternalCamera.Instance.isActive || MapView.MapCamera.isActiveAndEnabled)) |
| 230 | + { |
| 231 | + angle = 0; |
| 232 | + machPass = 1; |
| 233 | + } |
| 234 | + |
| 235 | + mach = hostPart.vessel.GetComponent<ShipEffects>().Mach; |
| 236 | + machAngle = hostPart.vessel.GetComponent<ShipEffects>().MachAngle; |
| 237 | + } |
| 238 | + } |
| 239 | + |
| 240 | + public void OnGamePaused() |
| 241 | + { |
| 242 | + if (audioSource == null) return; |
| 243 | + audioSource.Pause(); |
| 244 | + } |
| 245 | + |
| 246 | + public void OnGameUnpaused() |
| 247 | + { |
| 248 | + if (audioSource == null) return; |
| 249 | + audioSource.UnPause(); |
| 250 | + } |
| 251 | + |
| 252 | + public void OnDestroy() |
| 253 | + { |
| 254 | + GameEvents.onGamePause.Remove(OnGamePaused); |
| 255 | + GameEvents.onGameUnpause.Remove(OnGameUnpaused); |
| 256 | + } |
| 257 | + } |
| 258 | +} |
0 commit comments