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());
            }
        }
示例#9
0
        //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();
        }