GetAirTemperature() static private method

static private GetAirTemperature ( double Elevation ) : double
Elevation double
return double
示例#1
0
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        private static void UpdateLinearModel(double timeElapsed)
        {
            /*
             * Set up the listener
             * */
            OpenBveApi.Math.Vector3      listenerPosition    = World.AbsoluteCameraPosition;
            OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection);
            OpenBveApi.Math.Vector3      listenerVelocity    = World.CameraAlignmentSpeed.Position;
            AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f);
            AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            var Orientation = new[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z };

            AL.Listener(ALListenerfv.Orientation, ref Orientation);

            /*
             * Set up the atmospheric attributes
             * */
            double elevation      = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation;
            double airTemperature = Game.GetAirTemperature(elevation);
            double airPressure    = Game.GetAirPressure(elevation, airTemperature);
            double speedOfSound   = Game.GetSpeedOfSound(airPressure, airTemperature);

            try
            {
                AL.SpeedOfSound((float)speedOfSound);
            }
            catch { }

            /*
             * Update the sound sources
             * */
            int actuallyPlaying = 0;

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * Calculate the sound gain.
                     * */
                    OpenBveApi.Math.Vector3 position;
                    OpenBveApi.Math.Vector3 velocity;

                    switch (Sources[i].Type)
                    {
                    case SoundType.TrainCar:
                        OpenBveApi.Math.Vector3 direction;
                        Sources[i].Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position, out position, out direction);
                        velocity = Sources[i].Train.Cars[Sources[i].Car].Specs.CurrentSpeed * direction;
                        break;

                    default:
                        position = Sources[i].Position;
                        velocity = OpenBveApi.Math.Vector3.Zero;
                        break;
                    }
                    OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition;
                    double gain;
                    if (GlobalMute)
                    {
                        gain = 0.0;
                    }
                    else
                    {
                        double distance    = positionDifference.Norm();
                        double innerRadius = Sources[i].Radius;
                        if (World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead)
                        {
                            if (Sources[i].Train != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar)
                            {
                                innerRadius *= 0.5;
                            }
                        }
                        double outerRadius = OuterRadiusFactor * innerRadius;
                        if (distance < outerRadius)
                        {
                            if (distance <= innerRadius)
                            {
                                gain = Sources[i].Volume;
                            }
                            else
                            {
                                gain  = (distance - outerRadius) / (innerRadius - outerRadius);
                                gain *= Sources[i].Volume;
                            }
                            gain = 3.0 * gain * gain - 2.0 * gain * gain * gain;
                        }
                        else
                        {
                            gain = 0.0;
                        }
                    }
                    if (gain <= GainThreshold)
                    {
                        /*
                         * If the gain is too low to be audible, stop the sound.
                         * If the sound is not looping, stop it if necessary,
                         * then remove it from the list of sound sources.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Play the sound and update position, velocity, pitch and gain.
                         * For non-looping sounds, check if the sound is still playing.
                         * */
                        gain = (gain - GainThreshold) / (1.0 - GainThreshold);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            LoadBuffer(Sources[i].Buffer);
                            if (Sources[i].Buffer.Loaded)
                            {
                                AL.GenSources(1, out Sources[i].OpenAlSourceName);
                                AL.Source(Sources[i].OpenAlSourceName, ALSourcei.Buffer, Sources[i].Buffer.OpenAlBufferName);
                            }
                            else
                            {
                                /*
                                 * We cannot play the sound because
                                 * the buffer could not be loaded.
                                 * */
                                Sources[i].State = SoundSourceState.Stopped;
                                continue;
                            }
                        }
                        AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Position, (float)positionDifference.X, (float)positionDifference.Y, (float)positionDifference.Z);
                        AL.Source(Sources[i].OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                        AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Pitch, (float)Sources[i].Pitch);
                        AL.Source(Sources[i].OpenAlSourceName, ALSourcef.Gain, (float)gain);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            AL.Source(Sources[i].OpenAlSourceName, ALSourceb.Looping, Sources[i].Looped);
                            AL.SourcePlay(Sources[i].OpenAlSourceName);
                            Sources[i].State = SoundSourceState.Playing;
                        }
                        if (!Sources[i].Looped)
                        {
                            int state;
                            AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state);
                            if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing)
                            {
                                /*
                                 * The sound is not playing any longer.
                                 * Remove it from the list of sound sources.
                                 * */
                                AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                                Sources[i].State            = SoundSourceState.Stopped;
                                Sources[i].OpenAlSourceName = 0;
                                Sources[i] = Sources[SourceCount - 1];
                                SourceCount--;
                                i--;
                            }
                            else
                            {
                                actuallyPlaying++;
                            }
                        }
                        else
                        {
                            actuallyPlaying++;
                        }
                    }
                }
            }

            /*
             * Adjust the outer radius factor / the clamp factor.
             * */
            if (actuallyPlaying >= Interface.CurrentOptions.SoundNumber - 2)
            {
                /*
                 * Too many sounds are playing.
                 * Reduce the outer radius factor.
                 * */
                OuterRadiusFactorSpeed -= timeElapsed;
                if (OuterRadiusFactorSpeed < -OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = -OuterRadiusFactorMaximumSpeed;
                }
            }
            else if (actuallyPlaying <= Interface.CurrentOptions.SoundNumber - 6)
            {
                /*
                 * Only few sounds are playing.
                 * Increase the outer radius factor.
                 * */
                OuterRadiusFactorSpeed += timeElapsed;
                if (OuterRadiusFactorSpeed > OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = OuterRadiusFactorMaximumSpeed;
                }
            }
            else
            {
                /*
                 * Neither too many nor too few sounds are playing.
                 * Stabilize the outer radius factor.
                 * */
                if (OuterRadiusFactorSpeed < 0.0)
                {
                    OuterRadiusFactorSpeed += timeElapsed;
                    if (OuterRadiusFactorSpeed > 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
                else
                {
                    OuterRadiusFactorSpeed -= timeElapsed;
                    if (OuterRadiusFactorSpeed < 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
            }
            OuterRadiusFactor += OuterRadiusFactorSpeed * timeElapsed;
            if (OuterRadiusFactor < OuterRadiusFactorMinimum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMinimum;
                OuterRadiusFactorSpeed = 0.0;
            }
            else if (OuterRadiusFactor > OuterRadiusFactorMaximum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMaximum;
                OuterRadiusFactorSpeed = 0.0;
            }
        }
示例#2
0
 // update
 internal static void Update(double TimeElapsed)
 {
     if (OpenAlContext != ContextHandle.Zero)
     {
         // listener
         double vx = World.CameraTrackFollower.WorldDirection.X * World.CameraSpeed;
         double vy = World.CameraTrackFollower.WorldDirection.Y * World.CameraSpeed;
         double vz = World.CameraTrackFollower.WorldDirection.Z * World.CameraSpeed;
         if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead)
         {
             ListenerVelocity[0] = 0.0f;
             ListenerVelocity[1] = 0.0f;
             ListenerVelocity[2] = 0.0f;
         }
         else
         {
             ListenerVelocity[0] = (float)vx;
             ListenerVelocity[1] = (float)vy;
             ListenerVelocity[2] = (float)vz;
         }
         ListenerOrientation[0] = (float)World.AbsoluteCameraDirection.X;
         ListenerOrientation[1] = (float)World.AbsoluteCameraDirection.Y;
         ListenerOrientation[2] = (float)World.AbsoluteCameraDirection.Z;
         ListenerOrientation[3] = (float)-World.AbsoluteCameraUp.X;
         ListenerOrientation[4] = (float)-World.AbsoluteCameraUp.Y;
         ListenerOrientation[5] = (float)-World.AbsoluteCameraUp.Z;
         AL.Listener(ALListener3f.Position, ListenerPosition[0], ListenerPosition[1], ListenerPosition[2]);
         AL.Listener(ALListener3f.Velocity, ListenerVelocity[0], ListenerVelocity[1], ListenerVelocity[2]);
         AL.Listener(ALListenerfv.Orientation, ref ListenerOrientation);
         double cx = World.AbsoluteCameraPosition.X;
         double cy = World.AbsoluteCameraPosition.Y;
         double cz = World.AbsoluteCameraPosition.Z;
         if (Mute)
         {
             // mute
             for (int i = 0; i < SoundSources.Length; i++)
             {
                 if (SoundSources[i] != null && !SoundSources[i].FinishedPlaying)
                 {
                     if (!SoundSources[i].Suppressed)
                     {
                         if (SoundSources[i].Looped)
                         {
                             if (SoundSources[i].OpenAlSourceIndex.Valid)
                             {
                                 int j = SoundSources[i].OpenAlSourceIndex.Index;
                                 AL.SourceStop(j);
                                 AL.DeleteSources(1, ref j);
                             }
                             SoundSources[i].OpenAlSourceIndex = new OpenAlIndex(0, false);
                             SoundSources[i].Suppressed        = true;
                         }
                         else
                         {
                             StopSound(i, false);
                         }
                     }
                     else if (!SoundSources[i].Looped)
                     {
                         StopSound(i, false);
                     }
                 }
             }
         }
         else
         {
             // outer radius
             int n = Interface.CurrentOptions.SoundNumber - 3;
             if (SoundsActuallyPlaying >= n)
             {
                 OuterRadiusSpeed -= OuterRadiusDeceleration * TimeElapsed;
                 if (OuterRadiusSpeed < -1.0)
                 {
                     OuterRadiusSpeed = -1.0;
                 }
             }
             else if (SoundsQueriedPlaying < n)
             {
                 OuterRadiusSpeed += OuterRadiusAcceleration * TimeElapsed;
                 if (OuterRadiusSpeed > 1.0)
                 {
                     OuterRadiusSpeed = 1.0;
                 }
             }
             else
             {
                 OuterRadiusSpeed -= (double)Math.Sign(OuterRadiusSpeed) * OuterRadiusDeceleration * TimeElapsed;
                 if (OuterRadiusSpeed * OuterRadiusSpeed <= TimeElapsed * TimeElapsed)
                 {
                     OuterRadiusSpeed = 0.0;
                 }
             }
             OuterRadiusFactor += OuterRadiusSpeed * TimeElapsed;
             if (OuterRadiusFactor < OuterRadiusFactorMinimum)
             {
                 OuterRadiusFactor = OuterRadiusFactorMinimum;
             }
             else if (OuterRadiusFactor > OuterRadiusFactorMaximum)
             {
                 OuterRadiusFactor = OuterRadiusFactorMaximum;
             }
             // sources
             SoundsQueriedPlaying  = 0;
             SoundsActuallyPlaying = 0;
             for (int i = 0; i < SoundSources.Length; i++)
             {
                 if (SoundSources[i] != null && !SoundSources[i].FinishedPlaying)
                 {
                     double rx = SoundSources[i].Position.X;
                     double ry = SoundSources[i].Position.Y;
                     double rz = SoundSources[i].Position.Z;
                     double px, py, pz;
                     if (SoundSources[i].Train != null)
                     {
                         int    c = SoundSources[i].CarIndex;
                         double tx, ty, tz;
                         TrainManager.CreateWorldCoordinates(SoundSources[i].Train, c, rx, ry, rz, out px, out py, out pz, out tx, out ty, out tz);
                         px -= cx; py -= cy; pz -= cz;
                         double sp = SoundSources[i].Train.Specs.CurrentAverageSpeed;
                         if (World.CameraMode != World.CameraViewMode.Interior & World.CameraMode != World.CameraViewMode.InteriorLookAhead)
                         {
                             SoundSources[i].OpenAlVelocity[0] = (float)(tx * sp);
                             SoundSources[i].OpenAlVelocity[1] = (float)(ty * sp);
                             SoundSources[i].OpenAlVelocity[2] = (float)(tz * sp);
                         }
                         else
                         {
                             SoundSources[i].OpenAlVelocity[0] = (float)(tx * sp - vx);
                             SoundSources[i].OpenAlVelocity[1] = (float)(ty * sp - vy);
                             SoundSources[i].OpenAlVelocity[2] = (float)(tz * sp - vz);
                         }
                     }
                     else
                     {
                         px = rx - cx; py = ry - cy; pz = rz - cz;
                         if (World.CameraMode != World.CameraViewMode.Interior & World.CameraMode != World.CameraViewMode.InteriorLookAhead)
                         {
                             SoundSources[i].OpenAlVelocity[0] = 0.0f;
                             SoundSources[i].OpenAlVelocity[1] = 0.0f;
                             SoundSources[i].OpenAlVelocity[2] = 0.0f;
                         }
                         else
                         {
                             SoundSources[i].OpenAlVelocity[0] = (float)-vx;
                             SoundSources[i].OpenAlVelocity[1] = (float)-vy;
                             SoundSources[i].OpenAlVelocity[2] = (float)-vz;
                         }
                     }
                     // play the sound only if within the outer radius
                     double distanceSquared    = px * px + py * py + pz * pz;
                     double distance           = Math.Sqrt(distanceSquared);
                     double innerRadius        = SoundSources[i].Radius;
                     double outerRadius        = OuterRadiusFactor * innerRadius;
                     double outerRadiusSquared = outerRadius * outerRadius;
                     if (distanceSquared < outerRadiusSquared)
                     {
                         // sound is in range
                         double       gain;
                         double       innerRadiusSquared = innerRadius * innerRadius;
                         const double rollOffFactor      = 0.9;
                         if (distanceSquared < innerRadiusSquared)
                         {
                             gain = 1.0 - (1.0 - rollOffFactor) * distanceSquared / innerRadiusSquared;
                         }
                         else
                         {
                             double value = distance / outerRadius;
                             gain = innerRadius * rollOffFactor * (1.0 - value * value * value) / distance;
                         }
                         SoundsQueriedPlaying++;
                         SoundsActuallyPlaying++;
                         bool startPlaying = false;
                         // play sound if currently suppressed
                         if (SoundSources[i].Suppressed)
                         {
                             if (SoundSources[i].SoundBufferIndex >= 0)
                             {
                                 UseSoundBuffer(SoundSources[i].SoundBufferIndex);
                                 if (SoundBuffers[SoundSources[i].SoundBufferIndex].OpenAlBufferIndex.Valid)
                                 {
                                     int j;
                                     AL.GetError();
                                     AL.GenSources(1, out j);
                                     ALError err = AL.GetError();
                                     if (err == ALError.NoError)
                                     {
                                         SoundSources[i].OpenAlSourceIndex = new OpenAlIndex(j, true);
                                         AL.Source(j, ALSourcei.Buffer, SoundBuffers[SoundSources[i].SoundBufferIndex].OpenAlBufferIndex.Index);
                                         SoundSources[i].Suppressed = false;
                                         startPlaying = true;
                                     }
                                     else
                                     {
                                         continue;
                                     }
                                 }
                                 else
                                 {
                                     StopSound(i, false);
                                     continue;
                                 }
                             }
                             else
                             {
                                 StopSound(i, false);
                                 continue;
                             }
                         }
                         // play or stop sound
                         if (startPlaying || IsPlaying(i))
                         {
                             SoundSources[i].OpenAlPosition[0] = (float)px;
                             SoundSources[i].OpenAlPosition[1] = (float)py;
                             SoundSources[i].OpenAlPosition[2] = (float)pz;
                             if (!SoundSources[i].OpenAlSourceIndex.Valid)
                             {
                                 throw new InvalidOperationException("A bug in the sound manager. (9431)");
                             }
                             int j = SoundSources[i].OpenAlSourceIndex.Index;
                             AL.Source(j, ALSource3f.Position, SoundSources[i].OpenAlPosition[0], SoundSources[i].OpenAlPosition[1], SoundSources[i].OpenAlPosition[2]);
                             AL.Source(j, ALSource3f.Velocity, SoundSources[i].OpenAlVelocity[0], SoundSources[i].OpenAlVelocity[1], SoundSources[i].OpenAlVelocity[2]);
                             AL.Source(j, ALSourcef.Pitch, SoundSources[i].Pitch);
                             float g = SoundSources[i].Gain * SoundSources[i].Gain * (float)gain;
                             if (g > 1.0f)
                             {
                                 g = 1.0f;
                             }
                             AL.Source(j, ALSourcef.Gain, g);
                         }
                         else
                         {
                             StopSound(i, false);
                             continue;
                         }
                         // update position and velocity of sound
                         if (startPlaying)
                         {
                             if (!SoundSources[i].OpenAlSourceIndex.Valid)
                             {
                                 throw new InvalidOperationException("A bug in the sound manager. (7625)");
                             }
                             int j = SoundSources[i].OpenAlSourceIndex.Index;
                             AL.Source(j, ALSourceb.Looping, SoundSources[i].Looped);
                             AL.Source(j, ALSourcef.ReferenceDistance, SoundBuffers[SoundSources[i].SoundBufferIndex].Radius);
                             AL.SourcePlay(j);
                         }
                     }
                     else
                     {
                         // sound is not in range
                         if (!SoundSources[i].Suppressed)
                         {
                             if (SoundSources[i].Looped)
                             {
                                 if (SoundSources[i].OpenAlSourceIndex.Valid)
                                 {
                                     int j = SoundSources[i].OpenAlSourceIndex.Index;
                                     AL.SourceStop(j);
                                     AL.DeleteSources(1, ref j);
                                 }
                                 SoundSources[i].OpenAlSourceIndex = new OpenAlIndex(0, false);
                                 SoundSources[i].Suppressed        = true;
                             }
                             else
                             {
                                 StopSound(i, false);
                             }
                         }
                         else if (!SoundSources[i].Looped)
                         {
                             StopSound(i, false);
                         }
                     }
                 }
             }
         }
         // infrequent updates
         InternalTimer += TimeElapsed;
         if (InternalTimer > 1.0)
         {
             InternalTimer = 0.0;
             double Elevation      = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation;
             double AirTemperature = Game.GetAirTemperature(Elevation);
             double AirPressure    = Game.GetAirPressure(Elevation, AirTemperature);
             double SpeedOfSound   = Game.GetSpeedOfSound(AirPressure, AirTemperature);
             AL.SpeedOfSound((float)SpeedOfSound);
         }
     }
 }
示例#3
0
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        private static void UpdateInverseModel(double timeElapsed)
        {
            /*
             * Set up the listener.
             * */
            OpenBveApi.Math.Vector3      listenerPosition    = World.AbsoluteCameraPosition;
            OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection);
            OpenBveApi.Math.Vector3      listenerVelocity;
            if (World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead | World.CameraMode == CameraViewMode.Exterior)
            {
                TrainManager.Car        car  = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
                OpenBveApi.Math.Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition;
                if (diff.IsNullVector())
                {
                    listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Forward;
                }
                else
                {
                    listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Normalize(diff);
                }
            }
            else
            {
                listenerVelocity = OpenBveApi.Math.Vector3.Zero;
            }
            AL.Listener(ALListener3f.Position, 0.0f, 0.0f, 0.0f);
            AL.Listener(ALListener3f.Velocity, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            var Orientation = new float[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z };

            AL.Listener(ALListenerfv.Orientation, ref Orientation);

            /*
             * Set up the atmospheric attributes.
             * */
            double elevation      = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation;
            double airTemperature = Game.GetAirTemperature(elevation);
            double airPressure    = Game.GetAirPressure(elevation, airTemperature);
            double speedOfSound   = Game.GetSpeedOfSound(airPressure, airTemperature);

            try
            {
                AL.SpeedOfSound((float)speedOfSound);
            }
            catch { }

            /*
             * Collect all sounds that are to be played
             * and ensure that all others are stopped.
             * */
            List <SoundSourceAttenuation> toBePlayed = new List <SoundSourceAttenuation>();

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        int state;
                        AL.GetSource(Sources[i].OpenAlSourceName, ALGetSourcei.SourceState, out state);
                        if (state != (int)ALSourceState.Initial & state != (int)ALSourceState.Playing)
                        {
                            /*
                             * The sound is not playing any longer.
                             * Remove it from the list of sound sources.
                             * */
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                            continue;
                        }
                    }

                    /*
                     * Calculate the gain, then add the sound
                     * to the list of sounds to be played.
                     * */
                    OpenBveApi.Math.Vector3 position;
                    if (Sources[i].Train != null)
                    {
                        OpenBveApi.Math.Vector3 direction;
                        Sources[i].Train.Cars[Sources[i].Car].CreateWorldCoordinates(Sources[i].Position, out position, out direction);
                    }
                    else
                    {
                        position = Sources[i].Position;
                    }
                    OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition;
                    double distance = positionDifference.Norm();
                    double radius   = Sources[i].Radius;
                    if (World.CameraMode == CameraViewMode.Interior | World.CameraMode == CameraViewMode.InteriorLookAhead)
                    {
                        if (Sources[i].Train != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar)
                        {
                            radius *= 0.5;
                        }
                    }
                    double gain;
                    if (distance < 2.0 * radius)
                    {
                        gain = 1.0 - distance * distance * (4.0 * radius - distance) / (16.0 * radius * radius * radius);
                    }
                    else
                    {
                        gain = radius / distance;
                    }
                    gain *= Sources[i].Volume;
                    if (gain <= 0.0)
                    {
                        /*
                         * The gain is too low. Stop the sound if playing,
                         * but keep looping sounds pending.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            AL.DeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Add the source.
                         * */
                        toBePlayed.Add(new SoundSourceAttenuation(Sources[i], gain, distance));
                    }
                }
            }

            /*
             * Now that we have the list of sounds that are to be played,
             * sort them by their gain so that we can determine and
             * adjust the clamp factor.
             * */
            double clampFactor = Math.Exp(LogClampFactor);

            for (int i = 0; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain -= clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
            }
            toBePlayed.Sort();
            for (int i = 0; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain += clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
            }
            double desiredLogClampFactor;
            int    index = Interface.CurrentOptions.SoundNumber;

            if (toBePlayed.Count <= index)
            {
                desiredLogClampFactor = MinLogClampFactor;
            }
            else
            {
                double cutoffDistance = toBePlayed[index].Distance;
                if (cutoffDistance <= 0.0)
                {
                    desiredLogClampFactor = MaxLogClampFactor;
                }
                else
                {
                    double cutoffGain = toBePlayed[index].Gain;
                    desiredLogClampFactor = Math.Log(cutoffGain / (cutoffDistance * cutoffDistance));
                    if (desiredLogClampFactor < MinLogClampFactor)
                    {
                        desiredLogClampFactor = MinLogClampFactor;
                    }
                    else if (desiredLogClampFactor > MaxLogClampFactor)
                    {
                        desiredLogClampFactor = MaxLogClampFactor;
                    }
                }
            }
            const double rate = 3.0;

            if (LogClampFactor < desiredLogClampFactor)
            {
                LogClampFactor += timeElapsed * rate;
                if (LogClampFactor > desiredLogClampFactor)
                {
                    LogClampFactor = desiredLogClampFactor;
                }
            }
            else if (LogClampFactor > desiredLogClampFactor)
            {
                LogClampFactor -= timeElapsed * rate;
                if (LogClampFactor < desiredLogClampFactor)
                {
                    LogClampFactor = desiredLogClampFactor;
                }
            }

            /*
             * Play the sounds.
             * */
            clampFactor = Math.Exp(LogClampFactor);
            for (int i = index; i < toBePlayed.Count; i++)
            {
                toBePlayed[i].Gain = 0.0;
            }
            for (int i = 0; i < toBePlayed.Count; i++)
            {
                SoundSource source = toBePlayed[i].Source;
                double      gain   = toBePlayed[i].Gain - clampFactor * toBePlayed[i].Distance * toBePlayed[i].Distance;
                if (gain <= 0.0)
                {
                    /*
                     * Stop the sound.
                     * */
                    if (source.State == SoundSourceState.Playing)
                    {
                        AL.DeleteSources(1, ref source.OpenAlSourceName);
                        source.State            = SoundSourceState.PlayPending;
                        source.OpenAlSourceName = 0;
                    }
                    if (!source.Looped)
                    {
                        source.State            = SoundSourceState.Stopped;
                        source.OpenAlSourceName = 0;
                    }
                }
                else
                {
                    /*
                     * Ensure the buffer is loaded, then play the sound.
                     * */
                    if (source.State != SoundSourceState.Playing)
                    {
                        LoadBuffer(source.Buffer);
                        if (source.Buffer.Loaded)
                        {
                            AL.GenSources(1, out source.OpenAlSourceName);
                            AL.Source(source.OpenAlSourceName, ALSourcei.Buffer, source.Buffer.OpenAlBufferName);
                        }
                        else
                        {
                            /*
                             * We cannot play the sound because
                             * the buffer could not be loaded.
                             * */
                            source.State = SoundSourceState.Stopped;
                            continue;
                        }
                    }
                    OpenBveApi.Math.Vector3 position;
                    OpenBveApi.Math.Vector3 velocity;
                    if (source.Train != null)
                    {
                        OpenBveApi.Math.Vector3 direction;
                        source.Train.Cars[source.Car].CreateWorldCoordinates(source.Position, out position, out direction);
                        velocity = source.Train.Cars[source.Car].Specs.CurrentSpeed * direction;
                    }
                    else
                    {
                        position = source.Position;
                        velocity = OpenBveApi.Math.Vector3.Zero;
                    }
                    position -= listenerPosition;
                    AL.Source(source.OpenAlSourceName, ALSource3f.Position, (float)position.X, (float)position.Y, (float)position.Z);
                    AL.Source(source.OpenAlSourceName, ALSource3f.Velocity, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                    AL.Source(source.OpenAlSourceName, ALSourcef.Pitch, (float)source.Pitch);
                    AL.Source(source.OpenAlSourceName, ALSourcef.Gain, (float)gain);
                    if (source.State != SoundSourceState.Playing)
                    {
                        AL.Source(source.OpenAlSourceName, ALSourceb.Looping, source.Looped);
                        AL.SourcePlay(source.OpenAlSourceName);
                        source.State = SoundSourceState.Playing;
                    }
                }
            }
        }
示例#4
0
        /// <summary>Updates the sound component. Should be called every frame.</summary>
        /// <param name="timeElapsed">The time in seconds that elapsed since the last call to this function.</param>
        private static void UpdateLinearModel(double timeElapsed)
        {
            /*
             * Set up the listener
             * */
            OpenBveApi.Math.Vector3      listenerPosition    = World.AbsoluteCameraPosition;
            OpenBveApi.Math.Orientation3 listenerOrientation = new OpenBveApi.Math.Orientation3(World.AbsoluteCameraSide, World.AbsoluteCameraUp, World.AbsoluteCameraDirection);
            OpenBveApi.Math.Vector3      listenerVelocity;
            if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead | World.CameraMode == World.CameraViewMode.Exterior)
            {
                TrainManager.Car        car  = TrainManager.PlayerTrain.Cars[TrainManager.PlayerTrain.DriverCar];
                OpenBveApi.Math.Vector3 diff = car.FrontAxle.Follower.WorldPosition - car.RearAxle.Follower.WorldPosition;
                listenerVelocity = car.Specs.CurrentSpeed * OpenBveApi.Math.Vector3.Normalize(diff) + World.CameraAlignmentSpeed.Position;
            }
            else
            {
                listenerVelocity = World.CameraAlignmentSpeed.Position;
            }
            Al.alListener3f(Al.AL_POSITION, 0.0f, 0.0f, 0.0f);
            Al.alListener3f(Al.AL_VELOCITY, (float)listenerVelocity.X, (float)listenerVelocity.Y, (float)listenerVelocity.Z);
            Al.alListenerfv(Al.AL_ORIENTATION, new float[] { (float)listenerOrientation.Z.X, (float)listenerOrientation.Z.Y, (float)listenerOrientation.Z.Z, -(float)listenerOrientation.Y.X, -(float)listenerOrientation.Y.Y, -(float)listenerOrientation.Y.Z });

            /*
             * Set up the atmospheric attributes
             * */
            double elevation      = World.AbsoluteCameraPosition.Y + Game.RouteInitialElevation;
            double airTemperature = Game.GetAirTemperature(elevation);
            double airPressure    = Game.GetAirPressure(elevation, airTemperature);
            double airDensity     = Game.GetAirDensity(airPressure, airTemperature);
            double speedOfSound   = Game.GetSpeedOfSound(airPressure, airTemperature);

            try {
                Al.alSpeedOfSound((float)speedOfSound);
            } catch { }

            /*
             * Update the sound sources
             * */
            int actuallyPlaying = 0;

            for (int i = 0; i < SourceCount; i++)
            {
                if (Sources[i].State == SoundSourceState.StopPending)
                {
                    /*
                     * The sound is still playing but is to be stopped.
                     * Stop the sound, then remove it from the list of
                     * sound sources.
                     * */
                    Al.alDeleteSources(1, ref Sources[i].OpenAlSourceName);
                    Sources[i].State            = SoundSourceState.Stopped;
                    Sources[i].OpenAlSourceName = 0;
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (Sources[i].State == SoundSourceState.Stopped)
                {
                    /*
                     * The sound was already stopped. Remove it from
                     * the list of sound sources.
                     * */
                    Sources[i] = Sources[SourceCount - 1];
                    SourceCount--;
                    i--;
                }
                else if (GlobalMute)
                {
                    /*
                     * The sound is playing or about to be played, but
                     * the global mute option is enabled. Stop the sound
                     * sound if necessary, then remove it from the list
                     * of sound sources if the sound is not looping.
                     * */
                    if (Sources[i].State == SoundSourceState.Playing)
                    {
                        Al.alDeleteSources(1, ref Sources[i].OpenAlSourceName);
                        Sources[i].State            = SoundSourceState.PlayPending;
                        Sources[i].OpenAlSourceName = 0;
                    }
                    if (!Sources[i].Looped)
                    {
                        Sources[i].State            = SoundSourceState.Stopped;
                        Sources[i].OpenAlSourceName = 0;
                        Sources[i] = Sources[SourceCount - 1];
                        SourceCount--;
                        i--;
                    }
                }
                else
                {
                    /*
                     * The sound is to be played or is already playing.
                     * Calculate the sound gain.
                     * */
                    OpenBveApi.Math.Vector3 position;
                    OpenBveApi.Math.Vector3 velocity;
                    if (Sources[i].Train != null)
                    {
                        OpenBveApi.Math.Vector3 direction;
                        TrainManager.CreateWorldCoordinates(Sources[i].Train, Sources[i].Car, Sources[i].Position.X, Sources[i].Position.Y, Sources[i].Position.Z, out position.X, out position.Y, out position.Z, out direction.X, out direction.Y, out direction.Z);
                        velocity = Sources[i].Train.Cars[Sources[i].Car].Specs.CurrentSpeed * direction;
                    }
                    else
                    {
                        position = Sources[i].Position;
                        velocity = OpenBveApi.Math.Vector3.Null;
                    }
                    OpenBveApi.Math.Vector3 positionDifference = position - listenerPosition;
                    double gain;
                    if (GlobalMute)
                    {
                        gain = 0.0;
                    }
                    else
                    {
                        double distance    = positionDifference.Norm();
                        double innerRadius = Sources[i].Radius;
                        if (World.CameraMode == World.CameraViewMode.Interior | World.CameraMode == World.CameraViewMode.InteriorLookAhead)
                        {
                            if (Sources[i].Train != TrainManager.PlayerTrain || Sources[i].Car != TrainManager.PlayerTrain.DriverCar)
                            {
                                innerRadius *= 0.5;
                            }
                        }
                        double outerRadius = OuterRadiusFactor * innerRadius;
                        if (distance < outerRadius)
                        {
                            if (distance <= innerRadius)
                            {
                                gain = Sources[i].Volume;
                            }
                            else
                            {
                                gain  = (distance - outerRadius) / (innerRadius - outerRadius);
                                gain *= Sources[i].Volume;
                            }
                            gain = 3.0 * gain * gain - 2.0 * gain * gain * gain;
                        }
                        else
                        {
                            gain = 0.0;
                        }
                    }
                    if (gain <= GainThreshold)
                    {
                        /*
                         * If the gain is too low to be audible, stop the sound.
                         * If the sound is not looping, stop it if necessary,
                         * then remove it from the list of sound sources.
                         * */
                        if (Sources[i].State == SoundSourceState.Playing)
                        {
                            Al.alDeleteSources(1, ref Sources[i].OpenAlSourceName);
                            Sources[i].State            = SoundSourceState.PlayPending;
                            Sources[i].OpenAlSourceName = 0;
                        }
                        if (!Sources[i].Looped)
                        {
                            Sources[i].State            = SoundSourceState.Stopped;
                            Sources[i].OpenAlSourceName = 0;
                            Sources[i] = Sources[SourceCount - 1];
                            SourceCount--;
                            i--;
                        }
                    }
                    else
                    {
                        /*
                         * Play the sound and update position, velocity, pitch and gain.
                         * For non-looping sounds, check if the sound is still playing.
                         * */
                        gain = (gain - GainThreshold) / (1.0 - GainThreshold);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            LoadBuffer(Sources[i].Buffer);
                            if (Sources[i].Buffer.Loaded)
                            {
                                Al.alGenSources(1, out Sources[i].OpenAlSourceName);
                                Al.alSourcei(Sources[i].OpenAlSourceName, Al.AL_BUFFER, Sources[i].Buffer.OpenAlBufferName);
                            }
                            else
                            {
                                /*
                                 * We cannot play the sound because
                                 * the buffer could not be loaded.
                                 * */
                                Sources[i].State = SoundSourceState.Stopped;
                                continue;
                            }
                        }
                        Al.alSource3f(Sources[i].OpenAlSourceName, Al.AL_POSITION, (float)positionDifference.X, (float)positionDifference.Y, (float)positionDifference.Z);
                        Al.alSource3f(Sources[i].OpenAlSourceName, Al.AL_VELOCITY, (float)velocity.X, (float)velocity.Y, (float)velocity.Z);
                        Al.alSourcef(Sources[i].OpenAlSourceName, Al.AL_PITCH, (float)Sources[i].Pitch);
                        Al.alSourcef(Sources[i].OpenAlSourceName, Al.AL_GAIN, (float)gain);
                        if (Sources[i].State != SoundSourceState.Playing)
                        {
                            Al.alSourcei(Sources[i].OpenAlSourceName, Al.AL_LOOPING, Sources[i].Looped ? Al.AL_TRUE : Al.AL_FALSE);
                            Al.alSourcePlay(Sources[i].OpenAlSourceName);
                            Sources[i].State = SoundSourceState.Playing;
                        }
                        if (!Sources[i].Looped)
                        {
                            int state;
                            Al.alGetSourcei(Sources[i].OpenAlSourceName, Al.AL_SOURCE_STATE, out state);
                            if (state != Al.AL_INITIAL & state != Al.AL_PLAYING)
                            {
                                /*
                                 * The sound is not playing any longer.
                                 * Remove it from the list of sound sources.
                                 * */
                                Al.alDeleteSources(1, ref Sources[i].OpenAlSourceName);
                                Sources[i].State            = SoundSourceState.Stopped;
                                Sources[i].OpenAlSourceName = 0;
                                Sources[i] = Sources[SourceCount - 1];
                                SourceCount--;
                                i--;
                            }
                            else
                            {
                                actuallyPlaying++;
                            }
                        }
                        else
                        {
                            actuallyPlaying++;
                        }
                    }
                }
            }

            /*
             * Adjust the outer radius factor / the clamp factor.
             * */
            if (actuallyPlaying >= Interface.CurrentOptions.SoundNumber - 2)
            {
                /*
                 * Too many sounds are playing.
                 * Reduce the outer radius factor.
                 * */
                OuterRadiusFactorSpeed -= timeElapsed;
                if (OuterRadiusFactorSpeed < -OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = -OuterRadiusFactorMaximumSpeed;
                }
            }
            else if (actuallyPlaying <= Interface.CurrentOptions.SoundNumber - 6)
            {
                /*
                 * Only few sounds are playing.
                 * Increase the outer radius factor.
                 * */
                OuterRadiusFactorSpeed += timeElapsed;
                if (OuterRadiusFactorSpeed > OuterRadiusFactorMaximumSpeed)
                {
                    OuterRadiusFactorSpeed = OuterRadiusFactorMaximumSpeed;
                }
            }
            else
            {
                /*
                 * Neither too many nor too few sounds are playing.
                 * Stabilize the outer radius factor.
                 * */
                if (OuterRadiusFactorSpeed < 0.0)
                {
                    OuterRadiusFactorSpeed += timeElapsed;
                    if (OuterRadiusFactorSpeed > 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
                else
                {
                    OuterRadiusFactorSpeed -= timeElapsed;
                    if (OuterRadiusFactorSpeed < 0.0)
                    {
                        OuterRadiusFactorSpeed = 0.0;
                    }
                }
            }
            OuterRadiusFactor += OuterRadiusFactorSpeed * timeElapsed;
            if (OuterRadiusFactor < OuterRadiusFactorMinimum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMinimum;
                OuterRadiusFactorSpeed = 0.0;
            }
            else if (OuterRadiusFactor > OuterRadiusFactorMaximum)
            {
                OuterRadiusFactor      = OuterRadiusFactorMaximum;
                OuterRadiusFactorSpeed = 0.0;
            }
        }