1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using OpenBveApi.Math; 5 using OpenBveApi.Trains; 6 using SoundManager; 7 using TrainEditor2.Models.Sounds; 8 using TrainManager.Car; 9 using TrainManager.Motor; 10 11 namespace TrainEditor2.Simulation.TrainManager 12 { 13 public static partial class TrainManager 14 { 15 /// <summary>The base class containing the properties of a train car</summary> 16 internal class Car : AbstractCar 17 { 18 private readonly Train baseTrain; 19 internal CarPhysics Specs; 20 internal CarSounds Sounds; 21 Car(Train baseTrain)22 internal Car(Train baseTrain) 23 { 24 this.baseTrain = baseTrain; 25 this.Specs = new CarPhysics(); 26 this.Sounds = new CarSounds(); 27 InitializeCarSounds(); 28 } 29 30 /// <summary>Initializes a train with the default (empty) set of car sounds</summary> InitializeCarSounds()31 internal void InitializeCarSounds() 32 { 33 Sounds.Run = new Dictionary<int, CarSound>(); 34 Sounds.Flange = new Dictionary<int, CarSound>(); 35 } 36 UpdateRunSounds(double TimeElapsed, int RunIndex)37 internal void UpdateRunSounds(double TimeElapsed, int RunIndex) 38 { 39 if (Sounds.Run == null || Sounds.Run.Count == 0) 40 { 41 return; 42 } 43 44 const double factor = 0.04; // 90 km/h -> m/s -> 1/x 45 double speed = Math.Abs(CurrentSpeed); 46 double pitch = speed * factor; 47 double baseGain = speed < 2.77777777777778 ? 0.36 * speed : 1.0; 48 49 for (int i = 0; i < Sounds.Run.Count; i++) 50 { 51 int key = Sounds.Run.ElementAt(i).Key; 52 if (key == RunIndex) 53 { 54 Sounds.Run[key].TargetVolume += 3.0 * TimeElapsed; 55 56 if (Sounds.Run[key].TargetVolume > 1.0) 57 { 58 Sounds.Run[key].TargetVolume = 1.0; 59 } 60 } 61 else 62 { 63 Sounds.Run[key].TargetVolume -= 3.0 * TimeElapsed; 64 65 if (Sounds.Run[key].TargetVolume < 0.0) 66 { 67 Sounds.Run[key].TargetVolume = 0.0; 68 } 69 } 70 71 double gain = baseGain * Sounds.Run[key].TargetVolume; 72 73 if (Sounds.Run[key].IsPlaying) 74 { 75 if (pitch > 0.01 & gain > 0.001) 76 { 77 Sounds.Run[key].Source.Pitch = pitch; 78 Sounds.Run[key].Source.Volume = gain; 79 } 80 else 81 { 82 Sounds.Run[key].Stop(); 83 } 84 } 85 else if (pitch > 0.02 & gain > 0.01) 86 { 87 Sounds.Run[key].Play(pitch, gain, this, true); 88 } 89 } 90 } 91 UpdateMotorSounds(bool isPlayTrack1, bool isPlayTrack2)92 internal void UpdateMotorSounds(bool isPlayTrack1, bool isPlayTrack2) 93 { 94 Vector3 pos = Sounds.Motor.Position; 95 double speed = Math.Abs(Specs.PerceivedSpeed); 96 int idx = (int)Math.Round(speed * Sounds.Motor.SpeedConversionFactor); 97 int odir = Sounds.Motor.CurrentAccelerationDirection; 98 int ndir = Math.Sign(Specs.Acceleration); 99 100 for (int h = 0; h < 2; h++) 101 { 102 int j = h == 0 ? BVEMotorSound.MotorP1 : BVEMotorSound.MotorP2; 103 int k = h == 0 ? BVEMotorSound.MotorB1 : BVEMotorSound.MotorB2; 104 105 if (odir > 0 & ndir <= 0) 106 { 107 if (j < Sounds.Motor.Tables.Length) 108 { 109 Program.SoundApi.StopSound(Sounds.Motor.Tables[j].Source); 110 Sounds.Motor.Tables[j].Source = null; 111 Sounds.Motor.Tables[j].Buffer = null; 112 } 113 } 114 else if (odir < 0 & ndir >= 0) 115 { 116 if (k < Sounds.Motor.Tables.Length) 117 { 118 Program.SoundApi.StopSound(Sounds.Motor.Tables[k].Source); 119 Sounds.Motor.Tables[k].Source = null; 120 Sounds.Motor.Tables[k].Buffer = null; 121 } 122 } 123 124 if (ndir != 0) 125 { 126 if (ndir < 0) 127 { 128 j = k; 129 } 130 131 if (j < Sounds.Motor.Tables.Length) 132 { 133 int idx2 = idx; 134 135 if (idx2 >= Sounds.Motor.Tables[j].Entries.Length) 136 { 137 idx2 = Sounds.Motor.Tables[j].Entries.Length - 1; 138 } 139 140 if ((!isPlayTrack1 && h == 0) || (!isPlayTrack2 && h == 1)) 141 { 142 idx2 = -1; 143 } 144 145 if (idx2 >= 0) 146 { 147 SoundBuffer obuf = Sounds.Motor.Tables[j].Buffer; 148 SoundBuffer nbuf = Sounds.Motor.Tables[j].Entries[idx2].Buffer; 149 double pitch = Sounds.Motor.Tables[j].Entries[idx2].Pitch; 150 double gain = Sounds.Motor.Tables[j].Entries[idx2].Gain; 151 152 if (obuf != nbuf) 153 { 154 Program.SoundApi.StopSound(Sounds.Motor.Tables[j].Source); 155 156 if (nbuf != null) 157 { 158 Sounds.Motor.Tables[j].Source = Program.SoundApi.PlaySound(nbuf, pitch, gain, pos, baseTrain, true); 159 Sounds.Motor.Tables[j].Buffer = nbuf; 160 } 161 else 162 { 163 Sounds.Motor.Tables[j].Source = null; 164 Sounds.Motor.Tables[j].Buffer = null; 165 } 166 } 167 else if (nbuf != null) 168 { 169 if (Sounds.Motor.Tables[j].Source != null) 170 { 171 Sounds.Motor.Tables[j].Source.Pitch = pitch; 172 Sounds.Motor.Tables[j].Source.Volume = gain; 173 } 174 } 175 else 176 { 177 Program.SoundApi.StopSound(Sounds.Motor.Tables[j].Source); 178 Sounds.Motor.Tables[j].Source = null; 179 Sounds.Motor.Tables[j].Buffer = null; 180 } 181 } 182 else 183 { 184 Program.SoundApi.StopSound(Sounds.Motor.Tables[j].Source); 185 Sounds.Motor.Tables[j].Source = null; 186 Sounds.Motor.Tables[j].Buffer = null; 187 } 188 } 189 } 190 } 191 192 Sounds.Motor.CurrentAccelerationDirection = ndir; 193 } 194 ApplySounds()195 internal void ApplySounds() 196 { 197 //Default sound positions and radii 198 double mediumRadius = 10.0; 199 200 //3D center of the car 201 Vector3 center = Vector3.Zero; 202 203 // run sound 204 foreach (var element in RunSounds) 205 { 206 Sounds.Run[element.Key] = new CarSound(Program.SoundApi.RegisterBuffer(element.FilePath, mediumRadius), center); 207 } 208 209 // motor sound 210 Sounds.Motor.Position = center; 211 212 for (int i = 0; i < Sounds.Motor.Tables.Length; i++) 213 { 214 Sounds.Motor.Tables[i].Buffer = null; 215 Sounds.Motor.Tables[i].Source = null; 216 217 for (int j = 0; j < Sounds.Motor.Tables[i].Entries.Length; j++) 218 { 219 MotorElement element = MotorSounds.FirstOrDefault(x => x.Key == Sounds.Motor.Tables[i].Entries[j].SoundIndex); 220 221 if (element != null) 222 { 223 Sounds.Motor.Tables[i].Entries[j].Buffer = Program.SoundApi.RegisterBuffer(element.FilePath, mediumRadius); 224 } 225 } 226 } 227 } 228 } 229 } 230 } 231