float MaxSupersonicFreq; // Hz public void Awake() { // Defaults for Configurable parameters. LowerMachThreshold = 0.80f; UpperMachThreshold = 1.20f; MaxDistortion = 0.95f; InteriorVolumeScale = 0.7f; InteriorMaxFreq = 300f; CondensationEffectStrength = 0.5f; MaxVacuumFreq = 0; // 150 MaxSupersonicFreq = 0; // 300 LoadConfig(); // TODO: // Option for microphone fixed to craft. // Options for shockwave reverb/distortion levels. // Option for maintaining low-pass sound in vacuum. // Initialise dynamic variables. CurrentState = Soundscape.Unknown; LastState = Soundscape.Unknown; AudioPanels = new List <ASEFilterPanel>(); LastVesselPartCount = 0; Density = 0; MachNumber = 0; MachAngle = 0; CameraAngle = 0; ShockwaveEffectStrength = 1f; NegativeSlopeWidthDeg = 24f; InteriorVolume = GameSettings.SHIP_VOLUME * InteriorVolumeScale; MaxShipVolume = GameSettings.SHIP_VOLUME; GetAeroFX(); }
public void OnPause() { Paused = true; CurrentState = Soundscape.Unknown; foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.all, -1); } }
private void NormalFlight() { CurrentState = Soundscape.NormalFlight; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Normal Atmospheric Flight"); } foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, -1); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
/// <summary> /// Inside the shock cone. /// </summary> private void AfterShockwave() { CurrentState = Soundscape.AfterShockwave; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to After Shock"); } foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion, -1f); aPanel.SetKnobs(Knobs.reverb, 0.15f); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
// Procedure methods to simplify Update() readability. #region Audio updates private void Interior() { CurrentState = Soundscape.Interior; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Interior"); foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.lowpass, InteriorMaxFreq); aPanel.SetKnobs(Knobs.volume, InteriorVolume); aPanel.SetKnobs(Knobs.distortion, -1); aPanel.SetKnobs(Knobs.reverb, 0.05f); } } }
/// <summary> /// The trailing edge of the shockwave, closer to the inside of the shock cone. /// </summary> /// <param name="negativeSlopeEdgeDeg"></param> private void NegativeSlope(float negativeSlopeEdgeDeg) { CurrentState = Soundscape.NegativeSlope; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Falling Edge"); } float dynEffect = ((CameraAngle - negativeSlopeEdgeDeg) / NegativeSlopeWidthDeg) * ShockwaveEffectStrength * MaxDistortion; foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, dynEffect); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
/// <summary> /// Undisturbed air in front of the craft. /// </summary> private void BeforeShockwave() { CurrentState = Soundscape.BeforeShockwave; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Before Shock"); } if (MaxSupersonicFreq < MinLowPassFreq) { // Silent ahead of the shockwave. float volume = MaxShipVolume * (1f - ShockwaveEffectStrength); foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, volume); } if (CurrentState != LastState) { foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.lowpass | Knobs.reverb | Knobs.distortion, -1);//effects off } } } else { // Low frequency ahead of the shockwave. foreach (ASEFilterPanel aPanel in AudioPanels) { if (CurrentState != LastState) { aPanel.SetKnobs(Knobs.reverb | Knobs.distortion, -1); aPanel.SetKnobs(Knobs.volume, MaxShipVolume); } float supersonicFreq = Mathf.Lerp(MaxSupersonicFreq, MaxLowPassFreq, 1f - ShockwaveEffectStrength); float atmoFreq = GetAtmosphericAttenuation(); if (atmoFreq > 0) { aPanel.SetKnobs(Knobs.lowpass, Math.Min(atmoFreq, supersonicFreq)); } else { aPanel.SetKnobs(Knobs.lowpass, supersonicFreq); } } } }
/// <summary> /// The leading edge of the shockwave: Translates to the first air the ear meets. /// </summary> /// <param name="positiveSlopeEdgeDeg"></param> /// <param name="positiveSlopeWidthDeg"></param> private void PositiveSlope(float positiveSlopeEdgeDeg, float positiveSlopeWidthDeg) { CurrentState = Soundscape.PositiveSlope; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Rising Edge"); } float volume = Mathf.Lerp((1f - ShockwaveEffectStrength), 1f, (positiveSlopeEdgeDeg - CameraAngle) / positiveSlopeWidthDeg); float dynEffect = (positiveSlopeEdgeDeg - CameraAngle) / positiveSlopeWidthDeg * ShockwaveEffectStrength * MaxDistortion; foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, volume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, dynEffect); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
//Returns a random audiostream from the given soundscape, if there is no soundscape specific sound it will return a //sound from the any soundscape, if there isn't one there it will return null public AudioStream Get(Soundscape ss) { AudioStream[] possibleStreams; //Look for soundscape specific streams if (this.streams.TryGetValue(ss, out possibleStreams)) { return(Command.Random(possibleStreams)); } //Look for generic streams if (this.streams.TryGetValue(Soundscape.ANY, out possibleStreams)) { return(Command.Random(possibleStreams)); } //No streams available return(null); }
private void Vacuum() { CurrentState = Soundscape.Vacuum; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Vacuum"); if (MaxVacuumFreq < MinLowPassFreq)// Vacuum is set to silent. { foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume | Knobs.lowpass | Knobs.reverb | Knobs.distortion, -1); } } else// Vacuum is set to quiet. { foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.lowpass, MaxVacuumFreq); aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, -1); } } } }
public void OnPause() { Paused = true; CurrentState = Soundscape.Unknown; foreach (ASEFilterPanel aPanel in AudioPanels) aPanel.SetKnobs(Knobs.all, -1); }
/// <summary> /// Inside the shock cone. /// </summary> private void AfterShockwave() { CurrentState = Soundscape.AfterShockwave; if (CurrentState != LastState) Debug.Log("ASE -- Switching to After Shock"); foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion, -1f); aPanel.SetKnobs(Knobs.reverb, 0.15f); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
/// <summary> /// Undisturbed air in front of the craft. /// </summary> private void BeforeShockwave() { CurrentState = Soundscape.BeforeShockwave; if (CurrentState != LastState) Debug.Log("ASE -- Switching to Before Shock"); if (MaxSupersonicFreq < MinLowPassFreq) { // Silent ahead of the shockwave. float volume = MaxShipVolume * (1f - ShockwaveEffectStrength); foreach (ASEFilterPanel aPanel in AudioPanels) aPanel.SetKnobs(Knobs.volume, volume); if (CurrentState != LastState) foreach (ASEFilterPanel aPanel in AudioPanels) aPanel.SetKnobs(Knobs.lowpass | Knobs.reverb | Knobs.distortion, -1);//effects off } else { // Low frequency ahead of the shockwave. foreach (ASEFilterPanel aPanel in AudioPanels) { if (CurrentState != LastState) { aPanel.SetKnobs(Knobs.reverb | Knobs.distortion, -1); aPanel.SetKnobs(Knobs.volume, MaxShipVolume); } float supersonicFreq = Mathf.Lerp(MaxSupersonicFreq, MaxLowPassFreq, 1f - ShockwaveEffectStrength); float atmoFreq = GetAtmosphericAttenuation(); if (atmoFreq > 0) aPanel.SetKnobs(Knobs.lowpass, Math.Min(atmoFreq, supersonicFreq)); else aPanel.SetKnobs(Knobs.lowpass, supersonicFreq); } } }
private void Interior() { CurrentState = Soundscape.Interior; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Interior"); foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.lowpass, InteriorMaxFreq); aPanel.SetKnobs(Knobs.volume, InteriorVolume); aPanel.SetKnobs(Knobs.distortion, -1); aPanel.SetKnobs(Knobs.reverb, 0.05f); } } }
/// <summary> /// The trailing edge of the shockwave, closer to the inside of the shock cone. /// </summary> /// <param name="negativeSlopeEdgeDeg"></param> private void NegativeSlope(float negativeSlopeEdgeDeg) { CurrentState = Soundscape.NegativeSlope; if (CurrentState != LastState) Debug.Log("ASE -- Switching to Falling Edge"); float dynEffect = ((CameraAngle - negativeSlopeEdgeDeg) / NegativeSlopeWidthDeg) * ShockwaveEffectStrength * MaxDistortion; foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, dynEffect); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
private void NormalFlight() { CurrentState = Soundscape.NormalFlight; if (CurrentState != LastState) Debug.Log("ASE -- Switching to Normal Atmospheric Flight"); foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, -1); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
/// <summary> /// The leading edge of the shockwave: Translates to the first air the ear meets. /// </summary> /// <param name="positiveSlopeEdgeDeg"></param> /// <param name="positiveSlopeWidthDeg"></param> private void PositiveSlope(float positiveSlopeEdgeDeg, float positiveSlopeWidthDeg) { CurrentState = Soundscape.PositiveSlope; if (CurrentState != LastState) Debug.Log("ASE -- Switching to Rising Edge"); float volume = Mathf.Lerp((1f - ShockwaveEffectStrength), 1f, (positiveSlopeEdgeDeg - CameraAngle) / positiveSlopeWidthDeg); float dynEffect = (positiveSlopeEdgeDeg - CameraAngle) / positiveSlopeWidthDeg * ShockwaveEffectStrength * MaxDistortion; foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.volume, volume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, dynEffect); aPanel.SetKnobs(Knobs.lowpass, GetAtmosphericAttenuation()); } }
private void Vacuum() { CurrentState = Soundscape.Vacuum; if (CurrentState != LastState) { Debug.Log("ASE -- Switching to Vacuum"); if (MaxVacuumFreq < MinLowPassFreq)// Vacuum is set to silent. foreach (ASEFilterPanel aPanel in AudioPanels) aPanel.SetKnobs(Knobs.volume | Knobs.lowpass | Knobs.reverb | Knobs.distortion, -1); else// Vacuum is set to quiet. foreach (ASEFilterPanel aPanel in AudioPanels) { aPanel.SetKnobs(Knobs.lowpass, MaxVacuumFreq); aPanel.SetKnobs(Knobs.volume, MaxShipVolume); aPanel.SetKnobs(Knobs.distortion | Knobs.reverb, -1); } } }
/// <summary> /// Called once per frame. /// </summary> public void Update() { if (Paused) { return; } UpdateAeroFX(); UpdateAudioSources(); if (AudioPanels.Count() == 0) { return; } LastState = CurrentState; if (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Map) { Interior(); } else { Density = (float)AtmoDataProvider.Get().GetDensity(); if (Density <= 0) { Vacuum(); } else { //volume = MaxShipVolume; MachNumber = AtmoDataProvider.Get().GetMach(); if (MachNumber >= LowerMachThreshold)//transonic { MachAngle = 90f; if (MachNumber >= 1f) { MachAngle = Mathf.Rad2Deg * (float)Math.Asin(1f / MachNumber); ShockwaveEffectStrength = 1f; } else { ShockwaveEffectStrength = (MachNumber - LowerMachThreshold) / (1f - LowerMachThreshold); } NegativeSlopeWidthDeg = 5f + (15f / MachNumber); float negativeSlopeEdgeDeg = MachAngle - NegativeSlopeWidthDeg; float positiveSlopeWidthDeg = NegativeSlopeWidthDeg * (1f - ShockwaveEffectStrength); float positiveSlopeEdgeDeg = Mathf.Max(0f, MachAngle + positiveSlopeWidthDeg); CameraAngle = Vector3.Angle (FlightGlobals.ActiveVessel.GetSrfVelocity().normalized , (FlightGlobals.ActiveVessel.transform.position - FlightCamera.fetch.transform.position).normalized ); if (CameraAngle >= negativeSlopeEdgeDeg && CameraAngle <= positiveSlopeEdgeDeg)//at shockwave { if (CameraAngle > MachAngle) { PositiveSlope(positiveSlopeEdgeDeg, positiveSlopeWidthDeg); } else { NegativeSlope(negativeSlopeEdgeDeg); } } else if (CameraAngle > positiveSlopeEdgeDeg) { BeforeShockwave(); } else if (CameraAngle < negativeSlopeEdgeDeg) { AfterShockwave(); } } else { NormalFlight(); } } //end dense atmospheric conditions } //end external view } // end OnUpdate
/// <summary> /// Called once per frame. /// </summary> public void Update() { if(Paused) return; UpdateAeroFX(); UpdateAudioSources(); if (AudioPanels.Count() == 0) return; LastState = CurrentState; if(CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Internal || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA || CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.Map) Interior(); else { Density = (float)AtmoDataProvider.Get().GetDensity(); if (Density <= 0) Vacuum(); else { //volume = MaxShipVolume; MachNumber = AtmoDataProvider.Get().GetMach(); if (MachNumber >= LowerMachThreshold)//transonic { MachAngle = 90f; if (MachNumber >= 1f) { MachAngle = Mathf.Rad2Deg * (float)Math.Asin(1f / MachNumber); ShockwaveEffectStrength = 1f; } else ShockwaveEffectStrength = (MachNumber - LowerMachThreshold) / (1f - LowerMachThreshold); NegativeSlopeWidthDeg = 5f + (15f / MachNumber); float negativeSlopeEdgeDeg = MachAngle - NegativeSlopeWidthDeg; float positiveSlopeWidthDeg = NegativeSlopeWidthDeg * (1f - ShockwaveEffectStrength); float positiveSlopeEdgeDeg = Mathf.Max(0f, MachAngle + positiveSlopeWidthDeg); CameraAngle = Vector3.Angle (FlightGlobals.ActiveVessel.GetSrfVelocity().normalized , (FlightGlobals.ActiveVessel.transform.position - FlightCamera.fetch.transform.position).normalized ); if (CameraAngle >= negativeSlopeEdgeDeg && CameraAngle <= positiveSlopeEdgeDeg)//at shockwave if (CameraAngle > MachAngle) PositiveSlope(positiveSlopeEdgeDeg, positiveSlopeWidthDeg); else NegativeSlope(negativeSlopeEdgeDeg); else if (CameraAngle > positiveSlopeEdgeDeg) BeforeShockwave(); else if (CameraAngle < negativeSlopeEdgeDeg) AfterShockwave(); } else NormalFlight(); } //end dense atmospheric conditions }//end external view }
public void Awake() { // Defaults for Configurable parameters. LowerMachThreshold = 0.80f; UpperMachThreshold = 1.20f; MaxDistortion = 0.95f; InteriorVolumeScale = 0.7f; InteriorMaxFreq = 300f; CondensationEffectStrength = 0.5f; MaxVacuumFreq = 0; // 150 MaxSupersonicFreq = 0; // 300 LoadConfig(); // TODO: // Option for microphone fixed to craft. // Options for shockwave reverb/distortion levels. // Option for maintaining low-pass sound in vacuum. // Initialise dynamic variables. CurrentState = Soundscape.Unknown; LastState = Soundscape.Unknown; AudioPanels = new List<ASEFilterPanel>(); LastVesselPartCount = 0; Density = 0; MachNumber = 0; MachAngle = 0; CameraAngle = 0; ShockwaveEffectStrength = 1f; NegativeSlopeWidthDeg = 24f; InteriorVolume = GameSettings.SHIP_VOLUME * InteriorVolumeScale; MaxShipVolume = GameSettings.SHIP_VOLUME; GetAeroFX(); }