├── .gitattributes ├── .gitignore ├── Assets └── RSE_Icon.xcf ├── GameData └── RocketSoundEnhancement │ ├── Plugins │ ├── LICENSE.txt │ ├── RocketSoundEnhancement.Unity.dll │ ├── RocketSoundEnhancement.dll │ └── rse_bundle │ ├── RocketSoundEnhancement.version │ ├── Settings.cfg │ └── Textures │ └── RSE_Icon.png ├── LICENSE ├── README.md ├── Source ├── RocketSoundEnhancement.Unity │ ├── ISettingsPanel.cs │ ├── MathHelper.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── RSE_Panel.cs │ ├── RocketSoundEnhancement.Unity.csproj │ └── SliderValueDisplay.cs ├── RocketSoundEnhancement.sln ├── RocketSoundEnhancement │ ├── AudioFilters │ │ └── AirSimulationFilter.cs │ ├── AudioUtility.cs │ ├── EffectBehaviours │ │ └── RSE_AudioEffects.cs │ ├── PartModules │ │ ├── RSE_Coupler.cs │ │ ├── RSE_Engines.cs │ │ ├── RSE_KerbalEVA.cs │ │ ├── RSE_Module.cs │ │ ├── RSE_RCS.cs │ │ ├── RSE_RotorEngines.cs │ │ ├── RSE_Wheels.cs │ │ └── ShipEffectsCollisions.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── RocketSoundEnhancement.cs │ ├── RocketSoundEnhancement.csproj │ ├── Settings.cs │ ├── SettingsPanel.cs │ ├── ShipEffects.cs │ ├── ShipEffectsConfig.cs │ └── Startup.cs └── Unity │ └── RSE_Assets │ ├── Assembly-CSharp-Editor.csproj │ ├── Assembly-CSharp.csproj │ ├── AssetBundles │ ├── AssetBundles │ ├── AssetBundles.manifest │ ├── rse_bundle │ └── rse_bundle.manifest │ ├── Assets │ ├── Editor │ │ ├── Bundler.cs │ │ ├── KSPCurveEditor.cs │ │ └── UI Colors.colors │ ├── Fonts │ │ ├── AdventPro-Regular.ttf │ │ ├── AdventPro-SemiBold.ttf │ │ └── Gruppo.ttf │ ├── LogValueTest.cs │ ├── Plugins │ │ └── RocketSoundEnhancement.Unity.dll │ ├── RSE_Assets.unity │ ├── RSE_Mixer.mixer │ ├── RSE_Panel.prefab │ └── Screenshots │ │ ├── screenshot16.png │ │ └── screenshot5.png │ ├── ProjectSettings │ ├── AudioManager.asset │ ├── ClusterInputManager.asset │ ├── DynamicsManager.asset │ ├── EditorBuildSettings.asset │ ├── EditorSettings.asset │ ├── GraphicsSettings.asset │ ├── InputManager.asset │ ├── NavMeshAreas.asset │ ├── NetworkManager.asset │ ├── PackageManagerSettings.asset │ ├── Physics2DSettings.asset │ ├── PresetManager.asset │ ├── ProjectSettings.asset │ ├── ProjectVersion.txt │ ├── QualitySettings.asset │ ├── TagManager.asset │ ├── TimeManager.asset │ ├── UnityConnectSettings.asset │ ├── VFXManager.asset │ └── XRSettings.asset │ └── RSE_Assets.sln └── changelog.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Distribution 2 | .vscode 3 | *.zip 4 | *.mdb 5 | 6 | ## Ignore Visual Studio temporary files, build results, and 7 | ## files generated by popular Visual Studio add-ons. 8 | ## 9 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 10 | 11 | # User-specific files 12 | *.rsuser 13 | *.suo 14 | *.user 15 | *.userosscache 16 | *.sln.docstates 17 | 18 | # User-specific files (MonoDevelop/Xamarin Studio) 19 | *.userprefs 20 | 21 | # Mono auto generated files 22 | mono_crash.* 23 | 24 | # Build results 25 | [Dd]ebug/ 26 | [Dd]ebugPublic/ 27 | [Rr]elease/ 28 | [Rr]eleases/ 29 | x64/ 30 | x86/ 31 | [Ww][Ii][Nn]32/ 32 | [Aa][Rr][Mm]/ 33 | [Aa][Rr][Mm]64/ 34 | bld/ 35 | [Bb]in/ 36 | [Oo]bj/ 37 | [Ll]og/ 38 | [Ll]ogs/ 39 | 40 | # Visual Studio 2015/2017 cache/options directory 41 | .vs/ 42 | # Uncomment if you have tasks that create the project's static files in wwwroot 43 | #wwwroot/ 44 | 45 | # Visual Studio 2017 auto generated files 46 | Generated\ Files/ 47 | 48 | # MSTest test Results 49 | [Tt]est[Rr]esult*/ 50 | [Bb]uild[Ll]og.* 51 | 52 | # NUnit 53 | *.VisualState.xml 54 | TestResult.xml 55 | nunit-*.xml 56 | 57 | # Build Results of an ATL Project 58 | [Dd]ebugPS/ 59 | [Rr]eleasePS/ 60 | dlldata.c 61 | 62 | # Benchmark Results 63 | BenchmarkDotNet.Artifacts/ 64 | 65 | # .NET Core 66 | project.lock.json 67 | project.fragment.lock.json 68 | artifacts/ 69 | 70 | # ASP.NET Scaffolding 71 | ScaffoldingReadMe.txt 72 | 73 | # StyleCop 74 | StyleCopReport.xml 75 | 76 | # Files built by Visual Studio 77 | *_i.c 78 | *_p.c 79 | *_h.h 80 | *.ilk 81 | *.meta 82 | *.obj 83 | *.iobj 84 | *.pch 85 | *.pdb 86 | *.ipdb 87 | *.pgc 88 | *.pgd 89 | *.rsp 90 | *.sbr 91 | *.tlb 92 | *.tli 93 | *.tlh 94 | *.tmp 95 | *.tmp_proj 96 | *_wpftmp.csproj 97 | *.log 98 | *.vspscc 99 | *.vssscc 100 | .builds 101 | *.pidb 102 | *.svclog 103 | *.scc 104 | 105 | # Chutzpah Test files 106 | _Chutzpah* 107 | 108 | # Visual C++ cache files 109 | ipch/ 110 | *.aps 111 | *.ncb 112 | *.opendb 113 | *.opensdf 114 | *.sdf 115 | *.cachefile 116 | *.VC.db 117 | *.VC.VC.opendb 118 | 119 | # Visual Studio profiler 120 | *.psess 121 | *.vsp 122 | *.vspx 123 | *.sap 124 | 125 | # Visual Studio Trace Files 126 | *.e2e 127 | 128 | # TFS 2012 Local Workspace 129 | $tf/ 130 | 131 | # Guidance Automation Toolkit 132 | *.gpState 133 | 134 | # ReSharper is a .NET coding add-in 135 | _ReSharper*/ 136 | *.[Rr]e[Ss]harper 137 | *.DotSettings.user 138 | 139 | # TeamCity is a build add-in 140 | _TeamCity* 141 | 142 | # DotCover is a Code Coverage Tool 143 | *.dotCover 144 | 145 | # AxoCover is a Code Coverage Tool 146 | .axoCover/* 147 | !.axoCover/settings.json 148 | 149 | # Coverlet is a free, cross platform Code Coverage Tool 150 | coverage*.json 151 | coverage*.xml 152 | coverage*.info 153 | 154 | # Visual Studio code coverage results 155 | *.coverage 156 | *.coveragexml 157 | 158 | # NCrunch 159 | _NCrunch_* 160 | .*crunch*.local.xml 161 | nCrunchTemp_* 162 | 163 | # MightyMoose 164 | *.mm.* 165 | AutoTest.Net/ 166 | 167 | # Web workbench (sass) 168 | .sass-cache/ 169 | 170 | # Installshield output folder 171 | [Ee]xpress/ 172 | 173 | # DocProject is a documentation generator add-in 174 | DocProject/buildhelp/ 175 | DocProject/Help/*.HxT 176 | DocProject/Help/*.HxC 177 | DocProject/Help/*.hhc 178 | DocProject/Help/*.hhk 179 | DocProject/Help/*.hhp 180 | DocProject/Help/Html2 181 | DocProject/Help/html 182 | 183 | # Click-Once directory 184 | publish/ 185 | 186 | # Publish Web Output 187 | *.[Pp]ublish.xml 188 | *.azurePubxml 189 | # Note: Comment the next line if you want to checkin your web deploy settings, 190 | # but database connection strings (with potential passwords) will be unencrypted 191 | *.pubxml 192 | *.publishproj 193 | 194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 195 | # checkin your Azure Web App publish settings, but sensitive information contained 196 | # in these scripts will be unencrypted 197 | PublishScripts/ 198 | 199 | # NuGet Packages 200 | *.nupkg 201 | # NuGet Symbol Packages 202 | *.snupkg 203 | # The packages folder can be ignored because of Package Restore 204 | **/[Pp]ackages/* 205 | # except build/, which is used as an MSBuild target. 206 | !**/[Pp]ackages/build/ 207 | # Uncomment if necessary however generally it will be regenerated when needed 208 | #!**/[Pp]ackages/repositories.config 209 | # NuGet v3's project.json files produces more ignorable files 210 | *.nuget.props 211 | *.nuget.targets 212 | 213 | # Microsoft Azure Build Output 214 | csx/ 215 | *.build.csdef 216 | 217 | # Microsoft Azure Emulator 218 | ecf/ 219 | rcf/ 220 | 221 | # Windows Store app package directories and files 222 | AppPackages/ 223 | BundleArtifacts/ 224 | Package.StoreAssociation.xml 225 | _pkginfo.txt 226 | *.appx 227 | *.appxbundle 228 | *.appxupload 229 | 230 | # Visual Studio cache files 231 | # files ending in .cache can be ignored 232 | *.[Cc]ache 233 | # but keep track of directories ending in .cache 234 | !?*.[Cc]ache/ 235 | 236 | # Others 237 | ClientBin/ 238 | ~$* 239 | *~ 240 | *.dbmdl 241 | *.dbproj.schemaview 242 | *.jfm 243 | *.pfx 244 | *.publishsettings 245 | orleans.codegen.cs 246 | 247 | # Including strong name files can present a security risk 248 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 249 | #*.snk 250 | 251 | # Since there are multiple workflows, uncomment next line to ignore bower_components 252 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 253 | #bower_components/ 254 | 255 | # RIA/Silverlight projects 256 | Generated_Code/ 257 | 258 | # Backup & report files from converting an old project file 259 | # to a newer Visual Studio version. Backup files are not needed, 260 | # because we have git ;-) 261 | _UpgradeReport_Files/ 262 | Backup*/ 263 | UpgradeLog*.XML 264 | UpgradeLog*.htm 265 | ServiceFabricBackup/ 266 | *.rptproj.bak 267 | 268 | # SQL Server files 269 | *.mdf 270 | *.ldf 271 | *.ndf 272 | 273 | # Business Intelligence projects 274 | *.rdl.data 275 | *.bim.layout 276 | *.bim_*.settings 277 | *.rptproj.rsuser 278 | *- [Bb]ackup.rdl 279 | *- [Bb]ackup ([0-9]).rdl 280 | *- [Bb]ackup ([0-9][0-9]).rdl 281 | 282 | # Microsoft Fakes 283 | FakesAssemblies/ 284 | 285 | # GhostDoc plugin setting file 286 | *.GhostDoc.xml 287 | 288 | # Node.js Tools for Visual Studio 289 | .ntvs_analysis.dat 290 | node_modules/ 291 | 292 | # Visual Studio 6 build log 293 | *.plg 294 | 295 | # Visual Studio 6 workspace options file 296 | *.opt 297 | 298 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 299 | *.vbw 300 | 301 | # Visual Studio LightSwitch build output 302 | **/*.HTMLClient/GeneratedArtifacts 303 | **/*.DesktopClient/GeneratedArtifacts 304 | **/*.DesktopClient/ModelManifest.xml 305 | **/*.Server/GeneratedArtifacts 306 | **/*.Server/ModelManifest.xml 307 | _Pvt_Extensions 308 | 309 | # Paket dependency manager 310 | .paket/paket.exe 311 | paket-files/ 312 | 313 | # FAKE - F# Make 314 | .fake/ 315 | 316 | # CodeRush personal settings 317 | .cr/personal 318 | 319 | # Python Tools for Visual Studio (PTVS) 320 | __pycache__/ 321 | *.pyc 322 | 323 | # Cake - Uncomment if you are using it 324 | # tools/** 325 | # !tools/packages.config 326 | 327 | # Tabs Studio 328 | *.tss 329 | 330 | # Telerik's JustMock configuration file 331 | *.jmconfig 332 | 333 | # BizTalk build output 334 | *.btp.cs 335 | *.btm.cs 336 | *.odx.cs 337 | *.xsd.cs 338 | 339 | # OpenCover UI analysis results 340 | OpenCover/ 341 | 342 | # Azure Stream Analytics local run output 343 | ASALocalRun/ 344 | 345 | # MSBuild Binary and Structured Log 346 | *.binlog 347 | 348 | # NVidia Nsight GPU debugger configuration file 349 | *.nvuser 350 | 351 | # MFractors (Xamarin productivity tool) working folder 352 | .mfractor/ 353 | 354 | # Local History for Visual Studio 355 | .localhistory/ 356 | 357 | # BeatPulse healthcheck temp database 358 | healthchecksdb 359 | 360 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 361 | MigrationBackup/ 362 | 363 | # Ionide (cross platform F# VS Code tools) working folder 364 | .ionide/ 365 | 366 | # Fody - auto-generated XML schema 367 | FodyWeavers.xsd 368 | /Source/Unity/RSE_Assets/Temp 369 | /Source/Unity/RSE_Assets/Library/ScriptAssemblies/*.dll 370 | /Source/Unity/RSE_Assets/Library 371 | /Source/Unity/RSE_Testing 372 | -------------------------------------------------------------------------------- /Assets/RSE_Icon.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Assets/RSE_Icon.xcf -------------------------------------------------------------------------------- /GameData/RocketSoundEnhancement/Plugins/RocketSoundEnhancement.Unity.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/GameData/RocketSoundEnhancement/Plugins/RocketSoundEnhancement.Unity.dll -------------------------------------------------------------------------------- /GameData/RocketSoundEnhancement/Plugins/RocketSoundEnhancement.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/GameData/RocketSoundEnhancement/Plugins/RocketSoundEnhancement.dll -------------------------------------------------------------------------------- /GameData/RocketSoundEnhancement/Plugins/rse_bundle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/GameData/RocketSoundEnhancement/Plugins/rse_bundle -------------------------------------------------------------------------------- /GameData/RocketSoundEnhancement/RocketSoundEnhancement.version: -------------------------------------------------------------------------------- 1 | { 2 | "NAME":"Rocket Sound Enhancement", 3 | "URL":"https://raw.githubusercontent.com/ensou04/RocketSoundEnhancement/master/GameData/RocketSoundEnhancement/RocketSoundEnhancement.version", 4 | "DOWNLOAD":"https://github.com/ensou04/RocketSoundEnhancement/releases", 5 | "GITHUB": 6 | { 7 | "USERNAME":"ensou04", 8 | "REPOSITORY":"RocketSoundEnhancement", 9 | "ALLOW_PRE_RELEASE":false 10 | }, 11 | "VERSION": 12 | { 13 | "MAJOR":0, 14 | "MINOR":9, 15 | "PATCH":11, 16 | "BUILD":0 17 | }, 18 | "KSP_VERSION": 19 | { 20 | "MAJOR":1, 21 | "MINOR":12, 22 | "PATCH":3 23 | }, 24 | "KSP_VERSION_MIN":{ 25 | "MAJOR":1, 26 | "MINOR":12, 27 | "PATCH":3 28 | }, 29 | "KSP_VERSION_MAX":{ 30 | "MAJOR":1, 31 | "MINOR":12, 32 | "PATCH":99 33 | } 34 | } -------------------------------------------------------------------------------- /GameData/RocketSoundEnhancement/Settings.cfg: -------------------------------------------------------------------------------- 1 | RSE_SETTINGS 2 | { 3 | EnableAudioEffects = True 4 | DisableStagingSound = True 5 | ExteriorVolume = 1 6 | InteriorVolume = 1 7 | Colliders 8 | { 9 | default = concrete 10 | runway_lev1_v2 = dirt 11 | } 12 | CustomMixerRouting 13 | { 14 | AudioSources 15 | { 16 | MusicLogic = Ignore 17 | SoundtrackEditor = Ignore 18 | PartActionController(Clone) = Ignore 19 | } 20 | AudioClips 21 | { 22 | Chatterer/Sounds/AAE/effect/breathing = Interior 23 | Chatterer/Sounds/AAE/effect/airlock = Focus 24 | Chatterer/Sounds/AAE/wind/mario1298__weak-wind = Exterior 25 | } 26 | } 27 | LIMITER 28 | { 29 | EnableCustomLimiter = False 30 | AutoLimiter = 0.5 31 | Threshold = 0 32 | Gain = 0 33 | Attack = 10 34 | Release = 20 35 | } 36 | MUFFLER 37 | { 38 | ClampActiveVesselMuffling = False 39 | MufflerQuality = AirSim 40 | MachEffectsAmount = 0.9 41 | InternalMode = 1500 42 | ExternalMode = 1000 43 | DopplerFactor = 1 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /GameData/RocketSoundEnhancement/Textures/RSE_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/GameData/RocketSoundEnhancement/Textures/RSE_Icon.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rocket Sound Enhancement 2 | Rocket Sound Enhancement (RSE) is an Audio Plugin Framework Mod for [Kerbal Space Program](https://www.kerbalspaceprogram.com/) that offers modders advance sound effects features not available in the base game. 3 | It features a robust Layering System for use of multiple sounds just like in other games (eg: FMod). 4 | 5 | By itself, RSE only does Sound Limiting and Muffling. You'll need to download a Config Pack Mod in order to have new sounds in your game. 6 | If you release a mod that uses RSE, let me know so I can add it here in a list! 7 | 8 | ## Config and Sound Mods 9 | - [Rocket Sound Enhancement Default](https://github.com/ensou04/RocketSoundEnhancementDefault) (The Default Sound Library and Config) 10 | 11 | ## Features 12 | ### Master Audio Limiter/Compressor 13 | Sound Mastering that controls the overall loudness of the game with Adjustable Amount for different dynamics with the "Auto-Limiter" feature or you can tweak your own settings. 14 | 15 | ### Audio Muffler - Normal 16 | Mixer based Audio Muffler with Dedicated channels for Exterior Sounds, Focused Vessel and Interior while ignoring UI sounds like Music. 17 | 18 | ### Audio Muffler - AirSim & AirSim Lite 19 | An Audio Muffler that works on top of the regular muffler that takes into account the Mach Angle, Velocity and Distance of a Vessel with Sonic Booms Effects (provided by a Config Pack via ShipEffects). 20 | 21 | Parts with RSE Modules will simulate realistic sound attenuation over distance, comb-filtering, and distortion. Game Events like distant explosions will now sound muffled just like in real life. 22 | 23 | **AirSim Lite** is a version of **AirSim** that does similar effects without using sound filters. 24 | 25 | ### Additional Effects 26 | RSE also adds a more robust Doppler Effect. 27 | 28 | ### Part Modules 29 | Part Modules dedicated for assigning and controlling sound effects for Parts beyond what the regular stock audio can do. Including parts that didn't have any support for sounds before like Rotors, Wheels and Kerbal Jetpacks. 30 | - RSE_Engines 31 | - RSE_RCS 32 | - RSE_Wheels 33 | - RSE_RotorEngines 34 | - RSE_KerbalEVA (For Jetpacks) 35 | - RSE_Coupler 36 | - RSE_AUDIO (A Simpler non-layer EFFECTS Node version of RSE Modules for drop-in replacement of Stock AUDIO{} with full AirSim Support and a more direct Muffling Support.) 37 | 38 | ### ShipEffects - Physics based Sound Effects System 39 | - Add Sounds and assign it's Pitch or Volume to any physics control available for each Vessel. (air pressure, jerk, g-forces, etc) 40 | - Add Sonic Boom sound during Mach Angle Events. 41 | - Replace or Disable Staging Sound Effects. 42 | - ShipEffectsCollisions (Part Module) - Add Collision Sound Effects for different impact surfaces to any Part. 43 | 44 | ### Known Issues 45 | - Sound glitches and stuttering might occur in large part ships and more so when AirSim is enabled or when loading in-between scenes. 46 | - Stock sounds might be un-muffled for a single frame or two. Replacing AUDIO with RSE_AUDIO in Part's EFFECTS node via it's config fixes this issue. 47 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.Unity/ISettingsPanel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | 8 | namespace RocketSoundEnhancement.Unity 9 | { 10 | public enum AudioMufflerQuality 11 | { 12 | Normal = 0, 13 | AirSimLite = 1, 14 | AirSim = 2 15 | } 16 | public interface ISettingsPanel 17 | { 18 | float CanvasScale { get; } 19 | string Version { get; } 20 | 21 | bool EnableAudioEffects { get; set; } 22 | bool DisableStagingSound { get; set; } 23 | float InteriorVolume { get; set; } 24 | float ExteriorVolume { get; set; } 25 | 26 | AudioMufflerQuality MufflerQuality { get; set; } 27 | bool ClampActiveVesselMuffling { get; set; } 28 | float MufflerInternalMode { get; set; } 29 | float MufflerExternalMode { get; set; } 30 | float MachEffectsAmount { get; set; } 31 | float DopplerFactor { get; set; } 32 | 33 | 34 | bool EnableCustomLimiter { get; set; } 35 | float AutoLimiter { get; set; } 36 | float LimiterThreshold { get; set; } 37 | float LimiterGain { get; set; } 38 | float LimiterAttack { get; set; } 39 | float LimiterRelease { get; set; } 40 | 41 | void LoadSettings(); 42 | void SaveSettings(); 43 | void ClampToScreen(RectTransform rect); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.Unity/MathHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | 8 | namespace RocketSoundEnhancement.Unity 9 | { 10 | public static class MathHelper 11 | { 12 | public static float AmountToFrequency(float amount) 13 | { 14 | return Mathf.Round(11000 * (1 - Mathf.Log(Mathf.Lerp(0.1f, 10, amount), 10))); 15 | } 16 | 17 | public static float FrequencyToAmount(float frequency) 18 | { 19 | return Round(Mathf.InverseLerp(0.1f, 10, Mathf.Pow(10, 1 - (frequency / 11000))), 2); 20 | } 21 | 22 | public static float Round(float value, int decimals = 0) 23 | { 24 | return Mathf.Round(value * Mathf.Pow(10, decimals)) / Mathf.Pow(10, decimals); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.Unity/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("RocketSoundEnhancement.Unity")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RocketSoundEnhancement.Unity")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5dff0176-7ba8-49f4-8155-f5d9b37d7d3d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | [assembly: KSPAssembly("RocketSoundEnhancement.Unity", 1, 0)] 38 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.Unity/RSE_Panel.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.EventSystems; 3 | using UnityEngine.UI; 4 | 5 | namespace RocketSoundEnhancement.Unity 6 | { 7 | [RequireComponent(typeof(RectTransform))] 8 | public class RSE_Panel : MonoBehaviour, IDragHandler, IEndDragHandler, IPointerDownHandler 9 | { 10 | [SerializeField] private GameObject basicPanel; 11 | [SerializeField] private GameObject advancePanel; 12 | [SerializeField] private Text versionLabel; 13 | 14 | [SerializeField] private Toggle enableAudioEffects; 15 | [SerializeField] private Toggle disableStagingSound; 16 | 17 | [SerializeField] private Slider interiorVolume; 18 | [SerializeField] private Slider exteriorVolume; 19 | 20 | [SerializeField] private Toggle enableCustomLimiter; 21 | [SerializeField] private Slider autoLimiter; 22 | [SerializeField] private Slider limiterThreshold; 23 | [SerializeField] private Slider limiterGain; 24 | [SerializeField] private Slider limiterAttack; 25 | [SerializeField] private Slider limiterRelease; 26 | 27 | [SerializeField] private Toggle mufflerNormalQuality; 28 | [SerializeField] private Toggle mufflerAirSimLiteQuality; 29 | [SerializeField] private Toggle mufflerAirSimFullQuality; 30 | [SerializeField] private Toggle clampActiveVesselMuffling; 31 | [SerializeField] private Slider mufflerInternalMode; 32 | [SerializeField] private Slider mufflerExternalMode; 33 | [SerializeField] private Slider machEffectsAmount; 34 | [SerializeField] private Slider dopplerFactor; 35 | 36 | private RectTransform rectTransform; 37 | private ISettingsPanel settingsPanel; 38 | private bool initialized = false; 39 | private void Awake() 40 | { 41 | rectTransform = GetComponent(); 42 | } 43 | 44 | public void OnDrag(PointerEventData eventData) 45 | { 46 | rectTransform.anchoredPosition += eventData.delta / settingsPanel.CanvasScale; 47 | } 48 | 49 | public void OnEndDrag(PointerEventData eventData) 50 | { 51 | if (settingsPanel == null) return; 52 | 53 | settingsPanel.ClampToScreen(rectTransform); 54 | } 55 | 56 | public void OnPointerDown(PointerEventData eventData) 57 | { 58 | transform.SetAsLastSibling(); 59 | } 60 | 61 | public void Initialize(ISettingsPanel _settingsPanel) 62 | { 63 | settingsPanel = _settingsPanel; 64 | versionLabel.text = settingsPanel.Version; 65 | 66 | enableAudioEffects.isOn = settingsPanel.EnableAudioEffects; 67 | disableStagingSound.isOn = settingsPanel.DisableStagingSound; 68 | enableCustomLimiter.isOn = settingsPanel.EnableCustomLimiter; 69 | 70 | interiorVolume.value = settingsPanel.InteriorVolume; 71 | exteriorVolume.value = settingsPanel.ExteriorVolume; 72 | 73 | autoLimiter.value = settingsPanel.AutoLimiter; 74 | limiterThreshold.value = settingsPanel.LimiterThreshold; 75 | limiterGain.value = settingsPanel.LimiterGain; 76 | limiterAttack.value = settingsPanel.LimiterAttack; 77 | limiterRelease.value = settingsPanel.LimiterRelease; 78 | 79 | mufflerNormalQuality.isOn = settingsPanel.MufflerQuality == AudioMufflerQuality.Normal; 80 | mufflerAirSimLiteQuality.isOn = settingsPanel.MufflerQuality == AudioMufflerQuality.AirSimLite; 81 | mufflerAirSimFullQuality.isOn = settingsPanel.MufflerQuality == AudioMufflerQuality.AirSim; 82 | clampActiveVesselMuffling.isOn = settingsPanel.ClampActiveVesselMuffling; 83 | 84 | mufflerExternalMode.value = MathHelper.FrequencyToAmount(settingsPanel.MufflerExternalMode); 85 | mufflerInternalMode.value = MathHelper.FrequencyToAmount(settingsPanel.MufflerInternalMode); 86 | machEffectsAmount.value = settingsPanel.MachEffectsAmount; 87 | dopplerFactor.value = settingsPanel.DopplerFactor; 88 | 89 | initialized = true; 90 | } 91 | public void ToggleAdvanceSettings(bool toggle) 92 | { 93 | if (basicPanel == null || advancePanel == null) return; 94 | 95 | basicPanel.SetActive(!toggle); 96 | advancePanel.SetActive(toggle); 97 | } 98 | public void OnAudioEffecstEnabled(bool isOn) 99 | { 100 | if (!initialized) return; 101 | 102 | settingsPanel.EnableAudioEffects = isOn; 103 | } 104 | public void OnDisableStagingSound(bool isOn) 105 | { 106 | if (!initialized) return; 107 | settingsPanel.DisableStagingSound = isOn; 108 | } 109 | public void OnInteriorVolume(float value) 110 | { 111 | if (!initialized) return; 112 | settingsPanel.InteriorVolume = MathHelper.Round(value, 2); 113 | } 114 | public void OnExteriorVolume(float value) 115 | { 116 | if (!initialized) return; 117 | settingsPanel.ExteriorVolume = MathHelper.Round(value, 2); 118 | } 119 | public void OnEnableCustomLimiter(bool isOn) 120 | { 121 | if (!initialized) return; 122 | settingsPanel.EnableCustomLimiter = isOn; 123 | } 124 | public void OnAutoLimiter(float value) 125 | { 126 | if (!initialized) return; 127 | settingsPanel.AutoLimiter = MathHelper.Round(value, 2); 128 | } 129 | public void OnLimiterThreshold(float value) 130 | { 131 | if (!initialized) return; 132 | settingsPanel.LimiterThreshold = MathHelper.Round(value, 2); 133 | } 134 | public void OnLimiterGain(float value) 135 | { 136 | if (!initialized) return; 137 | settingsPanel.LimiterGain = MathHelper.Round(value, 2); 138 | } 139 | public void OnLimiterAttack(float value) 140 | { 141 | if (!initialized) return; 142 | settingsPanel.LimiterAttack = MathHelper.Round(value, 2); 143 | } 144 | public void OnLimiterRelease(float value) 145 | { 146 | if (!initialized) return; 147 | settingsPanel.LimiterRelease = MathHelper.Round(value, 2); 148 | } 149 | public void OnMufflerQuality(int qualityIndex) 150 | { 151 | if(!initialized) return; 152 | switch (qualityIndex) 153 | { 154 | case 0: 155 | settingsPanel.MufflerQuality = AudioMufflerQuality.Normal; 156 | break; 157 | case 1: 158 | settingsPanel.MufflerQuality = AudioMufflerQuality.AirSimLite; 159 | break; 160 | case 2: 161 | settingsPanel.MufflerQuality = AudioMufflerQuality.AirSim; 162 | break; 163 | default: 164 | settingsPanel.MufflerQuality = AudioMufflerQuality.Normal; 165 | break; 166 | } 167 | } 168 | public void OnClampActiveVesselMuffling(bool isOn) 169 | { 170 | if (!initialized) return; 171 | settingsPanel.ClampActiveVesselMuffling = isOn; 172 | } 173 | public void OnMufflerInternalMode(float value) 174 | { 175 | if (!initialized) return; 176 | settingsPanel.MufflerInternalMode = MathHelper.AmountToFrequency(value); 177 | } 178 | public void OnMufflerExternalMode(float value) 179 | { 180 | if (!initialized) return; 181 | settingsPanel.MufflerExternalMode = MathHelper.AmountToFrequency(value); 182 | } 183 | public void OnMachEffectsAmount(float value) 184 | { 185 | if (!initialized) return; 186 | settingsPanel.MachEffectsAmount = MathHelper.Round(value, 2); 187 | } 188 | public void OnDopplerFactor(float value) 189 | { 190 | if (!initialized) return; 191 | settingsPanel.DopplerFactor = MathHelper.Round(value, 2); 192 | } 193 | public void OnReload() 194 | { 195 | if (!initialized) return; 196 | 197 | initialized = false; 198 | settingsPanel.LoadSettings(); 199 | Initialize(settingsPanel); 200 | } 201 | public void OnSave() 202 | { 203 | if (!initialized) return; 204 | settingsPanel.SaveSettings(); 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.Unity/RocketSoundEnhancement.Unity.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5DFF0176-7BA8-49F4-8155-F5D9B37D7D3D} 8 | Library 9 | Properties 10 | RocketSoundEnhancement.Unity 11 | RocketSoundEnhancement.Unity 12 | v4.7.2 13 | 512 14 | true 15 | 16 | 17 | true 18 | portable 19 | false 20 | ..\..\GameData\RocketSoundEnhancement\Plugins\ 21 | TRACE;DEBUG;ENABLE_PROFILER;DEVELOPMENT 22 | prompt 23 | 4 24 | 25 | 26 | portable 27 | true 28 | ..\..\GameData\RocketSoundEnhancement\Plugins\ 29 | TRACE 30 | prompt 31 | 4 32 | true 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.dll 45 | False 46 | 47 | 48 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.CoreModule.dll 49 | False 50 | 51 | 52 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.UI.dll 53 | False 54 | 55 | 56 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.UIModule.dll 57 | False 58 | 59 | 60 | False 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.Unity/SliderValueDisplay.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEngine.UI; 3 | 4 | namespace RocketSoundEnhancement.Unity 5 | { 6 | [RequireComponent(typeof(Slider))] 7 | public class SliderValueDisplay : MonoBehaviour 8 | { 9 | public string NumberFormat = string.Empty; 10 | public float Multiplier = 1.0f; 11 | [SerializeField] Slider slider; 12 | [SerializeField] Text label; 13 | public void Awake() 14 | { 15 | if (slider == null) slider = GetComponent(); 16 | 17 | if (label == null) return; 18 | 19 | label.text = (slider.value * Multiplier).ToString("0") + NumberFormat; 20 | slider.onValueChanged.AddListener(x => 21 | { 22 | label.text = (x * Multiplier).ToString("0") + NumberFormat; 23 | }); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32526.322 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RocketSoundEnhancement", "RocketSoundEnhancement\RocketSoundEnhancement.csproj", "{BBC72A52-EE4F-4DC0-9845-4350A54AC1CD}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RocketSoundEnhancement.Unity", "RocketSoundEnhancement.Unity\RocketSoundEnhancement.Unity.csproj", "{5DFF0176-7BA8-49F4-8155-F5D9B37D7D3D}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{23E94561-E5A6-43BE-90D8-A93E167D6A5F}" 11 | ProjectSection(SolutionItems) = preProject 12 | ..\changelog.md = ..\changelog.md 13 | ..\GameData\RocketSoundEnhancement\RocketSoundEnhancement.version = ..\GameData\RocketSoundEnhancement\RocketSoundEnhancement.version 14 | ..\GameData\RocketSoundEnhancement\Settings.cfg = ..\GameData\RocketSoundEnhancement\Settings.cfg 15 | EndProjectSection 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {BBC72A52-EE4F-4DC0-9845-4350A54AC1CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {BBC72A52-EE4F-4DC0-9845-4350A54AC1CD}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {BBC72A52-EE4F-4DC0-9845-4350A54AC1CD}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {BBC72A52-EE4F-4DC0-9845-4350A54AC1CD}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {5DFF0176-7BA8-49F4-8155-F5D9B37D7D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {5DFF0176-7BA8-49F4-8155-F5D9B37D7D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {5DFF0176-7BA8-49F4-8155-F5D9B37D7D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {5DFF0176-7BA8-49F4-8155-F5D9B37D7D3D}.Release|Any CPU.Build.0 = Release|Any CPU 31 | EndGlobalSection 32 | GlobalSection(SolutionProperties) = preSolution 33 | HideSolutionNode = FALSE 34 | EndGlobalSection 35 | GlobalSection(ExtensibilityGlobals) = postSolution 36 | SolutionGuid = {690879CC-0199-4D04-9D65-64CE9A442824} 37 | EndGlobalSection 38 | EndGlobal 39 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/AudioFilters/AirSimulationFilter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using UnityEngine; 4 | using UnityEngine.Profiling; 5 | 6 | namespace RocketSoundEnhancement.AudioFilters 7 | { 8 | public enum AirSimulationUpdate 9 | { 10 | Full, 11 | Basic, 12 | None 13 | } 14 | 15 | [RequireComponent(typeof(AudioBehaviour))] 16 | public class AirSimulationFilter : MonoBehaviour 17 | { 18 | // Simulation Settings 19 | public bool EnableCombFilter 20 | { 21 | get => _enableCombFilter; 22 | set 23 | { 24 | if (!value) 25 | { 26 | buffer = null; 27 | } 28 | 29 | _enableCombFilter = value; 30 | 31 | AllocateCombFilterBuffer(); 32 | } 33 | } 34 | bool _enableCombFilter; 35 | 36 | public bool EnableLowpassFilter { get; set; } 37 | public bool EnableDistortionFilter { get; set; } 38 | public AirSimulationUpdate SimulationUpdate { get; set; } 39 | public float MaxDistance { get; set; } = 500; 40 | public float FarLowpass { get; set; } 41 | public float MaxCombDelay { get; set; } 42 | public float MaxCombMix { get; set; } 43 | public float MaxDistortion { get; set; } 44 | public float AngleHighpass { get; set; } 45 | 46 | 47 | // Simulation Inputs 48 | public float Distance = 0; 49 | public float Mach = 0; 50 | public float Angle = 0; 51 | public float MachAngle = 90; 52 | public float MachPass = 1; 53 | 54 | // Filter Controls 55 | public float CombDelay = 0; 56 | public float CombMix = 0; 57 | public float LowpassFrequency = 22000; 58 | public float HighPassFrequency = 0; 59 | public float Distortion = 0; 60 | 61 | private int sampleRate; 62 | private double delaySamples; 63 | 64 | private float distanceLog, machVelocityClamped, angleAbsolute, anglePositive, machPass; 65 | 66 | private AudioDistortionFilter distortionFilter; 67 | 68 | private void Awake() 69 | { 70 | sampleRate = AudioSettings.outputSampleRate; 71 | 72 | if (EnableDistortionFilter) 73 | { 74 | distortionFilter = gameObject.AddComponent(); 75 | distortionFilter.enabled = enabled; 76 | } 77 | } 78 | 79 | void Start() 80 | { 81 | AllocateCombFilterBuffer(); 82 | } 83 | 84 | private void LateUpdate() 85 | { 86 | UpdateFilters(); 87 | } 88 | 89 | public IEnumerator UpdateDistance() 90 | { 91 | Distance = Vector3.Distance(CameraManager.GetCurrentCamera().transform.position, transform.position); 92 | yield return null; 93 | } 94 | 95 | private void UpdateFilters() 96 | { 97 | if (SimulationUpdate != AirSimulationUpdate.None) 98 | { 99 | distanceLog = (1 - Mathf.Log10(Mathf.Lerp(0.1f, 10, Mathf.Clamp01(Distance / MaxDistance)))) * 0.5f; 100 | anglePositive = Mathf.Clamp01((Angle - MachAngle) / MachAngle); 101 | 102 | if (SimulationUpdate == AirSimulationUpdate.Full) 103 | { 104 | machPass = Mathf.Clamp01(MachPass / Mathf.Lerp(0.1f, 1f, Distance / 100)); 105 | machVelocityClamped = Mathf.Clamp01(Mach); 106 | angleAbsolute = 1 - Mathf.Clamp01(Angle / 180); 107 | } 108 | 109 | if (EnableCombFilter) 110 | { 111 | CombDelay = MaxCombDelay * distanceLog; 112 | CombMix = Mathf.Lerp(MaxCombMix, 0, distanceLog); 113 | } 114 | 115 | if (EnableLowpassFilter) 116 | { 117 | LowpassFrequency = Mathf.Lerp(FarLowpass, 22000, distanceLog); 118 | HighPassFrequency = AngleHighpass * anglePositive; 119 | 120 | if (SimulationUpdate == AirSimulationUpdate.Full) 121 | { 122 | LowpassFrequency *= machPass; 123 | } 124 | } 125 | 126 | if (EnableDistortionFilter) 127 | { 128 | if (SimulationUpdate == AirSimulationUpdate.Full) 129 | { 130 | Distortion = Mathf.Lerp(MaxDistortion, (MaxDistortion * 0.5f) * machVelocityClamped, distanceLog) * angleAbsolute; 131 | } 132 | else 133 | { 134 | Distortion = Mathf.Lerp(MaxDistortion, 0, distanceLog); 135 | } 136 | } 137 | } 138 | 139 | #region Combfilter Update 140 | if (EnableCombFilter) 141 | { 142 | delaySamples = Mathf.FloorToInt(Mathf.Min(CombDelay * sampleRate / 1000, 500000)); 143 | } 144 | #endregion 145 | 146 | #region LowpassHighpassFilter Update 147 | if (EnableLowpassFilter) 148 | { 149 | float clp = 1.0f / Mathf.Tan(Mathf.PI * Mathf.Clamp(LowpassFrequency, 10, 22000) / sampleRate); 150 | 151 | float r = Mathf.Sqrt(2); 152 | alp[0] = 1.0f / (1.0f + r * clp + clp * clp); 153 | alp[1] = 2 * alp[0]; 154 | alp[2] = alp[0]; 155 | alp[3] = 2.0f * (1.0f - clp * clp) * alp[0]; 156 | alp[4] = (1.0f - r * clp + clp * clp) * alp[0]; 157 | 158 | if (AngleHighpass > 0) 159 | { 160 | float chp = Mathf.Tan(Mathf.PI * Mathf.Clamp(HighPassFrequency, 0, 22000) / sampleRate); 161 | chp = (chp + r) * chp; 162 | ahp[0] = 1.0f / (1.0f + chp); 163 | ahp[1] = (1.0f - chp); 164 | } 165 | } 166 | #endregion 167 | 168 | #region Waveshaper Update 169 | if (EnableDistortionFilter && distortionFilter != null) 170 | { 171 | distortionFilter.distortionLevel = Mathf.Clamp01(Distortion); 172 | } 173 | #endregion 174 | } 175 | 176 | private void OnAudioFilterRead(float[] data, int channels) 177 | { 178 | for (int i = 0; i < data.Length; i++) 179 | { 180 | if (EnableCombFilter) 181 | { 182 | data[i] = CombFilter(data[i]); 183 | } 184 | if (EnableLowpassFilter) 185 | { 186 | data[i] = LowpassHighpassFilter(Quantize(data[i]), i); 187 | } 188 | } 189 | } 190 | 191 | //removes denormal numbers that causes very high cpu 192 | private float dn = 1e-18f; 193 | private float Quantize(float input) 194 | { 195 | dn = -dn; 196 | return (+input) + dn; 197 | } 198 | 199 | #region Comb Filter 200 | private float[] buffer; 201 | private int counter = 0; 202 | private float CombFilter(float input) 203 | { 204 | int delay = counter - (int)delaySamples; 205 | delay = delay > buffer.Length || delay < 0 ? 0 : delay; 206 | 207 | buffer[counter] = input; 208 | float output = buffer[delay] * CombMix; 209 | 210 | counter++; 211 | if (counter >= buffer.Length) 212 | { 213 | counter = 0; 214 | } 215 | 216 | return input + output; 217 | } 218 | #endregion 219 | 220 | #region LowpassHighpass Filter 221 | // source: https://www.musicdsp.org/en/latest/Filters/38-lp-and-hp-filter.html 222 | float[] alp = new float[5]; 223 | float[] inlpl = new float[2], inlpr = new float[2]; 224 | float[] outlpl = new float[2], outlpr = new float[2]; 225 | 226 | float[] ahp = new float[2]; 227 | float[] inhpl = new float[2], inhpr = new float[2]; 228 | float[] outhpl = new float[2], outhpr = new float[2]; 229 | private float LowpassHighpassFilter(float input, int index) 230 | { 231 | float outputlp, outputhp; 232 | 233 | if (index % 2 == 0) 234 | { 235 | outputlp = alp[0] * input + alp[1] * inlpl[0] + alp[2] * inlpl[1] - alp[3] * outlpl[0] - alp[4] * outlpl[1]; 236 | 237 | inlpl[1] = inlpl[0]; 238 | inlpl[0] = input; 239 | 240 | outlpl[1] = outlpl[0]; 241 | outlpl[0] = outputlp; 242 | 243 | if (AngleHighpass > 0) 244 | { 245 | outputhp = (ahp[0] * outhpl[1] + outputlp - inhpl[1]) * ahp[1]; 246 | 247 | inhpl[1] = inhpl[0]; 248 | inhpl[0] = outputlp; 249 | 250 | outhpl[1] = outhpl[0]; 251 | outhpl[0] = outputhp; 252 | 253 | return outputhp; 254 | } 255 | 256 | return outputlp; 257 | } 258 | 259 | outputlp = alp[0] * input + alp[1] * inlpr[0] + alp[2] * inlpr[1] - alp[3] * outlpr[0] - alp[4] * outlpr[1]; 260 | 261 | inlpr[1] = inlpr[0]; 262 | inlpr[0] = input; 263 | 264 | outlpr[1] = outlpr[0]; 265 | outlpr[0] = outputlp; 266 | 267 | if (AngleHighpass > 0) 268 | { 269 | outputhp = (ahp[0] * outhpr[1] + outputlp - inhpr[1]) * ahp[1]; 270 | 271 | inhpr[1] = inhpr[0]; 272 | inhpr[0] = outputlp; 273 | 274 | outhpr[1] = outhpr[0]; 275 | outhpr[0] = outputhp; 276 | 277 | return outputhp; 278 | } 279 | 280 | return outputlp; 281 | } 282 | #endregion 283 | 284 | private void OnDisable() 285 | { 286 | if (distortionFilter != null) distortionFilter.enabled = false; 287 | 288 | buffer = null; 289 | 290 | Array.Clear(inlpl, 0, inlpl.Length); 291 | Array.Clear(inlpr, 0, inlpr.Length); 292 | Array.Clear(outlpl, 0, outlpl.Length); 293 | Array.Clear(outlpl, 0, outlpl.Length); 294 | 295 | Array.Clear(inhpl, 0, inhpl.Length); 296 | Array.Clear(inhpr, 0, inhpr.Length); 297 | Array.Clear(outhpl, 0, outhpl.Length); 298 | Array.Clear(outhpr, 0, outhpr.Length); 299 | 300 | counter = 0; 301 | 302 | } 303 | 304 | private void OnEnable() 305 | { 306 | if (distortionFilter != null) distortionFilter.enabled = true; 307 | 308 | AllocateCombFilterBuffer(); 309 | } 310 | 311 | void AllocateCombFilterBuffer() 312 | { 313 | if (HighLogic.LoadedScene != GameScenes.LOADING && EnableCombFilter && buffer == null) 314 | { 315 | buffer = new float[500000]; 316 | } 317 | } 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/AudioUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using RocketSoundEnhancement.AudioFilters; 5 | using UnityEngine; 6 | using UnityEngine.Audio; 7 | 8 | namespace RocketSoundEnhancement 9 | { 10 | public enum CollidingObject 11 | { 12 | Dirt, 13 | Concrete, 14 | Vessel, 15 | KerbalEVA 16 | } 17 | 18 | public enum FXChannel 19 | { 20 | Exterior, 21 | Interior 22 | } 23 | 24 | public enum MixerGroup 25 | { 26 | Ignore, 27 | Exterior, 28 | Interior, 29 | Focus 30 | } 31 | 32 | public enum PhysicsControl 33 | { 34 | ACCELERATION, 35 | JERK, 36 | AIRSPEED, 37 | GROUNDSPEED, 38 | SONICBOOM, 39 | DYNAMICPRESSURE, 40 | THRUST, 41 | REENTRYHEAT, 42 | None 43 | } 44 | 45 | public class SoundLayer 46 | { 47 | public string name; 48 | public string data; 49 | public AudioClip[] audioClips; 50 | public FXChannel channel; 51 | public bool loop; 52 | public bool loopAtRandom; 53 | public bool spool; 54 | public float spoolSpeed; 55 | public float spoolIdle; 56 | public float spread; 57 | public float maxDistance; 58 | public AudioRolloffMode rolloffMode; 59 | public FXCurve volume; 60 | public FXCurve pitch; 61 | public FloatCurve volumeFC; 62 | public FloatCurve pitchFC; 63 | public FXCurve massToVolume; 64 | public FXCurve massToPitch; 65 | public FloatCurve rollOffCurve; 66 | } 67 | 68 | public static class AudioUtility 69 | { 70 | public static AnimationCurve SmoothControl = AnimationCurve.EaseInOut(0f, 0.04f, 1f, 1f); 71 | public static string RSETag = "RSE"; 72 | 73 | public static ConfigNode GetConfigNode(string partInfoName, string moduleName, string moduleID = "") 74 | { 75 | var configs = GameDatabase.Instance.GetConfigs("PART"); 76 | 77 | foreach (var configNode in configs) 78 | { 79 | if (configNode.name.Replace("_", ".") == partInfoName) 80 | { 81 | if (moduleID == "") 82 | { 83 | return Array.FindAll(configNode.config.GetNodes("MODULE"), x => x.GetValue("name") == moduleName).FirstOrDefault(); 84 | } 85 | else 86 | { 87 | return Array.FindAll(configNode.config.GetNodes("MODULE"), x => x.GetValue("name") == moduleName && x.GetValue("moduleID") == moduleID).FirstOrDefault(); 88 | } 89 | } 90 | } 91 | return null; 92 | } 93 | 94 | public static List CreateSoundLayerGroup(ConfigNode[] groupNodes) 95 | { 96 | var group = new List(); 97 | foreach (var node in groupNodes) 98 | { 99 | group.Add(CreateSoundLayer(node)); 100 | } 101 | return group; 102 | } 103 | 104 | public static SoundLayer CreateSoundLayer(ConfigNode node) 105 | { 106 | var soundLayer = new SoundLayer { name = node.GetValue("name") }; 107 | 108 | if (node.HasValue("audioClip")) 109 | { 110 | var clips = new List(); 111 | var clipValues = node.GetValues("audioClip"); 112 | for (int i = 0; i < clipValues.Length; i++) 113 | { 114 | string value = clipValues[i]; 115 | AudioClip clip = GameDatabase.Instance.GetAudioClip(value); 116 | if (clip == null) 117 | { 118 | Debug.Log($"[RSE]: Cannot find AudioClip [{value}] in SoundLayer [{soundLayer.name}]"); 119 | continue; 120 | } 121 | 122 | clips.Add(clip); 123 | } 124 | soundLayer.audioClips = clips.ToArray(); 125 | } 126 | 127 | if(soundLayer.audioClips == null || soundLayer.audioClips.Length == 0) 128 | { 129 | Debug.Log($"[RSE]: [{soundLayer.name}] audioClip is empty."); 130 | } 131 | 132 | if (!node.TryGetValue("loopAtRandom", ref soundLayer.loopAtRandom)) { soundLayer.loopAtRandom = true; } 133 | node.TryGetValue("loop", ref soundLayer.loop); 134 | node.TryGetValue("spool", ref soundLayer.spool); 135 | node.TryGetValue("spoolSpeed", ref soundLayer.spoolSpeed); 136 | node.TryGetValue("spoolIdle", ref soundLayer.spoolIdle); 137 | node.TryGetValue("spread", ref soundLayer.spread); 138 | node.TryGetEnum("channel", ref soundLayer.channel, FXChannel.Exterior); 139 | node.TryGetEnum("rolloffMode", ref soundLayer.rolloffMode, AudioRolloffMode.Logarithmic); 140 | if (!node.TryGetValue("maxDistance", ref soundLayer.maxDistance)) soundLayer.maxDistance = 500; 141 | 142 | if (node.HasNode("rolloffCurve")) 143 | { 144 | soundLayer.rollOffCurve = new FloatCurve(); 145 | soundLayer.rollOffCurve.Load(node.GetNode("rolloffCurve")); 146 | soundLayer.rollOffCurve.Curve.preWrapMode = WrapMode.ClampForever; 147 | soundLayer.rollOffCurve.Curve.postWrapMode = WrapMode.ClampForever; 148 | } 149 | 150 | soundLayer.volume = new FXCurve("volume", 1); 151 | soundLayer.pitch = new FXCurve("pitch", 1); 152 | soundLayer.volume.Load("volume", node); 153 | soundLayer.pitch.Load("pitch", node); 154 | 155 | if (node.HasNode("volumeFC")) 156 | { 157 | soundLayer.volumeFC = new FloatCurve(); 158 | soundLayer.volumeFC.Load(node.GetNode("volumeFC")); 159 | soundLayer.volumeFC.Curve.preWrapMode = WrapMode.ClampForever; 160 | soundLayer.volumeFC.Curve.postWrapMode = WrapMode.ClampForever; 161 | } 162 | 163 | if (node.HasNode("pitchFC")) 164 | { 165 | soundLayer.pitchFC = new FloatCurve(); 166 | soundLayer.pitchFC.Load(node.GetNode("pitchFC")); 167 | soundLayer.pitchFC.Curve.preWrapMode = WrapMode.ClampForever; 168 | soundLayer.pitchFC.Curve.postWrapMode = WrapMode.ClampForever; 169 | } 170 | 171 | if (node.HasValue("massToVolume")) 172 | { 173 | soundLayer.massToVolume = new FXCurve("massToVolume", 1); 174 | soundLayer.massToVolume.Load("massToVolume", node); 175 | } 176 | 177 | if (node.HasValue("massToPitch")) 178 | { 179 | soundLayer.massToPitch = new FXCurve("massToPitch", 1); 180 | soundLayer.massToPitch.Load("massToPitch", node); 181 | } 182 | 183 | soundLayer.data = node.HasValue("data") ? node.GetValue("data") : ""; 184 | 185 | return soundLayer; 186 | } 187 | public static AudioSource CreateSource(GameObject sourceGameObject, FXCurve volume, FXCurve pitch, bool loop = false, float spread = 0.0f) 188 | { 189 | var source = sourceGameObject.AddComponent(); 190 | source.playOnAwake = false; 191 | source.volume = volume; 192 | source.pitch = pitch; 193 | source.loop = loop; 194 | source.spatialBlend = 1; 195 | source.rolloffMode = AudioRolloffMode.Logarithmic; 196 | 197 | if (spread > 0) { source.SetCustomCurve(AudioSourceCurveType.Spread, AnimationCurve.Linear(0, spread, 1, 0)); } 198 | 199 | return source; 200 | } 201 | 202 | public static AudioSource CreateSource(GameObject sourceGameObject, SoundLayer soundLayer) 203 | { 204 | var source = sourceGameObject.AddComponent(); 205 | source.playOnAwake = false; 206 | source.volume = soundLayer.volume; 207 | source.pitch = soundLayer.pitch; 208 | source.loop = soundLayer.loop; 209 | source.spatialBlend = 1; 210 | 211 | source.rolloffMode = soundLayer.rolloffMode; 212 | if (soundLayer.rolloffMode > AudioRolloffMode.Logarithmic) { source.maxDistance = soundLayer.maxDistance; } 213 | if (soundLayer.rolloffMode == AudioRolloffMode.Custom && soundLayer.rollOffCurve != null) 214 | { 215 | source.SetCustomCurve(AudioSourceCurveType.CustomRolloff, soundLayer.rollOffCurve.Curve); 216 | } 217 | 218 | if (soundLayer.spread > 0) { source.SetCustomCurve(AudioSourceCurveType.Spread, AnimationCurve.Linear(0, soundLayer.spread, 1, 0)); } 219 | 220 | return source; 221 | } 222 | 223 | public static CollidingObject GetCollidingObject(GameObject gameObject) 224 | { 225 | var part = Part.FromGO(gameObject); 226 | if (part) 227 | { 228 | if (part.GetComponent()) return CollidingObject.Dirt; 229 | if (part.isVesselEVA) return CollidingObject.KerbalEVA; 230 | return CollidingObject.Vessel; 231 | } 232 | if (gameObject.tag.ToLower() != "untagged") 233 | { 234 | if (Settings.CollisionData.ContainsKey(gameObject.name)) return Settings.CollisionData[gameObject.name]; 235 | if (Settings.CollisionData.ContainsKey("default")) return Settings.CollisionData["default"]; 236 | } 237 | return CollidingObject.Dirt; 238 | } 239 | 240 | public static GameObject CreateAudioParent(Part part, string partName) 241 | { 242 | var audioParent = part.gameObject.GetChild($"{RSETag}_partName"); 243 | if (!audioParent) 244 | { 245 | audioParent = new GameObject(partName); 246 | audioParent.transform.parent = part.transform; 247 | audioParent.transform.localRotation = Quaternion.Euler(0, 0, 0); 248 | audioParent.transform.localPosition = Vector3.zero; 249 | } 250 | return audioParent; 251 | } 252 | 253 | public static AudioMixerGroup GetMixerGroup(MixerGroup group) 254 | { 255 | if (Settings.EnableAudioEffects) 256 | { 257 | switch (group) 258 | { 259 | case MixerGroup.Exterior: return RocketSoundEnhancement.ExteriorMixer; 260 | case MixerGroup.Interior: return RocketSoundEnhancement.InteriorMixer; 261 | case MixerGroup.Focus: return RocketSoundEnhancement.FocusMixer; 262 | default: return null; 263 | } 264 | } 265 | return null; 266 | } 267 | 268 | public static AudioMixerGroup GetMixerGroup(FXChannel channel, bool isActiveVessel) 269 | { 270 | if (Settings.EnableAudioEffects) 271 | { 272 | switch (channel) 273 | { 274 | case FXChannel.Interior: return RocketSoundEnhancement.InteriorMixer; 275 | case FXChannel.Exterior: return isActiveVessel ? RocketSoundEnhancement.FocusMixer : RocketSoundEnhancement.ExteriorMixer; 276 | } 277 | } 278 | return null; 279 | } 280 | 281 | public static void PlayAtChannel(AudioSource source, FXChannel channel, bool isActiveVessel, bool loop = false, float volumeScale = 1.0f, AudioClip audioclip = null) 282 | { 283 | if (source == null || !source.isActiveAndEnabled) return; 284 | 285 | if (TimeWarp.CurrentRate > TimeWarp.fetch.physicsWarpRates.Last()) source.volume = 0; 286 | 287 | source.outputAudioMixerGroup = GetMixerGroup(channel, isActiveVessel); 288 | switch (channel) 289 | { 290 | case FXChannel.Exterior: 291 | source.volume *= Settings.ExteriorVolume; 292 | break; 293 | case FXChannel.Interior: 294 | source.volume *= Settings.InteriorVolume; 295 | source.mute = !isActiveVessel || !InternalCamera.Instance.isActive; 296 | break; 297 | } 298 | 299 | if (!loop) 300 | { 301 | source.PlayOneShot(audioclip, volumeScale); 302 | return; 303 | } 304 | 305 | if (loop && !source.isPlaying) source.Play(); 306 | } 307 | } 308 | } -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/EffectBehaviours/RSE_AudioEffects.cs: -------------------------------------------------------------------------------- 1 | using RocketSoundEnhancement.AudioFilters; 2 | using RocketSoundEnhancement.Unity; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using UnityEngine; 10 | 11 | namespace RocketSoundEnhancement.EffectBehaviours 12 | { 13 | [EffectDefinition("RSE_AUDIO")] 14 | public class RSE_AudioEffects : EffectBehaviour 15 | { 16 | [Persistent] public AudioFX.AudioChannel channel; 17 | [Persistent] public string clip = ""; 18 | [Persistent] public bool loop; 19 | [Persistent] public bool loopAtRandom = true; 20 | [Persistent] public float spread; 21 | 22 | [Persistent] public bool EnableCombFilter = false; 23 | [Persistent] public bool EnableLowpassFilter = false; 24 | [Persistent] public bool EnableDistortionFilter = false; 25 | [Persistent] public float DopplerFactor = 0.5f; 26 | [Persistent] public AirSimulationUpdate AirSimUpdateMode = AirSimulationUpdate.Full; 27 | [Persistent] public float FarLowpass = Settings.AirSimFarLowpass; 28 | [Persistent] public float MaxCombDelay = Settings.AirSimMaxCombDelay; 29 | [Persistent] public float MaxCombMix = Settings.AirSimMaxCombMix; 30 | [Persistent] public float MaxDistortion = Settings.AirSimMaxDistortion; 31 | [Persistent] public float AngleHighpass = 0; 32 | 33 | public FXCurve volume = new FXCurve("volume", 1f); 34 | public FXCurve pitch = new FXCurve("pitch", 1f); 35 | 36 | public System.Random random = new System.Random(); 37 | public GameObject audioParent; 38 | public AudioSource audioSource; 39 | public AirSimulationFilter airSimFilter; 40 | public AudioClip audioClip; 41 | 42 | private bool isActiveVessel; 43 | private bool markForPlay; 44 | private bool playOneShot; 45 | private int slowUpdate; 46 | private float loopRandomStart; 47 | private float control; 48 | private float distance; 49 | private float lastDistance; 50 | private float doppler = 1; 51 | private float angle = 0; 52 | private float machPass = 1; 53 | private float mach = 0; 54 | private float machAngle = 0; 55 | 56 | public override void OnInitialize() 57 | { 58 | if (audioParent != null) 59 | { 60 | Debug.LogWarningFormat("[RSE] AudioEffect named {0} already has an audioParent", effectName); 61 | } 62 | if (audioSource != null) 63 | { 64 | Debug.LogWarningFormat("[RSE] AudioEffect named {0} already has an audioSource", effectName); 65 | } 66 | 67 | audioParent = new GameObject($"{AudioUtility.RSETag}_{this.effectName}"); 68 | audioParent.transform.SetParent(transform, false); 69 | audioParent.transform.localRotation = Quaternion.Euler(0, 0, 0); 70 | audioParent.transform.localPosition = Vector3.zero; 71 | 72 | audioClip = GameDatabase.Instance.GetAudioClip(clip); 73 | while (audioClip == null) 74 | { 75 | clip = Path.ChangeExtension(clip, null); 76 | audioClip = GameDatabase.Instance.GetAudioClip(clip); 77 | if (audioClip == null) 78 | { 79 | Debug.Log($"[RSE]: RSE_AUDIO: {clip} clip cannot be found"); 80 | break; 81 | } 82 | } 83 | 84 | audioSource = AudioUtility.CreateSource(audioParent, volume, pitch, loop, spread); 85 | audioSource.enabled = false; 86 | audioSource.clip = audioClip; 87 | 88 | if (hostPart != null && (EnableCombFilter || EnableLowpassFilter || EnableDistortionFilter)) 89 | { 90 | airSimFilter = audioParent.AddComponent(); 91 | airSimFilter.enabled = false; 92 | 93 | airSimFilter.EnableCombFilter = EnableCombFilter; 94 | airSimFilter.EnableLowpassFilter = EnableLowpassFilter; 95 | airSimFilter.EnableDistortionFilter = EnableDistortionFilter; 96 | airSimFilter.SimulationUpdate = AirSimUpdateMode; 97 | 98 | airSimFilter.MaxDistance = Settings.AirSimMaxDistance; 99 | airSimFilter.FarLowpass = FarLowpass; 100 | airSimFilter.MaxCombDelay = MaxCombDelay; 101 | airSimFilter.MaxCombMix = MaxCombMix; 102 | airSimFilter.MaxDistortion = MaxDistortion; 103 | airSimFilter.AngleHighpass = AngleHighpass; 104 | } 105 | } 106 | 107 | void Start() 108 | { 109 | GameEvents.onGamePause.Add(OnGamePaused); 110 | GameEvents.onGameUnpause.Add(OnGameUnpaused); 111 | } 112 | 113 | public override void OnLoad(ConfigNode node) 114 | { 115 | ConfigNode.LoadObjectFromConfig(this, node); 116 | volume.Load("volume", node); 117 | pitch.Load("pitch", node); 118 | } 119 | 120 | public override void OnEvent() 121 | { 122 | Play(1); 123 | } 124 | 125 | public override void OnEvent(float power) 126 | { 127 | Play(power); 128 | } 129 | 130 | public void Play(float power) 131 | { 132 | markForPlay = true; 133 | control = power; 134 | playOneShot = !loop; 135 | } 136 | 137 | public virtual void LateUpdate() 138 | { 139 | if (audioSource == null || audioClip == null || !HighLogic.LoadedSceneIsFlight) return; 140 | 141 | isActiveVessel = hostPart != null && hostPart.vessel == FlightGlobals.ActiveVessel; 142 | 143 | if (markForPlay) 144 | { 145 | float finalVolume = volume.Value(control); 146 | 147 | if (finalVolume < float.Epsilon) 148 | { 149 | if (audioSource.volume == 0 && loop) 150 | audioSource.Stop(); 151 | 152 | if (audioSource.isPlaying && loop) 153 | audioSource.volume = 0; 154 | 155 | goto end; 156 | } 157 | 158 | audioSource.enabled = true; 159 | if (Settings.MufflerQuality > AudioMufflerQuality.Normal) 160 | { 161 | if (airSimFilter != null && Settings.MufflerQuality == AudioMufflerQuality.AirSim) 162 | { 163 | airSimFilter.enabled = true; 164 | airSimFilter.Distance = distance; 165 | airSimFilter.Mach = mach; 166 | airSimFilter.Angle = angle; 167 | airSimFilter.MachAngle = machAngle; 168 | airSimFilter.MachPass = machPass; 169 | } 170 | else 171 | { 172 | if (Settings.MachEffectsAmount > 0) 173 | { 174 | finalVolume *= Mathf.Log10(Mathf.Lerp(0.1f, 10, machPass)) * 0.5f; 175 | } 176 | } 177 | } 178 | 179 | audioSource.volume = finalVolume * GetVolumeChannel(channel); 180 | audioSource.pitch = pitch.Value(control) * (loop ? doppler : 1); 181 | audioSource.outputAudioMixerGroup = AudioUtility.GetMixerGroup(FXChannel.Exterior, isActiveVessel); 182 | 183 | if (!audioSource.isPlaying && loop) 184 | { 185 | if (audioSource.clip == null) audioSource.clip = audioClip; 186 | 187 | audioSource.time = loopAtRandom ? audioClip.length * loopRandomStart : 0; 188 | audioSource.Play(); 189 | } 190 | 191 | if (playOneShot) 192 | { 193 | audioSource.PlayOneShot(audioClip); 194 | playOneShot = false; 195 | } 196 | } 197 | 198 | end: 199 | 200 | slowUpdate++; 201 | if (slowUpdate >= 60) 202 | { 203 | slowUpdate = 0; 204 | 205 | if (audioSource.isPlaying || !audioSource.enabled) return; 206 | 207 | audioSource.enabled = false; 208 | markForPlay = false; 209 | loopRandomStart = (float)random.NextDouble(); 210 | 211 | if (!audioSource.enabled && airSimFilter != null) 212 | { 213 | airSimFilter.enabled = false; 214 | airSimFilter.Distance = distance; 215 | airSimFilter.Mach = mach; 216 | airSimFilter.Angle = angle; 217 | airSimFilter.MachAngle = machAngle; 218 | airSimFilter.MachPass = machPass; 219 | } 220 | } 221 | 222 | if (airSimFilter != null && airSimFilter.enabled && Settings.MufflerQuality != AudioMufflerQuality.AirSim) 223 | airSimFilter.enabled = false; 224 | } 225 | 226 | public void FixedUpdate() 227 | { 228 | if (Settings.EnableAudioEffects && Settings.MufflerQuality > AudioMufflerQuality.Normal && HighLogic.LoadedSceneIsFlight) 229 | { 230 | distance = Vector3.Distance(CameraManager.GetCurrentCamera().transform.position, transform.position); 231 | 232 | if (hostPart == null) return; 233 | 234 | if (DopplerFactor > 0) 235 | { 236 | var relativeSpeed = (lastDistance - distance) / TimeWarp.fixedDeltaTime; 237 | lastDistance = distance; 238 | float dopplerScale = DopplerFactor * Settings.DopplerFactor; 239 | float speedOfSound = hostPart.vessel.speedOfSound > 0 ? (float)hostPart.vessel.speedOfSound : 340.29f; 240 | float dopplerRaw = Mathf.Clamp((speedOfSound + ((relativeSpeed) * dopplerScale)) / speedOfSound, 1 - (dopplerScale * 0.5f), 1 + dopplerScale); 241 | doppler = Mathf.MoveTowards(doppler, dopplerRaw, 0.5f * TimeWarp.fixedDeltaTime); 242 | } 243 | 244 | angle = (1 + Vector3.Dot(hostPart.vessel.GetComponent().MachTipCameraNormal, (transform.up + hostPart.vessel.velocityD).normalized)) * 90; 245 | 246 | bool isActiveAndInternal = hostPart.vessel.isActiveVessel && (InternalCamera.Instance.isActive || MapView.MapCamera.isActiveAndEnabled); 247 | if (isActiveAndInternal) 248 | { 249 | angle = 0; 250 | machPass = 1; 251 | return; 252 | } 253 | 254 | if (Settings.MachEffectsAmount > 0) 255 | { 256 | mach = Mathf.Clamp01(hostPart.vessel.GetComponent().Mach); 257 | machAngle = hostPart.vessel.GetComponent().MachAngle; 258 | machPass = Mathf.Lerp(1, Settings.MachEffectLowerLimit, Mathf.Clamp01(angle / machAngle) * mach); 259 | } 260 | else 261 | { 262 | mach = 0; 263 | machAngle = 90; 264 | machPass = 1; 265 | } 266 | } 267 | } 268 | 269 | public float GetVolumeChannel(AudioFX.AudioChannel channel) 270 | { 271 | switch (channel) 272 | { 273 | case AudioFX.AudioChannel.Ship: 274 | return GameSettings.SHIP_VOLUME; 275 | case AudioFX.AudioChannel.Voice: 276 | return GameSettings.VOICE_VOLUME; 277 | case AudioFX.AudioChannel.Ambient: 278 | return GameSettings.AMBIENCE_VOLUME; 279 | case AudioFX.AudioChannel.Music: 280 | return GameSettings.MUSIC_VOLUME; 281 | case AudioFX.AudioChannel.UI: 282 | return GameSettings.UI_VOLUME; 283 | default: return 1; 284 | } 285 | } 286 | 287 | public void OnGamePaused() 288 | { 289 | if (audioSource == null) return; 290 | audioSource.Pause(); 291 | } 292 | 293 | public void OnGameUnpaused() 294 | { 295 | if (audioSource == null) return; 296 | audioSource.UnPause(); 297 | } 298 | 299 | public void OnDestroy() 300 | { 301 | GameEvents.onGamePause.Remove(OnGamePaused); 302 | GameEvents.onGameUnpause.Remove(OnGameUnpaused); 303 | } 304 | } 305 | } 306 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/RSE_Coupler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | namespace RocketSoundEnhancement.PartModules 7 | { 8 | public class RSE_Coupler : RSE_Module 9 | { 10 | private ModuleDecouplerBase moduleDecoupler; 11 | private bool isDecoupler; 12 | private bool hasDecoupled; 13 | 14 | public override void OnStart(StartState state) 15 | { 16 | if (state == StartState.Editor || state == StartState.None) 17 | return; 18 | 19 | EnableLowpassFilter = true; 20 | EnableDistortionFilter = true; 21 | base.OnStart(state); 22 | 23 | if(part.GetComponent()) { 24 | moduleDecoupler = part.GetComponent(); 25 | hasDecoupled = moduleDecoupler.isDecoupled; 26 | isDecoupler = true; 27 | } 28 | 29 | if (SoundLayerGroups.ContainsKey("LaunchClamp") && part.isLaunchClamp()) 30 | { 31 | var clampSoundLayer = SoundLayerGroups["LaunchClamp"].FirstOrDefault(); 32 | if (clampSoundLayer.audioClips != null) 33 | { 34 | var fxGroup = part.GetComponent().releaseFx; 35 | int index = clampSoundLayer.audioClips.Length > 1 ? UnityEngine.Random.Range(0, clampSoundLayer.audioClips.Length) : 0; 36 | fxGroup.sfx = clampSoundLayer.audioClips[index]; 37 | fxGroup.audio = AudioUtility.CreateSource(AudioParent, clampSoundLayer); 38 | Sources.Add("launchClamp", fxGroup.audio); 39 | } 40 | } 41 | 42 | GameEvents.onDockingComplete.Add(onDock); 43 | GameEvents.onPartUndockComplete.Add(onUnDock); 44 | 45 | Initialized = true; 46 | } 47 | 48 | private void onUnDock(Part data) 49 | { 50 | if(part.flightID == data.flightID && !isDecoupler) { 51 | PlaySound("Undock"); 52 | } 53 | } 54 | 55 | private void onDock(GameEvents.FromToAction data) 56 | { 57 | if(part.flightID == data.from.flightID && !isDecoupler) { 58 | PlaySound("Dock"); 59 | } 60 | } 61 | 62 | public override void LateUpdate() 63 | { 64 | if(!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused) 65 | return; 66 | 67 | if(moduleDecoupler != null && SoundLayerGroups.ContainsKey("Decouple")) { 68 | if(moduleDecoupler.isDecoupled && !hasDecoupled) { 69 | foreach(var soundlayer in SoundLayerGroups["Decouple"]) { 70 | PlaySoundLayer(soundlayer, 1, 1); 71 | } 72 | hasDecoupled = moduleDecoupler.isDecoupled; 73 | } 74 | } 75 | 76 | base.LateUpdate(); 77 | } 78 | 79 | public void PlaySound(string action) 80 | { 81 | if (SoundLayerGroups.ContainsKey(action)) 82 | { 83 | foreach (var soundLayer in SoundLayerGroups[action]) 84 | { 85 | PlaySoundLayer(soundLayer, 1, 1); 86 | } 87 | } 88 | } 89 | 90 | public override void OnDestroy() 91 | { 92 | GameEvents.onDockingComplete.Remove(onDock); 93 | GameEvents.onPartUndockComplete.Remove(onUnDock); 94 | 95 | base.OnDestroy(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/RSE_Engines.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace RocketSoundEnhancement.PartModules 5 | { 6 | public class RSE_Engines : RSE_Module 7 | { 8 | public Dictionary ignites = new Dictionary(); 9 | public Dictionary flameouts = new Dictionary(); 10 | public Dictionary bursts = new Dictionary(); 11 | 12 | public Dictionary sharedSoundLayers = new Dictionary(); 13 | private List engineModules = new List(); 14 | 15 | public override void OnStart(StartState state) 16 | { 17 | if(state == StartState.Editor || state == StartState.None) 18 | return; 19 | 20 | EnableLowpassFilter = true; 21 | EnableCombFilter = true; 22 | EnableDistortionFilter = true; 23 | base.OnStart(state); 24 | 25 | var soundLayersCache = new HashSet(); 26 | engineModules = part.Modules.GetModules(); 27 | foreach (var engineModule in engineModules) 28 | { 29 | if (engineModules.Count > 1) 30 | { 31 | foreach (var soundLayer in SoundLayerGroups[engineModule.engineID]) 32 | { 33 | if (sharedSoundLayers.ContainsKey(soundLayer.name)) 34 | { 35 | sharedSoundLayers[soundLayer.name] += 1; 36 | continue; 37 | } 38 | 39 | if (soundLayersCache.Contains(soundLayer.name)) 40 | { 41 | sharedSoundLayers.Add(soundLayer.name, 1); 42 | continue; 43 | } 44 | soundLayersCache.Add(soundLayer.name); 45 | } 46 | } 47 | 48 | ignites.Add(engineModule.engineID, engineModule.EngineIgnited); 49 | flameouts.Add(engineModule.engineID, engineModule.flameout); 50 | bursts.Add(engineModule.engineID, false); 51 | } 52 | 53 | Initialized = true; 54 | } 55 | 56 | public override void LateUpdate() 57 | { 58 | if(!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused) 59 | return; 60 | 61 | foreach (var engineModule in engineModules) 62 | { 63 | var engineID = engineModule.engineID; 64 | var engineIgnited = engineModule.EngineIgnited; 65 | var engineFlameout = engineModule.flameout; 66 | var currentThrust = engineModule.GetCurrentThrust() / engineModule.maxThrust; 67 | 68 | if (SoundLayerGroups.ContainsKey(engineID)) 69 | { 70 | foreach (var soundLayer in SoundLayerGroups[engineID]) 71 | { 72 | if (sharedSoundLayers.ContainsKey(soundLayer.name) && !engineModule.isEnabled) 73 | continue; 74 | 75 | float control = currentThrust; 76 | 77 | if (!Controls.ContainsKey(soundLayer.name)) 78 | { 79 | Controls.Add(soundLayer.name, 0); 80 | } 81 | 82 | if (soundLayer.spool) 83 | { 84 | float spoolSpeed = Mathf.Max(soundLayer.spoolSpeed, control) * TimeWarp.deltaTime; 85 | float spoolControl = Mathf.Lerp(engineIgnited ? soundLayer.spoolIdle : 0, 1, control); 86 | spoolControl = engineFlameout ? 0 : spoolControl; 87 | 88 | if (!soundLayer.data.Contains("Turbine") && (!engineIgnited || engineFlameout)) 89 | { 90 | spoolSpeed = AudioUtility.SmoothControl.Evaluate(control) * (60 * Time.deltaTime); 91 | } 92 | 93 | Controls[soundLayer.name] = Mathf.MoveTowards(Controls[soundLayer.name], spoolControl, spoolSpeed); 94 | } 95 | else 96 | { 97 | float smoothControl = AudioUtility.SmoothControl.Evaluate(control) * (60 * Time.deltaTime); 98 | Controls[soundLayer.name] = Mathf.MoveTowards(Controls[soundLayer.name], control, smoothControl); 99 | } 100 | 101 | PlaySoundLayer(soundLayer, Controls[soundLayer.name], Volume); 102 | } 103 | } 104 | 105 | foreach (var soundLayerGroup in SoundLayerGroups) { 106 | float control = currentThrust; 107 | switch(soundLayerGroup.Key) { 108 | case "Engage": 109 | if(engineIgnited && !ignites[engineID]) { 110 | ignites[engineID] = true; 111 | } else { 112 | if(!SoundLayerGroups.ContainsKey("Disengage")) 113 | ignites[engineID] = engineIgnited; 114 | continue; 115 | } 116 | break; 117 | case "Disengage": 118 | if(!engineIgnited && ignites[engineID]) { 119 | ignites[engineID] = false; 120 | } else { 121 | if(!SoundLayerGroups.ContainsKey("Engage")) 122 | ignites[engineID] = engineIgnited; 123 | continue; 124 | } 125 | break; 126 | case "Flameout": 127 | if (flameouts[engineID] == engineFlameout) 128 | continue; 129 | 130 | flameouts[engineID] = engineFlameout; 131 | break; 132 | case "Burst": 133 | if(engineIgnited && currentThrust > 0) { 134 | if(!bursts[engineID]) { 135 | bursts[engineID] = true; 136 | } else { 137 | continue; 138 | } 139 | } else { 140 | bursts[engineID] = false; 141 | continue; 142 | } 143 | break; 144 | default: 145 | continue; 146 | } 147 | 148 | foreach (var soundLayer in soundLayerGroup.Value) 149 | { 150 | PlaySoundLayer(soundLayer, control, Volume); 151 | } 152 | } 153 | } 154 | 155 | base.LateUpdate(); 156 | } 157 | 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/RSE_KerbalEVA.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using UnityEngine; 3 | 4 | namespace RocketSoundEnhancement.PartModules 5 | { 6 | public class RSE_KerbalEVA : RSE_Module 7 | { 8 | public override void OnStart(StartState state) 9 | { 10 | if (state == StartState.Editor || state == StartState.None) 11 | return; 12 | 13 | EnableLowpassFilter = true; 14 | base.OnStart(state); 15 | 16 | Initialized = true; 17 | } 18 | 19 | public override void LateUpdate() 20 | { 21 | if (!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused) 22 | return; 23 | 24 | foreach (var soundLayer in SoundLayers) 25 | { 26 | string sourceLayerName = soundLayer.name; 27 | 28 | if (!Controls.ContainsKey(sourceLayerName)) 29 | { 30 | Controls.Add(sourceLayerName, 0); 31 | } 32 | var fxGroup = part.fxGroups.FirstOrDefault(g => g.name == sourceLayerName); 33 | 34 | float control = 0; 35 | if (fxGroup.activeLatch) // thruster is firing 36 | { 37 | control = fxGroup.power; 38 | } 39 | float smoothControl = AudioUtility.SmoothControl.Evaluate(control) * (60 * Time.deltaTime); 40 | Controls[sourceLayerName] = Mathf.MoveTowards(Controls[sourceLayerName], control, smoothControl); 41 | 42 | PlaySoundLayer(soundLayer, Controls[sourceLayerName], Volume); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/RSE_RCS.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using UnityEngine; 3 | 4 | namespace RocketSoundEnhancement.PartModules 5 | { 6 | public class RSE_RCS : RSE_Module 7 | { 8 | private ModuleRCSFX moduleRCSFX; 9 | 10 | public override void OnStart(StartState state) 11 | { 12 | if (state == StartState.Editor || state == StartState.None) 13 | return; 14 | 15 | EnableLowpassFilter = true; 16 | base.OnStart(state); 17 | 18 | moduleRCSFX = part.Modules.GetModule(); 19 | Initialized = true; 20 | } 21 | 22 | public override void LateUpdate() 23 | { 24 | if (!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused) 25 | return; 26 | 27 | var thrustTransformsCount = moduleRCSFX.thrusterTransforms.Count > 0 ? moduleRCSFX.thrusterTransforms.Count : 1; 28 | var thrustForces = moduleRCSFX.thrustForces; 29 | float control = 0; 30 | 31 | if(thrustForces != null || thrustForces.Length > 0) 32 | { 33 | for (int i = 0; i < thrustForces.Length; i++) 34 | { 35 | control += thrustForces[i] / moduleRCSFX.thrusterPower; 36 | } 37 | control /= thrustTransformsCount; 38 | } 39 | 40 | foreach (var soundLayer in SoundLayers) 41 | { 42 | string sourceLayerName = soundLayer.name; 43 | 44 | if (!Controls.ContainsKey(sourceLayerName)) 45 | { 46 | Controls.Add(sourceLayerName, 0); 47 | } 48 | 49 | float smoothControl = AudioUtility.SmoothControl.Evaluate(control) * (30 * Time.deltaTime); 50 | Controls[sourceLayerName] = Mathf.MoveTowards(Controls[sourceLayerName], control, smoothControl); 51 | 52 | PlaySoundLayer(soundLayer, Controls[sourceLayerName], Volume * thrustTransformsCount); 53 | } 54 | 55 | base.LateUpdate(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/RSE_RotorEngines.cs: -------------------------------------------------------------------------------- 1 | using Expansions.Serenity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using UnityEngine; 8 | 9 | namespace RocketSoundEnhancement.PartModules 10 | { 11 | public struct PropellerBladeData 12 | { 13 | public int bladeCount; 14 | public float baseRPM; 15 | public int maxBlades; 16 | public FXCurve volume; 17 | public List soundLayers; 18 | } 19 | 20 | public class RSE_RotorEngines : RSE_Module 21 | { 22 | public Dictionary PropellerBlades = new Dictionary(); 23 | private ModuleRoboticServoRotor rotorModule; 24 | private ModuleResourceIntake resourceIntake; 25 | private int childPartsCount = 0; 26 | 27 | public override void OnStart(StartState state) 28 | { 29 | if(state == StartState.Editor || state == StartState.None) 30 | return; 31 | 32 | EnableLowpassFilter = true; 33 | EnableCombFilter = true; 34 | EnableDistortionFilter = true; 35 | base.OnStart(state); 36 | 37 | rotorModule = part.GetComponent(); 38 | resourceIntake = part.GetComponent(); 39 | 40 | SetupBlades(); 41 | 42 | Initialized = true; 43 | } 44 | 45 | public void SetupBlades() 46 | { 47 | if (PropellerBlades.Count > 0) 48 | { 49 | foreach (var propellerBlade in PropellerBlades.Keys.ToList()) 50 | { 51 | var cleanData = PropellerBlades[propellerBlade]; 52 | cleanData.bladeCount = 0; 53 | PropellerBlades[propellerBlade] = cleanData; 54 | } 55 | } 56 | 57 | var childParts = rotorModule.part.children; 58 | childPartsCount = childParts.Count; 59 | foreach (var childPart in childParts) 60 | { 61 | var configNode = GameDatabase.Instance.GetConfigs("PART").FirstOrDefault(x => x.name.Replace("_", ".") == childPart.partInfo.name); 62 | var propConfig = configNode.config.GetNode("RSE_Propellers"); 63 | 64 | if (propConfig != null) 65 | { 66 | if (!PropellerBlades.ContainsKey(childPart.partInfo.name)) 67 | { 68 | var propData = new PropellerBladeData(); 69 | propData.soundLayers = AudioUtility.CreateSoundLayerGroup(propConfig.GetNodes("SOUNDLAYER")); 70 | 71 | propData.volume = new FXCurve("volume", 1); 72 | propData.volume.Load("volume", propConfig); 73 | 74 | if (!float.TryParse(propConfig.GetValue("baseRPM"), out propData.baseRPM)) 75 | { 76 | Debug.Log("[RSE]: [RSE_Propellers] baseRPM cannot be empty"); 77 | Initialized = false; 78 | return; 79 | } 80 | 81 | if (!int.TryParse(propConfig.GetValue("maxBlades"), out propData.maxBlades)) 82 | { 83 | Debug.Log("[RSE]: [RSE_Propellers] maxBlades cannot be empty"); 84 | Initialized = false; 85 | return; 86 | } 87 | 88 | propData.bladeCount = 1; 89 | PropellerBlades.Add(childPart.partInfo.name, propData); 90 | 91 | } 92 | else 93 | { 94 | var propUpdate = PropellerBlades[childPart.partInfo.name]; 95 | propUpdate.bladeCount += 1; 96 | PropellerBlades[childPart.partInfo.name] = propUpdate; 97 | } 98 | } 99 | } 100 | 101 | foreach (var propSoundLayers in PropellerBlades.Values) 102 | { 103 | StartCoroutine(SetupAudioSources(propSoundLayers.soundLayers)); 104 | } 105 | 106 | Initialized = true; 107 | } 108 | 109 | public override void LateUpdate() 110 | { 111 | if (!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused) 112 | return; 113 | 114 | if (SoundLayerGroups.Count > 0) 115 | { 116 | float intakeMultiplier = 1; 117 | bool motorEngaged = rotorModule.servoMotorIsEngaged && !rotorModule.servoIsLocked; 118 | 119 | if (resourceIntake != null) 120 | { 121 | motorEngaged = rotorModule.servoMotorIsEngaged && !rotorModule.servoIsLocked && resourceIntake.intakeEnabled; 122 | intakeMultiplier = resourceIntake.intakeEnabled ? Mathf.Min(resourceIntake.airFlow, 1) : 0; 123 | } 124 | 125 | float rpm = rotorModule.transformRateOfMotion / rotorModule.traverseVelocityLimits.y; 126 | float torque = rotorModule.totalTorque / rotorModule.maxTorque; 127 | 128 | foreach (var soundLayerGroup in SoundLayerGroups) 129 | { 130 | float control = 0; 131 | 132 | switch (soundLayerGroup.Key) 133 | { 134 | case "RPM": 135 | control = rpm; 136 | break; 137 | case "Motor": 138 | control = motorEngaged ? Mathf.Min(torque, rpm) * intakeMultiplier : 0; 139 | if (rotorModule.servoIsBraking) 140 | { 141 | control *= 0.25f; 142 | } 143 | break; 144 | } 145 | 146 | foreach (var soundLayer in soundLayerGroup.Value) 147 | { 148 | string soundLayerName = soundLayerGroup.Key + "_" + soundLayer.name; 149 | 150 | if (!Controls.ContainsKey(soundLayerName)) 151 | { 152 | Controls.Add(soundLayerName, 0); 153 | } 154 | 155 | if (soundLayer.spool) 156 | { 157 | float spoolSpeed = Mathf.Max(soundLayer.spoolSpeed, control) * TimeWarp.deltaTime; 158 | float spoolControl = Mathf.Lerp(motorEngaged ? soundLayer.spoolIdle : 0, 1, control); 159 | 160 | Controls[soundLayerName] = Mathf.MoveTowards(Controls[soundLayerName], spoolControl, spoolSpeed); 161 | } 162 | else 163 | { 164 | float smoothControl = AudioUtility.SmoothControl.Evaluate(control) * (60 * Time.deltaTime); 165 | Controls[soundLayerName] = Mathf.MoveTowards(Controls[soundLayerName], control, smoothControl); 166 | } 167 | 168 | PlaySoundLayer(soundLayer, Controls[soundLayerName], Volume); 169 | } 170 | } 171 | } 172 | 173 | if (PropellerBlades.Count > 0) 174 | { 175 | float rotorRPM = (rotorModule.movingPartRB.angularVelocity.magnitude / 2 / Mathf.PI) * 60; //use the world space RPM instead of relative 176 | 177 | float atm = Mathf.Clamp((float)vessel.atmDensity, 0f, 1f); //only play prop sounds in an atmosphere 178 | 179 | if (childPartsCount != rotorModule.part.children.Count) 180 | { 181 | SetupBlades(); 182 | } 183 | 184 | foreach (var propellerBlade in PropellerBlades.Values) 185 | { 186 | float propControl = rotorRPM / propellerBlade.baseRPM; 187 | float propOverallVolume = propellerBlade.volume.Value(propControl) * atm; 188 | float bladeMultiplier = Mathf.Clamp((float)propellerBlade.bladeCount / propellerBlade.maxBlades, 0, 2); 189 | float control = propControl * bladeMultiplier; 190 | 191 | foreach (var soundLayer in propellerBlade.soundLayers) 192 | { 193 | string soundLayerName = propellerBlade + "_" + "_" + soundLayer.name; 194 | 195 | if (!Controls.ContainsKey(soundLayerName)) 196 | { 197 | Controls.Add(soundLayerName, 0); 198 | } 199 | 200 | Controls[soundLayerName] = Mathf.MoveTowards(Controls[soundLayerName], control, AudioUtility.SmoothControl.Evaluate(control) * (60 * Time.deltaTime)); 201 | 202 | PlaySoundLayer(soundLayer, Controls[soundLayerName], propOverallVolume); 203 | } 204 | } 205 | } 206 | 207 | base.LateUpdate(); 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/RSE_Wheels.cs: -------------------------------------------------------------------------------- 1 | using ModuleWheels; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | using UnityEngine.Profiling; 6 | 7 | namespace RocketSoundEnhancement.PartModules 8 | { 9 | public class RSE_Wheels : RSE_Module 10 | { 11 | private Dictionary offLoadVolumeScale = new Dictionary(); 12 | private Dictionary volumeScaleSpools = new Dictionary(); 13 | 14 | private ModuleWheelBase moduleWheel; 15 | private ModuleWheelMotor moduleMotor; 16 | private ModuleWheelDamage moduleWheelDamage; 17 | private ModuleWheelDeployment moduleDeploy; 18 | private CollidingObject collidingObject; 19 | 20 | private bool retracted = false; 21 | private bool motorRunning = false; 22 | private float motorOutput = 0; 23 | private float wheelSpeed = 0; 24 | private float slipDisplacement = 0; 25 | 26 | public override void OnStart(StartState state) 27 | { 28 | if (state == StartState.Editor || state == StartState.None) 29 | return; 30 | 31 | EnableLowpassFilter = true; 32 | base.OnStart(state); 33 | 34 | if (PartConfigNode.HasNode("Motor")) 35 | { 36 | ConfigNode offLoadVolumeScaleNode; 37 | if ((offLoadVolumeScaleNode = PartConfigNode.GetNode("Motor").GetNode("offLoadVolumeScale")) != null && offLoadVolumeScaleNode.HasValues()) 38 | { 39 | foreach (ConfigNode.Value node in offLoadVolumeScaleNode.values) 40 | { 41 | string soundLayerName = node.name; 42 | float value = float.Parse(node.value); 43 | 44 | if (offLoadVolumeScale.ContainsKey(soundLayerName)) 45 | { 46 | offLoadVolumeScale[soundLayerName] = value; 47 | continue; 48 | } 49 | 50 | offLoadVolumeScale.Add(soundLayerName, value); 51 | } 52 | } 53 | } 54 | 55 | moduleWheel = part.GetComponent(); 56 | moduleMotor = part.GetComponent(); 57 | moduleDeploy = part.GetComponent(); 58 | moduleWheelDamage = part.GetComponent(); 59 | 60 | Initialized = true; 61 | } 62 | 63 | public override void LateUpdate() 64 | { 65 | if (!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused || !moduleWheel || !moduleWheel.Wheel) 66 | return; 67 | 68 | if (moduleMotor) 69 | { 70 | motorRunning = moduleMotor.motorEnabled && moduleMotor.state > ModuleWheelMotor.MotorState.Disabled; 71 | motorOutput = motorRunning ? Mathf.Clamp(wheelSpeed / moduleMotor.wheelSpeedMax, 0, 2f) : 0; 72 | } 73 | 74 | if (moduleDeploy) 75 | { 76 | retracted = moduleDeploy.stateString == "Retracted"; 77 | } 78 | 79 | foreach (var soundLayerGroup in SoundLayerGroups) 80 | { 81 | string soundLayerGroupKey = soundLayerGroup.Key; 82 | float control = 0; 83 | 84 | if (!retracted) 85 | { 86 | switch (soundLayerGroup.Key) 87 | { 88 | case "Motor": 89 | control = motorOutput; 90 | break; 91 | case "Speed": 92 | control = wheelSpeed; 93 | break; 94 | case "Ground": 95 | control = moduleWheel.isGrounded ? Mathf.Max(wheelSpeed, slipDisplacement) : 0; 96 | break; 97 | case "Slip": 98 | control = moduleWheel.isGrounded ? slipDisplacement : 0; 99 | break; 100 | default: 101 | continue; 102 | } 103 | } 104 | 105 | foreach (var soundLayer in soundLayerGroup.Value) 106 | { 107 | string soundLayerName = soundLayerGroupKey + "_" + soundLayer.name; 108 | float finalControl = control; 109 | float volumeScale = 1; 110 | 111 | if (soundLayerGroupKey == "Ground" || soundLayerGroupKey == "Slip") 112 | { 113 | string collidingObjectString = collidingObject.ToString().ToLower(); 114 | if (soundLayer.data != "" && !soundLayer.data.Contains(collidingObjectString)) 115 | finalControl = 0; 116 | } 117 | 118 | if (!Controls.ContainsKey(soundLayerName)) 119 | { 120 | Controls.Add(soundLayerName, 0); 121 | } 122 | 123 | if (soundLayer.spool) 124 | { 125 | float spoolControl = soundLayerGroupKey == "Motor" ? Mathf.Lerp(motorRunning ? soundLayer.spoolIdle : 0, 1, finalControl) : finalControl; 126 | float spoolSpeed = Mathf.Max(soundLayer.spoolSpeed, finalControl * 0.5f); 127 | 128 | if (soundLayerGroupKey == "Motor" && moduleWheel.wheel.brakeState > 0 && Controls[soundLayerName] > spoolControl) 129 | { 130 | spoolSpeed = soundLayer.spoolSpeed; 131 | } 132 | 133 | Controls[soundLayerName] = Mathf.MoveTowards(Controls[soundLayerName], spoolControl, soundLayer.spoolSpeed * TimeWarp.deltaTime); 134 | } 135 | else 136 | { 137 | float smoothControl = AudioUtility.SmoothControl.Evaluate(Mathf.Max(Controls[soundLayerName], finalControl)) * (60 * Time.deltaTime); 138 | Controls[soundLayerName] = Mathf.MoveTowards(Controls[soundLayerName], finalControl, smoothControl); 139 | } 140 | 141 | if (soundLayerGroupKey == "Motor" && offLoadVolumeScale.ContainsKey(soundLayer.name)) 142 | { 143 | volumeScale = moduleMotor.state == ModuleWheelMotor.MotorState.Running ? 1 : offLoadVolumeScale[soundLayer.name]; 144 | if (soundLayer.spool) 145 | { 146 | if (!volumeScaleSpools.Keys.Contains(soundLayerName)) 147 | volumeScaleSpools.Add(soundLayerName, 0); 148 | 149 | volumeScaleSpools[soundLayerName] = Mathf.MoveTowards(volumeScaleSpools[soundLayerName], volumeScale, soundLayer.spoolSpeed * TimeWarp.deltaTime); 150 | volumeScale = volumeScaleSpools[soundLayerName]; 151 | } 152 | } 153 | 154 | PlaySoundLayer(soundLayer, Controls[soundLayerName], Volume * volumeScale); 155 | } 156 | } 157 | 158 | base.LateUpdate(); 159 | } 160 | 161 | public override void FixedUpdate() 162 | { 163 | if (!Initialized || !moduleWheel || !moduleWheel.Wheel || GamePaused || !vessel.loaded) 164 | return; 165 | 166 | base.FixedUpdate(); 167 | 168 | if (moduleWheelDamage != null && moduleWheelDamage.isDamaged) 169 | { 170 | wheelSpeed = 0; 171 | slipDisplacement = 0; 172 | return; 173 | } 174 | 175 | if (moduleWheel.isGrounded) 176 | { 177 | WheelHit hit; 178 | if (moduleWheel.Wheel.wheelCollider.GetGroundHit(out hit)) 179 | { 180 | collidingObject = AudioUtility.GetCollidingObject(hit.collider.gameObject); 181 | } 182 | } 183 | 184 | wheelSpeed = Mathf.Abs(moduleWheel.Wheel.WheelRadius * moduleWheel.Wheel.wheelCollider.angularVelocity); 185 | 186 | float x = moduleWheel.Wheel.currentState.localWheelVelocity.x; 187 | float y = (moduleWheel.Wheel.WheelRadius * moduleWheel.Wheel.wheelCollider.angularVelocity) - moduleWheel.Wheel.currentState.localWheelVelocity.y; 188 | 189 | slipDisplacement = Mathf.Sqrt(x * x + y * y); 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/PartModules/ShipEffectsCollisions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | namespace RocketSoundEnhancement.PartModules 7 | { 8 | public enum CollisionType 9 | { 10 | CollisionEnter, 11 | CollisionStay, 12 | CollisionExit 13 | } 14 | 15 | public class ShipEffectsCollisions : RSE_Module 16 | { 17 | private Dictionary> SoundLayerCollisionGroups = new Dictionary>(); 18 | 19 | private bool collided; 20 | private Collision collision; 21 | private CollidingObject collidingObject; 22 | private CollisionType collisionType; 23 | 24 | public override void OnStart(StartState state) 25 | { 26 | if (state == StartState.Editor || state == StartState.None) 27 | return; 28 | 29 | PrepareSoundLayers = false; 30 | EnableLowpassFilter = true; 31 | base.OnStart(state); 32 | 33 | foreach (var node in PartConfigNode.GetNodes()) 34 | { 35 | var soundLayerNodes = node.GetNodes("SOUNDLAYER"); 36 | CollisionType collisionType; 37 | 38 | if (Enum.TryParse(node.name, out collisionType)) 39 | { 40 | SoundLayerCollisionGroups.Add(collisionType, AudioUtility.CreateSoundLayerGroup(soundLayerNodes)); 41 | } 42 | } 43 | 44 | if (SoundLayerCollisionGroups.Count > 0) 45 | { 46 | foreach (var soundLayerGroup in SoundLayerCollisionGroups) 47 | { 48 | StartCoroutine(SetupAudioSources(soundLayerGroup.Value)); 49 | } 50 | } 51 | 52 | Initialized = true; 53 | } 54 | 55 | public override void LateUpdate() 56 | { 57 | if (!HighLogic.LoadedSceneIsFlight || !Initialized || !vessel.loaded || GamePaused) return; 58 | 59 | if (!collided) 60 | { 61 | foreach (var source in Sources.Values) 62 | { 63 | if (source.volume == 0 && source.loop) 64 | source.Stop(); 65 | if (source.isPlaying && source.loop) 66 | source.volume = 0; 67 | } 68 | enabled = false; 69 | goto baseLateUpdate; 70 | } 71 | 72 | if (!SoundLayerCollisionGroups.ContainsKey(collisionType)) return; 73 | 74 | string collidingObjectString = collidingObject.ToString().ToLower(); 75 | float control = collision != null ? collision.relativeVelocity.magnitude : 0; 76 | 77 | foreach (var soundLayer in SoundLayerCollisionGroups[collisionType]) 78 | { 79 | float finalControl = control; 80 | if (soundLayer.data != "" && !soundLayer.data.Contains(collidingObjectString)) finalControl = 0; 81 | 82 | PlaySoundLayer(soundLayer, finalControl, Volume, true); 83 | } 84 | 85 | baseLateUpdate: 86 | base.LateUpdate(); 87 | } 88 | 89 | public override void FixedUpdate() 90 | { 91 | if (!Initialized || GamePaused || !vessel.loaded) 92 | return; 93 | 94 | collided = false; 95 | collisionType = CollisionType.CollisionStay; 96 | base.FixedUpdate(); 97 | } 98 | 99 | public void OnCollisionEnter(Collision col) 100 | { 101 | enabled = true; 102 | 103 | collided = true; 104 | collidingObject = AudioUtility.GetCollidingObject(col.gameObject); 105 | collisionType = CollisionType.CollisionEnter; 106 | collision = col; 107 | } 108 | 109 | public void OnCollisionStay(Collision col) 110 | { 111 | collided = true; 112 | collidingObject = AudioUtility.GetCollidingObject(col.gameObject); 113 | collisionType = CollisionType.CollisionStay; 114 | collision = col; 115 | } 116 | 117 | public void OnCollisionExit(Collision col) 118 | { 119 | collided = false; 120 | collidingObject = AudioUtility.GetCollidingObject(col.gameObject); 121 | collisionType = CollisionType.CollisionExit; 122 | collision = col; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #region Using directives 2 | 3 | using System; 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | #endregion 8 | 9 | // General Information about an assembly is controlled through the following 10 | // set of attributes. Change these attribute values to modify the information 11 | // associated with an assembly. 12 | [assembly: AssemblyTitle("RocketSoundEnhancement")] 13 | [assembly: AssemblyDescription("")] 14 | [assembly: AssemblyConfiguration("")] 15 | [assembly: AssemblyCompany("")] 16 | [assembly: AssemblyProduct("RocketSoundEnhancement")] 17 | [assembly: AssemblyCopyright("Copyright 2022")] 18 | [assembly: AssemblyTrademark("")] 19 | [assembly: AssemblyCulture("")] 20 | 21 | // This sets the default COM visibility of types in the assembly to invisible. 22 | // If you need to expose a type to COM, use [ComVisible(true)] on that type. 23 | [assembly: ComVisible(false)] 24 | 25 | // The assembly version has following format : 26 | // 27 | // Major.Minor.Build.Revision 28 | // 29 | // You can specify all the values or you can use the default the Revision and 30 | // Build Numbers by using the '*' as shown below: 31 | [assembly: AssemblyVersion("0.9.11.*")] 32 | [assembly: AssemblyInformationalVersion("0.9.11")] 33 | [assembly: KSPAssembly("RocketSoundEnhancement", 0, 9, 11)] 34 | [assembly: KSPAssemblyDependency("RocketSoundEnhancement.Unity", 1, 0)] 35 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/RocketSoundEnhancement.cs: -------------------------------------------------------------------------------- 1 | using KSP.UI.Screens; 2 | using RocketSoundEnhancement.AudioFilters; 3 | using RocketSoundEnhancement.Unity; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using UnityEngine; 8 | using UnityEngine.Audio; 9 | 10 | namespace RocketSoundEnhancement 11 | { 12 | [KSPAddon(KSPAddon.Startup.Flight, false)] 13 | public class RocketSoundEnhancement : MonoBehaviour 14 | { 15 | public static RocketSoundEnhancement instance = null; 16 | public static RocketSoundEnhancement Instance { get { return instance; } } 17 | 18 | private static AssetBundle rse_Bundle; 19 | public static AssetBundle RSE_Bundle 20 | { 21 | get 22 | { 23 | if (rse_Bundle == null) 24 | { 25 | string path = KSPUtil.ApplicationRootPath + Settings.ModPath + "Plugins/"; 26 | rse_Bundle = AssetBundle.LoadFromFile(path + "rse_bundle"); 27 | Debug.Log("[RSE]: AssetBundle loaded"); 28 | } 29 | return rse_Bundle; 30 | } 31 | } 32 | 33 | private static AudioMixer mixer; 34 | public static AudioMixer Mixer 35 | { 36 | get 37 | { 38 | if (mixer == null) 39 | { 40 | mixer = RSE_Bundle.LoadAsset("RSE_Mixer") as AudioMixer; 41 | Debug.Log("[RSE]: AudioMixer loaded"); 42 | } 43 | return mixer; 44 | } 45 | } 46 | 47 | public static AudioMixerGroup MasterMixer { get { return Mixer.FindMatchingGroups("Master")[0]; } } 48 | public static AudioMixerGroup FocusMixer { get { return Mixer.FindMatchingGroups("FOCUS")[0]; } } 49 | public static AudioMixerGroup InteriorMixer { get { return Mixer.FindMatchingGroups("INTERIOR")[0]; } } 50 | public static AudioMixerGroup ExteriorMixer { get { return Mixer.FindMatchingGroups("EXTERIOR")[0]; } } 51 | 52 | public float MufflingFrequency { get; set; } = 30000; 53 | public float FocusMufflingFrequency { get; set; } = 30000; 54 | private float lastCutoffFreq; 55 | private float lastInteriorCutoffFreq; 56 | 57 | private HashSet managedSources = new HashSet(); 58 | 59 | private bool gamePaused; 60 | 61 | private void Awake() 62 | { 63 | if (instance != null) { Destroy(instance); } 64 | 65 | instance = this; 66 | } 67 | 68 | private void Start() 69 | { 70 | Settings.Load(); 71 | ShipEffectsConfig.Load(); 72 | 73 | ApplySettings(); 74 | 75 | FlightCamera.fetch.AudioListenerGameObject.transform.localPosition = Vector3.zero; 76 | FlightCamera.fetch.AudioListenerGameObject.transform.localEulerAngles = Vector3.zero; 77 | 78 | GameEvents.onGamePause.Add(OnGamePause); 79 | GameEvents.onGameUnpause.Add(OnGameUnpause); 80 | } 81 | 82 | void OnGamePause() 83 | { 84 | gamePaused = true; 85 | } 86 | 87 | void OnGameUnpause() 88 | { 89 | gamePaused = false; 90 | } 91 | 92 | public void ApplySettings() 93 | { 94 | var stageSource = StageManager.Instance.GetComponent(); 95 | if (stageSource) 96 | { 97 | stageSource.enabled = !Settings.DisableStagingSound; 98 | } 99 | 100 | managedSources.Clear(); 101 | foreach (var sourceObj in FindObjectsOfType(typeof(AudioSource))) 102 | { 103 | var source = (AudioSource)sourceObj; 104 | if (source == null) continue; 105 | int instanceID = source.GetInstanceID(); 106 | 107 | if (source.name.Contains(AudioUtility.RSETag)) 108 | { 109 | managedSources.Add(instanceID); 110 | } 111 | else if (Settings.CustomAudioSources.TryGetValue(source.gameObject.name, out MixerGroup mixerChannel)) 112 | { 113 | managedSources.Add(instanceID); 114 | 115 | source.outputAudioMixerGroup = AudioUtility.GetMixerGroup(mixerChannel); 116 | } 117 | else if (source.clip != null && Settings.CustomAudioClips.TryGetValue(source.clip.name, out mixerChannel)) 118 | { 119 | managedSources.Add(instanceID); 120 | 121 | source.outputAudioMixerGroup = AudioUtility.GetMixerGroup(mixerChannel); 122 | } 123 | else if (source.name == "FX Sound" || source.name == "airspeedNoise") 124 | { 125 | if (source.clip != null && source.clip.name != "sound_wind_constant") 126 | source.mute = ShipEffectsConfig.MuteStockAeroSounds; 127 | 128 | managedSources.Add(instanceID); 129 | source.outputAudioMixerGroup = Settings.EnableAudioEffects ? ExteriorMixer : null; 130 | } 131 | } 132 | 133 | UpdateLimiter(); 134 | } 135 | 136 | public void UpdateLimiter() 137 | { 138 | if (Mixer == null) return; 139 | 140 | float thrs, gain, atk, rls; 141 | float amount = Settings.AutoLimiter; 142 | bool isCustom = Settings.EnableCustomLimiter; 143 | thrs = isCustom ? Settings.LimiterThreshold : Mathf.Lerp(0, -16, amount); 144 | gain = isCustom ? Settings.LimiterGain : Mathf.Lerp(0, 16, amount); 145 | atk = isCustom ? Settings.LimiterAttack : Mathf.Lerp(10, 200, amount); 146 | rls = isCustom ? Settings.LimiterRelease : Mathf.Lerp(20, 1000, amount); 147 | 148 | Mixer.SetFloat("LimiterThreshold",thrs); 149 | Mixer.SetFloat("LimiterGain", gain); 150 | Mixer.SetFloat("LimiterAttack", atk); 151 | Mixer.SetFloat("LimiterRelease", rls); 152 | } 153 | 154 | public float WindModulation() 155 | { 156 | float windModulationSpeed = 2f; 157 | float windModulationAmount = 0.1f; 158 | float windModulation = 1 - windModulationAmount + Mathf.PerlinNoise(Time.time * windModulationSpeed, 0) * windModulationAmount; 159 | return Mathf.Lerp(1, windModulation, Mathf.Clamp01((float)FlightGlobals.ActiveVessel.atmDensity)); 160 | } 161 | 162 | public void LateUpdate() 163 | { 164 | if (gamePaused || !HighLogic.LoadedSceneIsFlight) return; 165 | 166 | if (!Settings.EnableAudioEffects || Mixer == null) 167 | { 168 | // TODO: some kind of latch so this only runs once 169 | foreach (var sourceObj in FindObjectsOfType(typeof(AudioSource))) 170 | { 171 | AudioSource source = (AudioSource)sourceObj; 172 | if (source != null) source.outputAudioMixerGroup = null; 173 | } 174 | managedSources.Clear(); 175 | 176 | return; 177 | } 178 | 179 | // NOTE: the generic (strongly typed) version of FindObjectsOfType is slower! 180 | foreach (var sourceObj in FindObjectsOfType(typeof(AudioSource))) 181 | { 182 | AudioSource source = (AudioSource)sourceObj; 183 | 184 | int instanceID = source.GetInstanceID(); 185 | 186 | // handle deleted sources 187 | if (instanceID == 0) 188 | { 189 | continue; 190 | } 191 | 192 | // if the source was already in the set, we're done 193 | if (!managedSources.Add(instanceID)) continue; 194 | 195 | // assume this source is a GUI source and ignore 196 | if (source.transform.position == Vector3.zero || source.spatialBlend == 0) 197 | { 198 | continue; 199 | } 200 | 201 | if (source.name.Contains(AudioUtility.RSETag)) continue; 202 | 203 | if (source.GetComponentInParent()) 204 | { 205 | source.outputAudioMixerGroup = InteriorMixer; 206 | continue; 207 | } 208 | 209 | Part sourcePart; 210 | if (sourcePart = source.GetComponentInParent()) 211 | { 212 | source.outputAudioMixerGroup = sourcePart?.vessel == FlightGlobals.ActiveVessel ? FocusMixer : ExteriorMixer; 213 | 214 | var partAudioManager = sourcePart.GetComponent(); 215 | 216 | if (Settings.MufflerQuality > AudioMufflerQuality.Normal && Settings.MachEffectsAmount > 0) 217 | { 218 | if (partAudioManager == null) 219 | { 220 | partAudioManager = sourcePart.gameObject.AddComponent(); 221 | partAudioManager.Initialize(sourcePart, source); 222 | } 223 | } 224 | else if (partAudioManager != null) 225 | { 226 | Component.Destroy(partAudioManager); 227 | } 228 | continue; 229 | } 230 | 231 | source.outputAudioMixerGroup = ExteriorMixer; 232 | if (Settings.MufflerQuality == AudioMufflerQuality.AirSim && source.gameObject.GetComponents().Length == 1) 233 | { 234 | var airSimFilter = source.gameObject.AddOrGetComponent(); 235 | airSimFilter.EnableLowpassFilter = true; 236 | airSimFilter.SimulationUpdate = AirSimulationUpdate.Basic; 237 | airSimFilter.MaxDistance = Settings.AirSimMaxDistance; 238 | airSimFilter.FarLowpass = Settings.AirSimFarLowpass; 239 | 240 | airSimFilter.StartCoroutine(airSimFilter.UpdateDistance()); 241 | } 242 | } 243 | 244 | float atmDensityClamped = Mathf.Clamp01((float)FlightGlobals.ActiveVessel.atmDensity); 245 | float atmCutOff = Mathf.Lerp(Settings.MufflerExternalMode, 30000, atmDensityClamped) * WindModulation(); 246 | float focusOutsideMuffling = Settings.ClampActiveVesselMuffling ? Mathf.Clamp(atmCutOff, Settings.MufflerInternalMode, 30000) : atmCutOff; 247 | float focusMuffling = InternalCamera.Instance.isActive ? Settings.MufflerInternalMode : focusOutsideMuffling; 248 | 249 | if (MapView.MapCamera.isActiveAndEnabled) focusMuffling = Mathf.Min(Settings.MufflerInternalMode, atmCutOff); 250 | 251 | MufflingFrequency = Mathf.MoveTowards(lastCutoffFreq, Mathf.Min(atmCutOff, focusMuffling), 5000); 252 | FocusMufflingFrequency = Mathf.MoveTowards(lastInteriorCutoffFreq, focusMuffling, 5000); 253 | lastCutoffFreq = MufflingFrequency; 254 | lastInteriorCutoffFreq = FocusMufflingFrequency; 255 | 256 | Mixer.SetFloat("ExteriorCutoff", Mathf.Clamp(MufflingFrequency, 10, 22000)); 257 | Mixer.SetFloat("FocusCutoff", Mathf.Clamp(FocusMufflingFrequency, 10, 22000)); 258 | 259 | Mixer.SetFloat("ExteriorVolume", Mathf.Lerp(-80, 0, Mathf.Clamp01(MufflingFrequency / 50))); 260 | Mixer.SetFloat("FocusVolume", Mathf.Lerp(-80, 0, Mathf.Clamp01(FocusMufflingFrequency / 50))); 261 | } 262 | 263 | private void OnDestroy() 264 | { 265 | AudioListener.volume = 0; // Temp fix for sound stuttering between scene changes 266 | 267 | GameEvents.onGamePause.Remove(OnGamePause); 268 | GameEvents.onGameUnpause.Remove(OnGameUnpause); 269 | 270 | instance = null; 271 | } 272 | } 273 | 274 | class RSE_PartAudioManager : MonoBehaviour 275 | { 276 | Part part; 277 | ShipEffects shipEffects; 278 | AudioSource source; 279 | float managedMinDistance; 280 | 281 | public void Initialize(Part part, AudioSource source) 282 | { 283 | this.part = part; 284 | this.source = source; 285 | managedMinDistance = source.minDistance; 286 | 287 | // The root gameobject of a vessel holds both the vessel component and the part component 288 | // The part component is created and destroyed as the vessel is loaded and unloaded but the gameobject is never destroyed (until the vessel is...) 289 | // So we need to make sure to delete the RSE_PartAudioManager when the part is destroyed. 290 | part.OnJustAboutToBeDestroyed += OnPartDestroyed; 291 | } 292 | 293 | private void OnPartDestroyed() 294 | { 295 | Destroy(this); 296 | } 297 | 298 | void LateUpdate() 299 | { 300 | // the vessel object may change on decoupling etc so we can't just cache the shipEffects object 301 | part.vessel.GetComponentCached(ref shipEffects); 302 | 303 | float machPass = shipEffects.MachPass; 304 | source.minDistance = managedMinDistance * machPass; 305 | } 306 | } 307 | } 308 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/RocketSoundEnhancement.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {BBC72A52-EE4F-4DC0-9845-4350A54AC1CD} 4 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 5 | Release 6 | AnyCPU 7 | Library 8 | RocketSoundEnhancement 9 | RocketSoundEnhancement 10 | v4.7.2 11 | Properties 12 | False 13 | False 14 | False 15 | False 16 | obj\$(Configuration)\ 17 | 4 18 | 19 | 20 | 21 | 22 | AnyCPU 23 | 4194304 24 | False 25 | Auto 26 | 4096 27 | 28 | 29 | ..\GameData\RocketSoundEnhancement\Plugins\ 30 | True 31 | pdbonly 32 | False 33 | True 34 | DEBUG;TRACE;ENABLE_PROFILER;DEVELOPMENT 35 | obj\ 36 | 37 | 38 | ..\GameData\RocketSoundEnhancement\Plugins\ 39 | False 40 | None 41 | True 42 | False 43 | TRACE 44 | 45 | 46 | 47 | 48 | 49 | ..\..\GameData\RocketSoundEnhancement\Plugins\ 50 | portable 51 | true 52 | 53 | 54 | ..\..\GameData\RocketSoundEnhancement\Plugins\ 55 | portable 56 | 57 | 58 | 59 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\Assembly-CSharp.dll 60 | False 61 | 62 | 63 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\Assembly-CSharp-firstpass.dll 64 | False 65 | 66 | 67 | 68 | 3.5 69 | 70 | 71 | 72 | 3.5 73 | 74 | 75 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.dll 76 | False 77 | 78 | 79 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.AnimationModule.dll 80 | False 81 | 82 | 83 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.AssetBundleModule.dll 84 | False 85 | 86 | 87 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.AudioModule.dll 88 | False 89 | 90 | 91 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.CoreModule.dll 92 | False 93 | 94 | 95 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.IMGUIModule.dll 96 | False 97 | 98 | 99 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.PhysicsModule.dll 100 | False 101 | 102 | 103 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.UI.dll 104 | False 105 | 106 | 107 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.UIModule.dll 108 | False 109 | 110 | 111 | ..\..\..\..\Kerbal Space Program\KSP 1.12.3\KSP_x64_Data\Managed\UnityEngine.VehiclesModule.dll 112 | False 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | {5dff0176-7ba8-49f4-8155-f5d9b37d7d3d} 144 | RocketSoundEnhancement.Unity 145 | False 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/Settings.cs: -------------------------------------------------------------------------------- 1 | using KSP.UI.Screens; 2 | using RocketSoundEnhancement.Unity; 3 | using System; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | 7 | namespace RocketSoundEnhancement 8 | { 9 | public static class Settings 10 | { 11 | public static string ModPath = "GameData/RocketSoundEnhancement/"; 12 | public static string SettingsNodeName = "RSE_SETTINGS"; 13 | public static int VoiceCount = 32; 14 | 15 | public static Dictionary CollisionData = new Dictionary(); 16 | public static Dictionary CustomAudioSources = new Dictionary(); 17 | public static Dictionary CustomAudioClips = new Dictionary(); 18 | 19 | public static AudioMufflerQuality MufflerQuality = AudioMufflerQuality.Normal; 20 | 21 | public static bool EnableAudioEffects = true; 22 | public static bool EnableCustomLimiter = false; 23 | public static bool DisableStagingSound = false; 24 | public static bool ClampActiveVesselMuffling = false; 25 | 26 | public static float DopplerFactor = 1f; 27 | 28 | public static float InteriorVolume = 1; 29 | public static float ExteriorVolume = 1; 30 | 31 | public static float AutoLimiter = 0.5f; 32 | public static float LimiterThreshold = 0; 33 | public static float LimiterGain = 0; 34 | public static float LimiterAttack = 10; 35 | public static float LimiterRelease = 20; 36 | 37 | public static float MufflerInternalMode = 1500; 38 | public static float MufflerExternalMode = 22000; 39 | public static float MachEffectsAmount = 0.9f; 40 | public static float MachEffectLowerLimit 41 | { 42 | get { 43 | return (1 - Mathf.Log10(Mathf.Lerp(0.1f, 10, MachEffectsAmount))) * 0.5f; 44 | } 45 | } 46 | 47 | // reference: https://codeandsound.files.wordpress.com/2014/08/att21.png 48 | public static float AirSimMaxDistance = 1000; 49 | public static float AirSimFarLowpass = 1000; 50 | public static float AirSimMaxCombDelay = 20; 51 | public static float AirSimMaxCombMix = 0.25f; 52 | public static float AirSimMaxDistortion = 0.5f; 53 | 54 | private static bool initialized; 55 | private static ConfigNode settingsConfigNode; 56 | public static void SetLimiterDefaults() 57 | { 58 | EnableCustomLimiter = false; 59 | AutoLimiter = 0.5f; 60 | LimiterThreshold = 0; 61 | LimiterGain = 0; 62 | LimiterAttack = 10; 63 | LimiterRelease = 20; 64 | } 65 | 66 | public static void SetMufflerDefaults() 67 | { 68 | MufflerInternalMode = 1500; 69 | MufflerExternalMode = 1000; 70 | } 71 | 72 | private static void LoadLimiter(ConfigNode settingsNode) 73 | { 74 | if (!settingsNode.HasNode("LIMITER")) 75 | { 76 | SetLimiterDefaults(); 77 | var defaultLimiterNode = settingsNode.AddNode("LIMITER"); 78 | defaultLimiterNode.AddValue("EnableCustomLimiter", EnableCustomLimiter); 79 | defaultLimiterNode.AddValue("AutoLimiter", AutoLimiter); 80 | defaultLimiterNode.AddValue("Threshold", LimiterThreshold); 81 | defaultLimiterNode.AddValue("Gain", LimiterGain); 82 | defaultLimiterNode.AddValue("Attack", LimiterAttack); 83 | defaultLimiterNode.AddValue("Attack", LimiterRelease); 84 | return; 85 | } 86 | 87 | var limiterNode = settingsNode.GetNode("LIMITER"); 88 | if (!limiterNode.HasValue("EnableCustomLimiter") || !bool.TryParse(limiterNode.GetValue("EnableCustomLimiter"), out EnableCustomLimiter)) 89 | limiterNode.AddValue("EnableCustomLimiter", EnableCustomLimiter); 90 | 91 | if (!limiterNode.HasValue("AutoLimiter") || !float.TryParse(limiterNode.GetValue("AutoLimiter"), out AutoLimiter)) 92 | limiterNode.AddValue("AutoLimiter", AutoLimiter); 93 | 94 | if (!limiterNode.HasValue("Threshold") || !float.TryParse(limiterNode.GetValue("Threshold"), out LimiterThreshold)) 95 | limiterNode.AddValue("Threshold", LimiterThreshold); 96 | 97 | if (!limiterNode.HasValue("Gain") || !float.TryParse(limiterNode.GetValue("Gain"), out LimiterGain)) 98 | limiterNode.AddValue("Gain", LimiterGain); 99 | 100 | if (!limiterNode.HasValue("Attack") || !float.TryParse(limiterNode.GetValue("Attack"), out LimiterAttack)) 101 | limiterNode.AddValue("Attack", LimiterAttack); 102 | 103 | if (!limiterNode.HasValue("Release") || !float.TryParse(limiterNode.GetValue("Release"), out LimiterRelease)) 104 | limiterNode.AddValue("Attack", LimiterRelease); 105 | } 106 | 107 | private static void LoadMuffler(ConfigNode settingsNode) 108 | { 109 | if (!settingsNode.HasNode("MUFFLER")) 110 | { 111 | SetMufflerDefaults(); 112 | var defaultMufflerNode = settingsNode.AddNode("MUFFLER"); 113 | defaultMufflerNode.AddValue("ClampActiveVesselMuffling", ClampActiveVesselMuffling); 114 | defaultMufflerNode.AddValue("MufflerQuality", MufflerQuality); 115 | defaultMufflerNode.AddValue("InternalMode", MufflerInternalMode); 116 | defaultMufflerNode.AddValue("ExternalMode", MufflerExternalMode); 117 | defaultMufflerNode.AddValue("MachEffectsAmount", MachEffectsAmount); 118 | return; 119 | } 120 | 121 | var mufflerNode = settingsNode.GetNode("MUFFLER"); 122 | if (!mufflerNode.HasValue("ClampActiveVesselMuffling") || !bool.TryParse(mufflerNode.GetValue("ClampActiveVesselMuffling"), out ClampActiveVesselMuffling)) 123 | mufflerNode.AddValue("ClampActiveVesselMuffling", ClampActiveVesselMuffling); 124 | 125 | if (mufflerNode.HasValue("MufflerQuality")) 126 | { 127 | if (!Enum.TryParse(mufflerNode.GetValue("MufflerQuality"), true, out MufflerQuality)) 128 | { 129 | MufflerQuality = AudioMufflerQuality.Normal; 130 | } 131 | } 132 | else 133 | { 134 | mufflerNode.AddValue("MufflerQuality", MufflerQuality); 135 | } 136 | 137 | if (!mufflerNode.HasValue("InternalMode") || !float.TryParse(mufflerNode.GetValue("InternalMode"), out MufflerInternalMode)) 138 | mufflerNode.AddValue("InternalMode", MufflerInternalMode); 139 | 140 | if (!mufflerNode.HasValue("ExternalMode") || !float.TryParse(mufflerNode.GetValue("ExternalMode"), out MufflerExternalMode)) 141 | mufflerNode.AddValue("ExternalMode", MufflerExternalMode); 142 | 143 | if (!mufflerNode.HasValue("DopplerFactor") || !float.TryParse(mufflerNode.GetValue("DopplerFactor"), out DopplerFactor)) 144 | mufflerNode.AddValue("DopplerFactor", DopplerFactor); 145 | 146 | if (!mufflerNode.HasValue("MachEffectsAmount") || !float.TryParse(mufflerNode.GetValue("MachEffectsAmount"), out MachEffectsAmount)) 147 | mufflerNode.AddValue("MachEffectsAmount", MachEffectsAmount); 148 | } 149 | 150 | public static void Load() 151 | { 152 | CustomAudioSources.Clear(); 153 | CustomAudioClips.Clear(); 154 | CollisionData.Clear(); 155 | 156 | settingsConfigNode = ConfigNode.Load(ModPath + "Settings.cfg"); 157 | if (settingsConfigNode == null) 158 | { 159 | Debug.LogError("[RSE]: Settings.cfg not found! using internal settings"); 160 | settingsConfigNode = new ConfigNode(); 161 | settingsConfigNode.AddNode(SettingsNodeName); 162 | } 163 | 164 | var settingsNode = settingsConfigNode.GetNode(SettingsNodeName); 165 | 166 | if (!settingsNode.HasValue("EnableAudioEffects")) settingsNode.AddValue("EnableAudioEffects", true); 167 | bool.TryParse(settingsNode.GetValue("EnableAudioEffects"), out EnableAudioEffects); 168 | 169 | if (!settingsNode.HasValue("DisableStagingSound") || !bool.TryParse(settingsNode.GetValue("DisableStagingSound"), out DisableStagingSound)) 170 | settingsNode.AddValue("DisableStagingSound", DisableStagingSound); 171 | 172 | if (settingsNode.HasValue("ExteriorVolume") && !float.TryParse(settingsNode.GetValue("ExteriorVolume"), out ExteriorVolume)) ExteriorVolume = 1; 173 | if (settingsNode.HasValue("InteriorVolume") && !float.TryParse(settingsNode.GetValue("InteriorVolume"), out InteriorVolume)) InteriorVolume = 1; 174 | 175 | 176 | if (settingsNode.HasNode("Colliders")) 177 | { 178 | var colNode = settingsNode.GetNode("Colliders"); 179 | foreach (ConfigNode.Value node in colNode.values) 180 | { 181 | CollidingObject colDataType; 182 | if (!CollisionData.ContainsKey(node.name) && Enum.TryParse(node.value, true, out colDataType)) 183 | CollisionData.Add(node.name, colDataType); 184 | } 185 | } 186 | else 187 | { 188 | var defaultColNode = settingsNode.AddNode("Colliders"); 189 | defaultColNode.AddValue("default", CollidingObject.Concrete); 190 | CollisionData.Add("default", CollidingObject.Concrete); 191 | } 192 | 193 | if (!settingsNode.HasNode("CustomMixerRouting")) settingsNode.AddNode("CustomMixerRouting"); 194 | 195 | var mixerRoutingNode = settingsNode.nodes.GetNode("CustomMixerRouting"); 196 | if (mixerRoutingNode.HasNode("AudioSources")) 197 | { 198 | var sourcesNode = mixerRoutingNode.GetNode("AudioSources"); 199 | foreach (ConfigNode.Value node in sourcesNode.values) 200 | { 201 | MixerGroup channel; 202 | if (!CustomAudioSources.ContainsKey(node.name) && Enum.TryParse(node.value, true, out channel)) 203 | CustomAudioSources.Add(node.name, channel); 204 | } 205 | } 206 | else 207 | { 208 | var defaultSourcesNode = mixerRoutingNode.AddNode("AudioSources"); 209 | defaultSourcesNode.AddValue("MusicLogic", MixerGroup.Ignore); 210 | defaultSourcesNode.AddValue("SoundtrackEditor", MixerGroup.Ignore); 211 | defaultSourcesNode.AddValue("PartActionController(Clone)", MixerGroup.Ignore); 212 | CustomAudioSources.Add("MusicLogic", MixerGroup.Ignore); 213 | CustomAudioSources.Add("SoundtrackEditor", MixerGroup.Ignore); 214 | CustomAudioSources.Add("PartActionController", MixerGroup.Ignore); 215 | } 216 | 217 | if (mixerRoutingNode.HasNode("AudioClips")) 218 | { 219 | var clipsNode = mixerRoutingNode.GetNode("AudioClips"); 220 | foreach (ConfigNode.Value node in clipsNode.values) 221 | { 222 | MixerGroup channel; 223 | if (!CustomAudioClips.ContainsKey(node.name) && Enum.TryParse(node.value, true, out channel)) 224 | CustomAudioClips.Add(node.name, channel); 225 | } 226 | } 227 | else 228 | { 229 | mixerRoutingNode.AddNode("AudioClips"); 230 | } 231 | 232 | LoadLimiter(settingsNode); 233 | LoadMuffler(settingsNode); 234 | 235 | settingsConfigNode.Save(ModPath + "Settings.cfg"); 236 | initialized = true; 237 | } 238 | 239 | public static void Save() 240 | { 241 | if (!initialized) Load(); 242 | 243 | var settingsNode = settingsConfigNode.GetNode(SettingsNodeName); 244 | 245 | settingsNode.SetValue("EnableAudioEffects", EnableAudioEffects, true); 246 | settingsNode.SetValue("ExteriorVolume", ExteriorVolume, true); 247 | settingsNode.SetValue("InteriorVolume", InteriorVolume, true); 248 | settingsNode.SetValue("DisableStagingSound", DisableStagingSound, true); 249 | 250 | var limiterNode = settingsNode.GetNode("LIMITER"); 251 | limiterNode.SetValue("EnableCustomLimiter", EnableCustomLimiter); 252 | limiterNode.SetValue("AutoLimiter", AutoLimiter); 253 | limiterNode.SetValue("Threshold", LimiterThreshold); 254 | limiterNode.SetValue("Gain", LimiterGain); 255 | limiterNode.SetValue("Attack", LimiterAttack); 256 | limiterNode.SetValue("Release", LimiterRelease); 257 | 258 | var mufflerNode = settingsNode.GetNode("MUFFLER"); 259 | mufflerNode.SetValue("MufflerQuality", MufflerQuality.ToString(), true); 260 | mufflerNode.SetValue("ClampActiveVesselMuffling", ClampActiveVesselMuffling, true); 261 | mufflerNode.SetValue("InternalMode", MufflerInternalMode, true); 262 | mufflerNode.SetValue("ExternalMode", MufflerExternalMode, true); 263 | mufflerNode.SetValue("DopplerFactor", DopplerFactor, true); 264 | mufflerNode.SetValue("MachEffectsAmount", MachEffectsAmount, true); 265 | 266 | settingsConfigNode.Save(ModPath + "Settings.cfg"); 267 | } 268 | } 269 | } -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/SettingsPanel.cs: -------------------------------------------------------------------------------- 1 | using KSP.UI.Screens; 2 | using UnityEngine; 3 | using RocketSoundEnhancement.Unity; 4 | using System.Reflection; 5 | using System; 6 | using KSP.UI; 7 | 8 | namespace RocketSoundEnhancement 9 | { 10 | [KSPAddon(KSPAddon.Startup.Flight, false)] 11 | public class SettingsPanel : MonoBehaviour, ISettingsPanel 12 | { 13 | private SettingsPanel instance; 14 | public SettingsPanel Instance { get { return instance; } } 15 | public float CanvasScale => GameSettings.UI_SCALE; 16 | 17 | public ApplicationLauncherButton AppButton; 18 | public Texture AppIcon = GameDatabase.Instance.GetTexture("RocketSoundEnhancement/Textures/RSE_Icon", false); 19 | 20 | private RSE_Panel panelController; 21 | private GameObject rse_PanelPrefab; 22 | private Vector2 panelPosition = Vector2.zero; 23 | public GameObject RSE_PanelPrefab 24 | { 25 | get 26 | { 27 | if (rse_PanelPrefab == null) 28 | { 29 | rse_PanelPrefab = RocketSoundEnhancement.RSE_Bundle.LoadAsset("RSE_Panel") as GameObject; 30 | } 31 | return rse_PanelPrefab; 32 | } 33 | } 34 | 35 | public string Version => version; 36 | public string version; 37 | public bool EnableAudioEffects { get => Settings.EnableAudioEffects; set => Settings.EnableAudioEffects = value; } 38 | public bool DisableStagingSound { get => Settings.DisableStagingSound; set => Settings.DisableStagingSound = value; } 39 | public float InteriorVolume { get => Settings.InteriorVolume; set => Settings.InteriorVolume = value; } 40 | public float ExteriorVolume { get => Settings.ExteriorVolume; set => Settings.ExteriorVolume = value; } 41 | public AudioMufflerQuality MufflerQuality { get => Settings.MufflerQuality; set => Settings.MufflerQuality = value; } 42 | public float MufflerExternalMode { get => Settings.MufflerExternalMode; set => Settings.MufflerExternalMode = value; } 43 | public float MufflerInternalMode { get => Settings.MufflerInternalMode; set => Settings.MufflerInternalMode = value; } 44 | public float MachEffectsAmount { get => Settings.MachEffectsAmount; set => Settings.MachEffectsAmount = value; } 45 | public float DopplerFactor { get => Settings.DopplerFactor; set => Settings.DopplerFactor = value; } 46 | public bool ClampActiveVesselMuffling { get => Settings.ClampActiveVesselMuffling; set => Settings.ClampActiveVesselMuffling = value; } 47 | public bool EnableCustomLimiter 48 | { 49 | get => Settings.EnableCustomLimiter; 50 | set 51 | { 52 | Settings.EnableCustomLimiter = value; 53 | RocketSoundEnhancement.instance.UpdateLimiter(); 54 | } 55 | } 56 | public float AutoLimiter 57 | { 58 | get => Settings.AutoLimiter; 59 | set 60 | { 61 | Settings.AutoLimiter = value; 62 | RocketSoundEnhancement.instance.UpdateLimiter(); 63 | } 64 | } 65 | public float LimiterThreshold 66 | { 67 | get => Settings.LimiterThreshold; 68 | set 69 | { 70 | Settings.LimiterThreshold = value; 71 | RocketSoundEnhancement.instance.UpdateLimiter(); 72 | } 73 | } 74 | public float LimiterGain 75 | { 76 | get => Settings.LimiterGain; 77 | set 78 | { 79 | Settings.LimiterGain = value; 80 | RocketSoundEnhancement.instance.UpdateLimiter(); 81 | } 82 | } 83 | public float LimiterAttack 84 | { 85 | get => Settings.LimiterAttack; 86 | set 87 | { 88 | Settings.LimiterAttack = value; 89 | RocketSoundEnhancement.instance.UpdateLimiter(); 90 | } 91 | } 92 | public float LimiterRelease 93 | { 94 | get => Settings.LimiterRelease; 95 | set 96 | { 97 | Settings.LimiterRelease = value; 98 | RocketSoundEnhancement.instance.UpdateLimiter(); 99 | } 100 | } 101 | 102 | private void Awake() 103 | { 104 | if (instance != null) Destroy(instance); 105 | 106 | instance = this; 107 | 108 | Assembly assembly = AssemblyLoader.loadedAssemblies.GetByAssembly(Assembly.GetExecutingAssembly()).assembly; 109 | var assemblyInformantion = Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute; 110 | version = assemblyInformantion != null ? assemblyInformantion.InformationalVersion : ""; 111 | } 112 | 113 | private void Start() 114 | { 115 | if (AppButton == null) 116 | { 117 | AppButton = ApplicationLauncher.Instance.AddModApplication( 118 | () => OpenSettingsPanel(), 119 | () => CloseSettingsPanel(), 120 | null, null, 121 | null, null, 122 | ApplicationLauncher.AppScenes.FLIGHT, AppIcon 123 | ); 124 | } 125 | } 126 | 127 | public void OpenSettingsPanel() 128 | { 129 | if (RSE_PanelPrefab == null) return; 130 | 131 | GameObject panelPrefab = Instantiate(RSE_PanelPrefab, Vector3.zero, Quaternion.identity) as GameObject; 132 | panelPrefab.transform.SetParent(UIMasterController.Instance.dialogCanvas.transform, false); 133 | panelPrefab.transform.SetAsFirstSibling(); 134 | panelController = panelPrefab.GetComponent(); 135 | 136 | if (panelController == null) return; 137 | panelController.transform.position = panelPosition; 138 | panelController.Initialize(Instance); 139 | } 140 | 141 | public void CloseSettingsPanel() 142 | { 143 | if (panelController != null) 144 | { 145 | panelPosition = panelController.transform.position; 146 | GameObject.Destroy(panelController.gameObject); 147 | } 148 | } 149 | 150 | public void LoadSettings() 151 | { 152 | Settings.Load(); 153 | RocketSoundEnhancement.Instance.ApplySettings(); 154 | } 155 | 156 | public void SaveSettings() 157 | { 158 | Settings.Save(); 159 | RocketSoundEnhancement.Instance.ApplySettings(); 160 | CloseSettingsPanel(); 161 | } 162 | public void ClampToScreen(RectTransform rect) 163 | { 164 | UIMasterController.ClampToScreen(rect, Vector2.zero); 165 | } 166 | 167 | private void OnDestroy() 168 | { 169 | if (panelController != null) 170 | UnityEngine.Object.Destroy(panelController.gameObject); 171 | 172 | if (AppButton != null) 173 | { 174 | ApplicationLauncher.Instance.RemoveModApplication(AppButton); 175 | AppButton = null; 176 | } 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/ShipEffectsConfig.cs: -------------------------------------------------------------------------------- 1 | using KSP.UI.Screens; 2 | using System.Collections.Generic; 3 | 4 | namespace RocketSoundEnhancement 5 | { 6 | public static class ShipEffectsConfig 7 | { 8 | public static bool MuteStockAeroSounds = false; 9 | 10 | private static List _shipEffectsNodes = new List(); 11 | public static List ShipEffectsConfigNode 12 | { 13 | get 14 | { 15 | if (_shipEffectsNodes.Count == 0) 16 | { 17 | foreach (var configNode in GameDatabase.Instance.GetConfigNodes("SHIPEFFECTS_SOUNDLAYERS")) 18 | { 19 | _shipEffectsNodes.AddRange(configNode.GetNodes()); 20 | } 21 | } 22 | 23 | return _shipEffectsNodes; 24 | } 25 | } 26 | 27 | public static void Load() 28 | { 29 | foreach (var configNode in GameDatabase.Instance.GetConfigNodes("SHIPEFFECTS_SOUNDLAYERS")) 30 | { 31 | if (configNode.HasValue("MuteStockAeroSounds")) 32 | bool.TryParse(configNode.GetValue("MuteStockAeroSounds"), out MuteStockAeroSounds); 33 | if (configNode.HasValue("nextStageClip")) 34 | StageManager.Instance.nextStageClip = GameDatabase.Instance.GetAudioClip(configNode.GetValue("nextStageClip")); 35 | if (configNode.HasValue("cannotSeparateClip")) 36 | StageManager.Instance.cannotSeparateClip = GameDatabase.Instance.GetAudioClip(configNode.GetValue("cannotSeparateClip")); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Source/RocketSoundEnhancement/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using UnityEngine; 7 | 8 | namespace RocketSoundEnhancement 9 | { 10 | [KSPAddon(KSPAddon.Startup.Instantly, true)] 11 | class Startup : MonoBehaviour 12 | { 13 | void Awake() 14 | { 15 | AudioConfiguration audioConfig = AudioSettings.GetConfiguration(); 16 | audioConfig.numRealVoices = Settings.VoiceCount; 17 | 18 | if(AudioSettings.Reset(audioConfig)) { 19 | Debug.Log("[RSE]: Audio Settings Applied"); 20 | Debug.Log("[RSE]: DSP Buffer Size : " + AudioSettings.GetConfiguration().dspBufferSize); 21 | Debug.Log("[RSE]: Real Voices : " + AudioSettings.GetConfiguration().numRealVoices); 22 | Debug.Log("[RSE]: Virtual Voices : " + AudioSettings.GetConfiguration().numVirtualVoices); 23 | Debug.Log("[RSE]: Samplerate : " + AudioSettings.GetConfiguration().sampleRate); 24 | Debug.Log("[RSE]: Spearker Mode : " + AudioSettings.GetConfiguration().speakerMode); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/AssetBundles/AssetBundles: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/AssetBundles/AssetBundles -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/AssetBundles/AssetBundles.manifest: -------------------------------------------------------------------------------- 1 | ManifestFileVersion: 0 2 | CRC: 3174496561 3 | AssetBundleManifest: 4 | AssetBundleInfos: 5 | Info_0: 6 | Name: rse_bundle 7 | Dependencies: {} 8 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/AssetBundles/rse_bundle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/AssetBundles/rse_bundle -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/AssetBundles/rse_bundle.manifest: -------------------------------------------------------------------------------- 1 | ManifestFileVersion: 0 2 | CRC: 1027181760 3 | Hashes: 4 | AssetFileHash: 5 | serializedVersion: 2 6 | Hash: 8435c1e774ddbe59457a4acdb6de6242 7 | TypeTreeHash: 8 | serializedVersion: 2 9 | Hash: cb20c6233195d7ed8e51fd5c4071f4d5 10 | HashAppended: 0 11 | ClassTypes: 12 | - Class: 1 13 | Script: {instanceID: 0} 14 | - Class: 21 15 | Script: {instanceID: 0} 16 | - Class: 28 17 | Script: {instanceID: 0} 18 | - Class: 48 19 | Script: {instanceID: 0} 20 | - Class: 114 21 | Script: {fileID: 11500000, guid: 67db9e8f0e2ae9c40bc1e2b64352a6b4, type: 3} 22 | - Class: 114 23 | Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3} 24 | - Class: 114 25 | Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 26 | - Class: 114 27 | Script: {fileID: 1096701715, guid: 0e52c662bd1351044ae9c9fb5c8ddffb, type: 3} 28 | - Class: 114 29 | Script: {fileID: -1886210225, guid: 0e52c662bd1351044ae9c9fb5c8ddffb, type: 3} 30 | - Class: 114 31 | Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} 32 | - Class: 114 33 | Script: {fileID: 11500000, guid: 306cc8c2b49d7114eaa3623786fc2126, type: 3} 34 | - Class: 114 35 | Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} 36 | - Class: 114 37 | Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3} 38 | - Class: 114 39 | Script: {fileID: 11500000, guid: 30649d3a9faa99c48a7b1166b86bf2a0, type: 3} 40 | - Class: 114 41 | Script: {fileID: 11500000, guid: 9085046f02f69544eb97fd06b6048fe2, type: 3} 42 | - Class: 114 43 | Script: {fileID: 11500000, guid: 2fafe2cfe61f6974895a912c3755e8f1, type: 3} 44 | - Class: 115 45 | Script: {instanceID: 0} 46 | - Class: 128 47 | Script: {instanceID: 0} 48 | - Class: 213 49 | Script: {instanceID: 0} 50 | - Class: 222 51 | Script: {instanceID: 0} 52 | - Class: 224 53 | Script: {instanceID: 0} 54 | - Class: 241 55 | Script: {instanceID: 0} 56 | - Class: 243 57 | Script: {instanceID: 0} 58 | - Class: 245 59 | Script: {instanceID: 0} 60 | SerializeReferenceClassIdentifiers: [] 61 | Assets: 62 | - Assets/RSE_Mixer.mixer 63 | - Assets/RSE_Panel.prefab 64 | Dependencies: [] 65 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Editor/Bundler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | public class Bundler 7 | { 8 | const string dir = "AssetBundles"; 9 | [MenuItem("Bundler/Build Bundles")] 10 | static void BuildAssetBundles() 11 | { 12 | BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.ForceRebuildAssetBundle, BuildTarget.StandaloneWindows); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Editor/KSPCurveEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using UnityEditorInternal; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | namespace MuMech 10 | { 11 | 12 | public class KSPCurveEditor : EditorWindow 13 | { 14 | [MenuItem("KSP/Curve Editor")] 15 | static void Init() 16 | { 17 | EditorWindow.GetWindow(typeof(KSPCurveEditor)); 18 | } 19 | 20 | AnimationCurve curve = new AnimationCurve(); 21 | Vector2 scrollPos = new Vector2(); 22 | string textVersion; 23 | List points = new List(); 24 | bool curveNeedsUpdate = false, textChanged = false; 25 | float lastCurve = 0; 26 | 27 | void OnGUI() 28 | { 29 | textChanged = false; 30 | 31 | GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.Height(50)); 32 | EditorGUILayout.LabelField("Click curve to edit ->", GUILayout.ExpandWidth(false)); 33 | curve = EditorGUILayout.CurveField(curve, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 34 | GUILayout.EndHorizontal(); 35 | 36 | string newT = EditorGUILayout.TextArea(textVersion, GUILayout.ExpandWidth(true), GUILayout.Height(100)); 37 | if (newT != textVersion) 38 | { 39 | textVersion = newT; 40 | textChanged = true; 41 | } 42 | 43 | scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); 44 | GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); 45 | 46 | GUILayout.BeginVertical(); 47 | GUILayout.Label("X", GUILayout.ExpandWidth(true)); 48 | foreach (FloatString4 p in points) 49 | { 50 | string ns = EditorGUILayout.TextField(p.strings[0]); 51 | if (ns != p.strings[0]) 52 | { 53 | p.strings[0] = ns; 54 | p.UpdateFloats(); 55 | curveNeedsUpdate = true; 56 | } 57 | 58 | } 59 | GUILayout.EndVertical(); 60 | 61 | GUILayout.BeginVertical(); 62 | GUILayout.Label("Y", GUILayout.ExpandWidth(true)); 63 | foreach (FloatString4 p in points) 64 | { 65 | string ns = EditorGUILayout.TextField(p.strings[1]); 66 | if (ns != p.strings[1]) 67 | { 68 | p.strings[1] = ns; 69 | p.UpdateFloats(); 70 | curveNeedsUpdate = true; 71 | } 72 | 73 | } 74 | GUILayout.EndVertical(); 75 | 76 | GUILayout.BeginVertical(); 77 | GUILayout.Label("Auto", GUILayout.ExpandWidth(true)); 78 | foreach (FloatString4 p in points) 79 | { 80 | bool a = EditorGUILayout.Toggle(p.twoMode); 81 | if (a != p.twoMode) 82 | { 83 | p.twoMode = a; 84 | curveNeedsUpdate = true; 85 | } 86 | 87 | } 88 | GUILayout.EndVertical(); 89 | 90 | GUILayout.BeginVertical(); 91 | GUILayout.Label("In Tangent", GUILayout.ExpandWidth(true)); 92 | foreach (FloatString4 p in points) 93 | { 94 | if (!p.twoMode) 95 | { 96 | string ns = EditorGUILayout.TextField(p.strings[2]); 97 | if (ns != p.strings[2]) 98 | { 99 | p.strings[2] = ns; 100 | p.UpdateFloats(); 101 | curveNeedsUpdate = true; 102 | } 103 | } 104 | else 105 | { 106 | EditorGUILayout.TextField(""); 107 | } 108 | } 109 | GUILayout.EndVertical(); 110 | 111 | GUILayout.BeginVertical(); 112 | GUILayout.Label("Out Tangent", GUILayout.ExpandWidth(true)); 113 | foreach (FloatString4 p in points) 114 | { 115 | if (!p.twoMode) 116 | { 117 | string ns = EditorGUILayout.TextField(p.strings[3]); 118 | if (ns != p.strings[3]) 119 | { 120 | p.strings[3] = ns; 121 | p.UpdateFloats(); 122 | curveNeedsUpdate = true; 123 | } 124 | } 125 | else 126 | { 127 | EditorGUILayout.TextField(""); 128 | } 129 | } 130 | GUILayout.EndVertical(); 131 | 132 | GUILayout.EndHorizontal(); 133 | EditorGUILayout.EndScrollView(); 134 | } 135 | 136 | static float HashAnimationCurve(AnimationCurve c) 137 | { 138 | float h = 0; 139 | 140 | foreach (Keyframe k in c.keys) 141 | { 142 | h += k.time + k.value + k.inTangent + k.outTangent + k.tangentMode; 143 | } 144 | 145 | return h; 146 | } 147 | 148 | void Update() 149 | { 150 | if (textChanged) 151 | { 152 | StringToCurve(textVersion); 153 | } 154 | 155 | if (curveNeedsUpdate) 156 | { 157 | UpdateCurve(); 158 | } 159 | 160 | float newCurve = HashAnimationCurve(curve); 161 | if (lastCurve != newCurve) 162 | { 163 | points = new List(); 164 | 165 | for (int i = 0; i < curve.keys.Length; i++) 166 | { 167 | FloatString4 nv = new FloatString4(curve.keys[i].time, curve.keys[i].value, curve.keys[i].inTangent, curve.keys[i].outTangent, (curve.keys[i].tangentMode == 10)); 168 | nv.UpdateStrings(); 169 | points.Add(nv); 170 | } 171 | 172 | if (!textChanged) 173 | { 174 | textVersion = CurveToString(); 175 | } 176 | 177 | lastCurve = newCurve; 178 | } 179 | } 180 | 181 | string CurveToString() 182 | { 183 | string buff = ""; 184 | foreach (FloatString4 p in points) 185 | { 186 | if (p.twoMode) 187 | { 188 | buff += "key = " + p.floats.x + " " + p.floats.y + "\n"; 189 | } 190 | else 191 | { 192 | buff += "key = " + p.floats.x + " " + p.floats.y + " " + p.floats.z + " " + p.floats.w + "\n"; 193 | } 194 | } 195 | return buff; 196 | } 197 | 198 | void StringToCurve(string data) 199 | { 200 | points = new List(); 201 | 202 | string[] lines = data.Split('\n'); 203 | foreach (string line in lines) 204 | { 205 | string[] pcs = line.Split(new char[] { '=', ' ' }, StringSplitOptions.RemoveEmptyEntries); 206 | if ((pcs.Length >= 3) && (pcs[0] == "key")) 207 | { 208 | FloatString4 nv = new FloatString4(); 209 | if (pcs.Length >= 5) 210 | { 211 | nv.strings = new string[] { pcs[1], pcs[2], pcs[3], pcs[4] }; 212 | nv.twoMode = false; 213 | } 214 | else 215 | { 216 | nv.strings = new string[] { pcs[1], pcs[2], "0", "0" }; 217 | nv.twoMode = true; 218 | } 219 | nv.UpdateFloats(); 220 | points.Add(nv); 221 | } 222 | } 223 | 224 | if (!textChanged) 225 | { 226 | textVersion = CurveToString(); 227 | } 228 | 229 | curveNeedsUpdate = true; 230 | } 231 | 232 | void UpdateCurve() 233 | { 234 | points.Sort(); 235 | 236 | curve = new AnimationCurve(); 237 | 238 | foreach (FloatString4 v in points) 239 | { 240 | Keyframe k = new Keyframe(v.floats.x, v.floats.y, v.floats.z, v.floats.w); 241 | if (v.twoMode) 242 | { 243 | k.tangentMode = 10; 244 | } 245 | else 246 | { 247 | k.tangentMode = 1; 248 | } 249 | curve.AddKey(k); 250 | } 251 | 252 | for (int i = 0; i < curve.keys.Length; i++) 253 | { 254 | if (points[i].twoMode) 255 | { 256 | curve.SmoothTangents(i, 0); 257 | } 258 | } 259 | 260 | if (!textChanged) 261 | { 262 | textVersion = CurveToString(); 263 | } 264 | 265 | lastCurve = HashAnimationCurve(curve); 266 | curveNeedsUpdate = false; 267 | } 268 | } 269 | 270 | public class FloatString4 : IComparable 271 | { 272 | public Vector4 floats; 273 | public string[] strings; 274 | public bool twoMode; 275 | 276 | public int CompareTo(FloatString4 other) 277 | { 278 | if (other == null) return 1; 279 | return floats.x.CompareTo(other.floats.x); 280 | } 281 | 282 | public FloatString4() 283 | { 284 | floats = new Vector4(); 285 | strings = new string[] { "0", "0", "0", "0" }; 286 | twoMode = false; 287 | } 288 | 289 | public FloatString4(float x, float y, float z = 0, float w = 0, bool twoMode = true) 290 | { 291 | floats = new Vector4(x, y, z, w); 292 | this.twoMode = twoMode; 293 | UpdateStrings(); 294 | } 295 | 296 | public void UpdateFloats() 297 | { 298 | float x, y, z, w; 299 | float.TryParse(strings[0], out x); 300 | float.TryParse(strings[1], out y); 301 | float.TryParse(strings[2], out z); 302 | float.TryParse(strings[3], out w); 303 | floats = new Vector4(x, y, z, w); 304 | } 305 | 306 | public void UpdateStrings() 307 | { 308 | strings = new string[] { floats.x.ToString(), floats.y.ToString(), floats.z.ToString(), floats.w.ToString() }; 309 | } 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Editor/UI Colors.colors: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 52 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 12323, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: UI Colors 14 | m_EditorClassIdentifier: 15 | m_Presets: 16 | - m_Name: 17 | m_Color: {r: 1, g: 1, b: 1, a: 1} 18 | - m_Name: 19 | m_Color: {r: 0.16078432, g: 0.16078432, b: 0.18039216, a: 1} 20 | - m_Name: 21 | m_Color: {r: 0.11764707, g: 0.26666668, b: 0.37647063, a: 1} 22 | - m_Name: 23 | m_Color: {r: 0, g: 0.5372549, b: 0.9607844, a: 1} 24 | - m_Name: 25 | m_Color: {r: 0.40784317, g: 0.7254902, b: 0.9686275, a: 1} 26 | - m_Name: 27 | m_Color: {r: 0.18039216, g: 0.20000002, b: 0.23529413, a: 1} 28 | - m_Name: 29 | m_Color: {r: 0.2901961, g: 0.33333334, b: 0.38823533, a: 1} 30 | - m_Name: 31 | m_Color: {r: 0.38823533, g: 0.41176474, b: 0.45098042, a: 1} 32 | - m_Name: 33 | m_Color: {r: 0.5176471, g: 0.54901963, b: 0.59607846, a: 1} 34 | - m_Name: 35 | m_Color: {r: 0.57254905, g: 0.2627451, b: 0.03137255, a: 1} 36 | - m_Name: 37 | m_Color: {r: 0.7019608, g: 0.3137255, b: 0.03137255, a: 1} 38 | - m_Name: 39 | m_Color: {r: 0.8705883, g: 0.47058827, b: 0.12941177, a: 1} 40 | - m_Name: 41 | m_Color: {r: 1, g: 0.5901467, b: 0.24056602, a: 1} 42 | - m_Name: 43 | m_Color: {r: 0.6084906, g: 0.8302548, b: 1, a: 1} 44 | - m_Name: 45 | m_Color: {r: 0.23137257, g: 0.22352943, b: 0.2509804, a: 1} 46 | - m_Name: 47 | m_Color: {r: 0.61960787, g: 0.13333334, b: 0.14117648, a: 1} 48 | - m_Name: 49 | m_Color: {r: 0.72156864, g: 0.25882354, b: 0.2627451, a: 1} 50 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Fonts/AdventPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/Assets/Fonts/AdventPro-Regular.ttf -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Fonts/AdventPro-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/Assets/Fonts/AdventPro-SemiBold.ttf -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Fonts/Gruppo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/Assets/Fonts/Gruppo.ttf -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/LogValueTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class LogValueTest : MonoBehaviour 6 | { 7 | [Range(0,1)] 8 | public float Input; 9 | public float Output; 10 | public float BackToInput; 11 | public AnimationCurve curve = new AnimationCurve(); 12 | 13 | public void OnValidate() 14 | { 15 | 16 | Output = AmountToFrequency(Input); 17 | BackToInput = FrequencyToAmount(Output); 18 | curve = new AnimationCurve(); 19 | for(float i = 0; i < 1; i+=0.01f) 20 | { 21 | curve.AddKey(i, AmountToFrequency(i)); 22 | } 23 | } 24 | 25 | public float AmountToFrequency(float amount) 26 | { 27 | return Mathf.Round(11000 * (1 - Mathf.Log(Mathf.Lerp(0.1f, 10, amount), 10))); 28 | } 29 | 30 | public float FrequencyToAmount(float frequency) 31 | { 32 | return Round(Mathf.InverseLerp(0.1f, 10, Mathf.Pow(10, 1 - (frequency / 11000))), 2); 33 | } 34 | 35 | public float Round(float value, int decimals = 0) 36 | { 37 | return Mathf.Round(value * Mathf.Pow(10, decimals)) / Mathf.Pow(10, decimals); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Plugins/RocketSoundEnhancement.Unity.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/Assets/Plugins/RocketSoundEnhancement.Unity.dll -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/RSE_Mixer.mixer: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!244 &-6216974954783729661 4 | AudioMixerEffectController: 5 | m_ObjectHideFlags: 3 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_Name: 10 | m_EffectID: dc5858760e34b9c429c293ffd6dba965 11 | m_EffectName: Attenuation 12 | m_MixLevel: cc97a21ad48b8514b8393adce8b05038 13 | m_Parameters: [] 14 | m_SendTarget: {fileID: 0} 15 | m_EnableWetMix: 0 16 | m_Bypass: 0 17 | --- !u!244 &-5349353249736776151 18 | AudioMixerEffectController: 19 | m_ObjectHideFlags: 3 20 | m_CorrespondingSourceObject: {fileID: 0} 21 | m_PrefabInstance: {fileID: 0} 22 | m_PrefabAsset: {fileID: 0} 23 | m_Name: 24 | m_EffectID: 6856c71c92889564c9cf7d1ea4fa048c 25 | m_EffectName: Attenuation 26 | m_MixLevel: 52efe0f841d18fd40bce28b539aa3d66 27 | m_Parameters: [] 28 | m_SendTarget: {fileID: 0} 29 | m_EnableWetMix: 0 30 | m_Bypass: 0 31 | --- !u!244 &-1068627033448524482 32 | AudioMixerEffectController: 33 | m_ObjectHideFlags: 3 34 | m_CorrespondingSourceObject: {fileID: 0} 35 | m_PrefabInstance: {fileID: 0} 36 | m_PrefabAsset: {fileID: 0} 37 | m_Name: 38 | m_EffectID: 4a2262c0cfcf8484c80ed9f4208dc9e1 39 | m_EffectName: Lowpass Simple 40 | m_MixLevel: 3f66a0d75d643af4b851a4d6cc5330cc 41 | m_Parameters: 42 | - m_ParameterName: Cutoff freq 43 | m_GUID: b0ef6d2c15abd9b44b6db8cfda37f713 44 | m_SendTarget: {fileID: 0} 45 | m_EnableWetMix: 0 46 | m_Bypass: 0 47 | --- !u!241 &24100000 48 | AudioMixerController: 49 | m_ObjectHideFlags: 0 50 | m_CorrespondingSourceObject: {fileID: 0} 51 | m_PrefabInstance: {fileID: 0} 52 | m_PrefabAsset: {fileID: 0} 53 | m_Name: RSE_Mixer 54 | m_OutputGroup: {fileID: 0} 55 | m_MasterGroup: {fileID: 24300002} 56 | m_Snapshots: 57 | - {fileID: 24500006} 58 | m_StartSnapshot: {fileID: 24500006} 59 | m_SuspendThreshold: -80 60 | m_EnableSuspend: 1 61 | m_UpdateMode: 0 62 | m_ExposedParameters: 63 | - guid: 64b9ef4ed75e2164bb7181f8fd86f685 64 | name: ExteriorVolume 65 | - guid: 671f7ffb3ac028b4fa4010e84ef276e6 66 | name: ExteriorCutoff 67 | - guid: 841f11c8f4574914b91c7710d13559d2 68 | name: FocusVolume 69 | - guid: b0ef6d2c15abd9b44b6db8cfda37f713 70 | name: FocusCutoff 71 | - guid: dd663ecdaccabef4da8acb0227affed4 72 | name: LimiterThreshold 73 | - guid: d33abb8c6fae6424f948a2d1fac890e8 74 | name: LimiterAttack 75 | - guid: 6c9e4b21330a6304dbcc071aedf15a0e 76 | name: LimiterRelease 77 | - guid: 53be6bcfdb7a84b48a9e17b54c0c9109 78 | name: LimiterGain 79 | m_AudioMixerGroupViews: 80 | - guids: 81 | - a40cf66709127ce47806949d2361d8fe 82 | - 86d33a642a05f1346bbe8d42f764414f 83 | - f91a40c5d616e1b499d7fe95c6fcece4 84 | - cd1b9f04b6acf394c8eb4cfd11b31b8c 85 | name: View 86 | m_CurrentViewIndex: 0 87 | m_TargetSnapshot: {fileID: 24500006} 88 | --- !u!243 &24300002 89 | AudioMixerGroupController: 90 | m_ObjectHideFlags: 0 91 | m_CorrespondingSourceObject: {fileID: 0} 92 | m_PrefabInstance: {fileID: 0} 93 | m_PrefabAsset: {fileID: 0} 94 | m_Name: Master 95 | m_AudioMixer: {fileID: 24100000} 96 | m_GroupID: a40cf66709127ce47806949d2361d8fe 97 | m_Children: 98 | - {fileID: 5969087097913920850} 99 | - {fileID: 4441860710090674652} 100 | - {fileID: 8485599683572803576} 101 | m_Volume: fcca984ec46e0e5418fa7686df364d68 102 | m_Pitch: a38d4ed33121ca14c977cab8d7e4332a 103 | m_Send: 00000000000000000000000000000000 104 | m_Effects: 105 | - {fileID: 2992216207053165396} 106 | - {fileID: 24400004} 107 | m_UserColorIndex: 0 108 | m_Mute: 0 109 | m_Solo: 0 110 | m_BypassEffects: 0 111 | --- !u!244 &24400004 112 | AudioMixerEffectController: 113 | m_ObjectHideFlags: 3 114 | m_CorrespondingSourceObject: {fileID: 0} 115 | m_PrefabInstance: {fileID: 0} 116 | m_PrefabAsset: {fileID: 0} 117 | m_Name: 118 | m_EffectID: 62d35672275142b4cbeb143185ae40b5 119 | m_EffectName: Attenuation 120 | m_MixLevel: 88e352001c975844b873e208bdb6e437 121 | m_Parameters: [] 122 | m_SendTarget: {fileID: 0} 123 | m_EnableWetMix: 0 124 | m_Bypass: 0 125 | --- !u!245 &24500006 126 | AudioMixerSnapshotController: 127 | m_ObjectHideFlags: 0 128 | m_CorrespondingSourceObject: {fileID: 0} 129 | m_PrefabInstance: {fileID: 0} 130 | m_PrefabAsset: {fileID: 0} 131 | m_Name: Snapshot 132 | m_AudioMixer: {fileID: 24100000} 133 | m_SnapshotID: b0d2b84f8d21ddb4a9ee6bfd42fb389c 134 | m_FloatValues: 135 | e53ed840aa71c8d4fba027e4ca9d7d9e: 0 136 | 6c9e4b21330a6304dbcc071aedf15a0e: 20 137 | 3bedb541b1a982d46894b7cee2f52e2b: 0 138 | 4198cf415f4cbe44e8393270657ecd58: 10 139 | 0ed44c14cfbc1ff4d8e74dbeb8af973a: 11420.729 140 | 0ed7c59766a8dcf41b7dc214411b0c33: 1 141 | 7c41afb70a9cfef44b1b2e0756acf024: 500 142 | 01d91218a40893847a27cf4d35c07d9f: 1.3999994 143 | 841f11c8f4574914b91c7710d13559d2: 0 144 | 4c95b87ad34d3e544a72aa0c7f445baa: 50 145 | 671f7ffb3ac028b4fa4010e84ef276e6: 22000 146 | 4bc8871ca64bd4546b77bfbeaea68965: 0.503 147 | b0ef6d2c15abd9b44b6db8cfda37f713: 22000 148 | d33abb8c6fae6424f948a2d1fac890e8: 10 149 | f40d718d7a310f444847a85c301eab1e: 0 150 | dd663ecdaccabef4da8acb0227affed4: 0 151 | 90d02ced34c531c4e8a54ed1fa412f5b: -80 152 | fcca984ec46e0e5418fa7686df364d68: 0 153 | faffbd7f8962c3947a5e0da4b6b8153d: 50 154 | 53be6bcfdb7a84b48a9e17b54c0c9109: 0 155 | m_TransitionOverrides: {} 156 | --- !u!244 &2992216207053165396 157 | AudioMixerEffectController: 158 | m_ObjectHideFlags: 3 159 | m_CorrespondingSourceObject: {fileID: 0} 160 | m_PrefabInstance: {fileID: 0} 161 | m_PrefabAsset: {fileID: 0} 162 | m_Name: 163 | m_EffectID: 56d6e276779f29c4893615ebd1d877a4 164 | m_EffectName: Compressor 165 | m_MixLevel: b09c17669cd199546bd3e801e8446085 166 | m_Parameters: 167 | - m_ParameterName: Threshold 168 | m_GUID: dd663ecdaccabef4da8acb0227affed4 169 | - m_ParameterName: Attack 170 | m_GUID: d33abb8c6fae6424f948a2d1fac890e8 171 | - m_ParameterName: Release 172 | m_GUID: 6c9e4b21330a6304dbcc071aedf15a0e 173 | - m_ParameterName: Make up gain 174 | m_GUID: 53be6bcfdb7a84b48a9e17b54c0c9109 175 | m_SendTarget: {fileID: 0} 176 | m_EnableWetMix: 0 177 | m_Bypass: 0 178 | --- !u!243 &4441860710090674652 179 | AudioMixerGroupController: 180 | m_ObjectHideFlags: 0 181 | m_CorrespondingSourceObject: {fileID: 0} 182 | m_PrefabInstance: {fileID: 0} 183 | m_PrefabAsset: {fileID: 0} 184 | m_Name: FOCUS 185 | m_AudioMixer: {fileID: 24100000} 186 | m_GroupID: f91a40c5d616e1b499d7fe95c6fcece4 187 | m_Children: [] 188 | m_Volume: 841f11c8f4574914b91c7710d13559d2 189 | m_Pitch: afff5aa3f5ae9aa4b941338d8d88511b 190 | m_Send: 00000000000000000000000000000000 191 | m_Effects: 192 | - {fileID: -5349353249736776151} 193 | - {fileID: -1068627033448524482} 194 | m_UserColorIndex: 0 195 | m_Mute: 0 196 | m_Solo: 0 197 | m_BypassEffects: 0 198 | --- !u!244 &5932450804440514950 199 | AudioMixerEffectController: 200 | m_ObjectHideFlags: 3 201 | m_CorrespondingSourceObject: {fileID: 0} 202 | m_PrefabInstance: {fileID: 0} 203 | m_PrefabAsset: {fileID: 0} 204 | m_Name: 205 | m_EffectID: 882ee51681f9d1f4c970f197f802d093 206 | m_EffectName: Lowpass Simple 207 | m_MixLevel: f40446f009cf9104faae59ff4782247c 208 | m_Parameters: 209 | - m_ParameterName: Cutoff freq 210 | m_GUID: 671f7ffb3ac028b4fa4010e84ef276e6 211 | m_SendTarget: {fileID: 0} 212 | m_EnableWetMix: 0 213 | m_Bypass: 0 214 | --- !u!243 &5969087097913920850 215 | AudioMixerGroupController: 216 | m_ObjectHideFlags: 0 217 | m_CorrespondingSourceObject: {fileID: 0} 218 | m_PrefabInstance: {fileID: 0} 219 | m_PrefabAsset: {fileID: 0} 220 | m_Name: INTERIOR 221 | m_AudioMixer: {fileID: 24100000} 222 | m_GroupID: 86d33a642a05f1346bbe8d42f764414f 223 | m_Children: [] 224 | m_Volume: 897da83b483549c41ae7acdec42e5f68 225 | m_Pitch: aaf4cf4d8f9a9094b8abd517597d41ea 226 | m_Send: 00000000000000000000000000000000 227 | m_Effects: 228 | - {fileID: 7848904388498332874} 229 | m_UserColorIndex: 0 230 | m_Mute: 0 231 | m_Solo: 0 232 | m_BypassEffects: 0 233 | --- !u!244 &7848904388498332874 234 | AudioMixerEffectController: 235 | m_ObjectHideFlags: 3 236 | m_CorrespondingSourceObject: {fileID: 0} 237 | m_PrefabInstance: {fileID: 0} 238 | m_PrefabAsset: {fileID: 0} 239 | m_Name: 240 | m_EffectID: a9466a82b69757c4ca87ab475fe1db97 241 | m_EffectName: Attenuation 242 | m_MixLevel: 27cc7eb6bdd9cab46a0dd5c7cd3b2b80 243 | m_Parameters: [] 244 | m_SendTarget: {fileID: 0} 245 | m_EnableWetMix: 0 246 | m_Bypass: 0 247 | --- !u!243 &8485599683572803576 248 | AudioMixerGroupController: 249 | m_ObjectHideFlags: 0 250 | m_CorrespondingSourceObject: {fileID: 0} 251 | m_PrefabInstance: {fileID: 0} 252 | m_PrefabAsset: {fileID: 0} 253 | m_Name: EXTERIOR 254 | m_AudioMixer: {fileID: 24100000} 255 | m_GroupID: cd1b9f04b6acf394c8eb4cfd11b31b8c 256 | m_Children: [] 257 | m_Volume: 64b9ef4ed75e2164bb7181f8fd86f685 258 | m_Pitch: c0af8fa328ece6840896f8304145c266 259 | m_Send: 00000000000000000000000000000000 260 | m_Effects: 261 | - {fileID: -6216974954783729661} 262 | - {fileID: 5932450804440514950} 263 | m_UserColorIndex: 0 264 | m_Mute: 0 265 | m_Solo: 0 266 | m_BypassEffects: 0 267 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Screenshots/screenshot16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/Assets/Screenshots/screenshot16.png -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/Assets/Screenshots/screenshot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KSPModStewards/RocketSoundEnhancement/bd384055c20cb879888496507fcce1db1a0da1a1/Source/Unity/RSE_Assets/Assets/Screenshots/screenshot5.png -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Volume: 1 8 | Rolloff Scale: 1 9 | Doppler Factor: 1 10 | Default Speaker Mode: 2 11 | m_SampleRate: 0 12 | m_DSPBufferSize: 1024 13 | m_VirtualVoiceCount: 512 14 | m_RealVoiceCount: 32 15 | m_SpatializerPlugin: 16 | m_AmbisonicDecoderPlugin: 17 | m_DisableAudio: 0 18 | m_VirtualizeEffects: 1 19 | m_RequestedDSPBufferSize: 1024 20 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 11 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 0 23 | m_ReuseCollisionCallbacks: 1 24 | m_ClothInterCollisionSettingsToggle: 0 25 | m_ContactPairsMode: 0 26 | m_BroadphaseType: 0 27 | m_WorldBounds: 28 | m_Center: {x: 0, y: 0, z: 0} 29 | m_Extent: {x: 250, y: 250, z: 250} 30 | m_WorldSubdivisions: 8 31 | m_FrictionType: 0 32 | m_EnableEnhancedDeterminism: 0 33 | m_EnableUnifiedHeightmaps: 1 34 | m_DefaultMaxAngluarSpeed: 7 35 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: [] 8 | m_configObjects: {} 9 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 9 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 0 10 | m_DefaultBehaviorMode: 1 11 | m_PrefabRegularEnvironment: {fileID: 0} 12 | m_PrefabUIEnvironment: {fileID: 0} 13 | m_SpritePackerMode: 4 14 | m_SpritePackerPaddingPower: 1 15 | m_EtcTextureCompressorBehavior: 1 16 | m_EtcTextureFastCompressor: 1 17 | m_EtcTextureNormalCompressor: 2 18 | m_EtcTextureBestCompressor: 4 19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref 20 | m_ProjectGenerationRootNamespace: 21 | m_CollabEditorSettings: 22 | inProgressEnabled: 1 23 | m_EnableTextureStreamingInEditMode: 1 24 | m_EnableTextureStreamingInPlayMode: 1 25 | m_AsyncShaderCompilation: 1 26 | m_EnterPlayModeOptionsEnabled: 0 27 | m_EnterPlayModeOptions: 3 28 | m_ShowLightmapResolutionOverlay: 1 29 | m_UseLegacyProbeSampleCount: 1 30 | m_AssetPipelineMode: 1 31 | m_CacheServerMode: 0 32 | m_CacheServerEndpoint: 33 | m_CacheServerNamespacePrefix: default 34 | m_CacheServerEnableDownload: 1 35 | m_CacheServerEnableUpload: 1 36 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 13 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 16001, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} 37 | m_PreloadedShaders: [] 38 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 39 | type: 0} 40 | m_CustomRenderPipeline: {fileID: 0} 41 | m_TransparencySortMode: 0 42 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 43 | m_DefaultRenderingPath: 1 44 | m_DefaultMobileRenderingPath: 1 45 | m_TierSettings: [] 46 | m_LightmapStripping: 0 47 | m_FogStripping: 0 48 | m_InstancingStripping: 0 49 | m_LightmapKeepPlain: 1 50 | m_LightmapKeepDirCombined: 1 51 | m_LightmapKeepDynamicPlain: 1 52 | m_LightmapKeepDynamicDirCombined: 1 53 | m_LightmapKeepShadowMask: 1 54 | m_LightmapKeepSubtractive: 1 55 | m_FogKeepLinear: 1 56 | m_FogKeepExp: 1 57 | m_FogKeepExp2: 1 58 | m_AlbedoSwatchInfos: [] 59 | m_LightsUseLinearIntensity: 0 60 | m_LightsUseColorTemperature: 0 61 | m_LogWhenShaderIsCompiled: 0 62 | m_AllowEnlightenSupportForUpgradedProject: 1 63 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/PackageManagerSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &1 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 61 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} 13 | m_Name: 14 | m_EditorClassIdentifier: 15 | m_ScopedRegistriesSettingsExpanded: 1 16 | oneTimeWarningShown: 0 17 | m_Registries: 18 | - m_Id: main 19 | m_Name: 20 | m_Url: https://packages.unity.com 21 | m_Scopes: [] 22 | m_IsDefault: 1 23 | m_UserSelectedRegistryName: 24 | m_UserAddingNewScopedRegistry: 0 25 | m_RegistryInfoDraft: 26 | m_ErrorMessage: 27 | m_Original: 28 | m_Id: 29 | m_Name: 30 | m_Url: 31 | m_Scopes: [] 32 | m_IsDefault: 0 33 | m_Modified: 0 34 | m_Name: 35 | m_Url: 36 | m_Scopes: 37 | - 38 | m_SelectedScopeIndex: 0 39 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 4 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_JobOptions: 23 | serializedVersion: 2 24 | useMultithreading: 0 25 | useConsistencySorting: 0 26 | m_InterpolationPosesPerJob: 100 27 | m_NewContactsPerJob: 30 28 | m_CollideContactsPerJob: 100 29 | m_ClearFlagsPerJob: 200 30 | m_ClearBodyForcesPerJob: 200 31 | m_SyncDiscreteFixturesPerJob: 50 32 | m_SyncContinuousFixturesPerJob: 50 33 | m_FindNearestContactsPerJob: 100 34 | m_UpdateTriggerContactsPerJob: 100 35 | m_IslandSolverCostThreshold: 100 36 | m_IslandSolverBodyCostScale: 1 37 | m_IslandSolverContactCostScale: 10 38 | m_IslandSolverJointCostScale: 10 39 | m_IslandSolverBodiesPerJob: 50 40 | m_IslandSolverContactsPerJob: 50 41 | m_AutoSimulation: 1 42 | m_QueriesHitTriggers: 1 43 | m_QueriesStartInColliders: 1 44 | m_CallbacksOnDisable: 1 45 | m_ReuseCollisionCallbacks: 1 46 | m_AutoSyncTransforms: 0 47 | m_AlwaysShowColliders: 0 48 | m_ShowColliderSleep: 1 49 | m_ShowColliderContacts: 0 50 | m_ShowColliderAABB: 0 51 | m_ContactArrowScale: 0.2 52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 57 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_DefaultPresets: {} 8 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2019.4.18f1 2 | m_EditorVersionWithRevision: 2019.4.18f1 (3310a4d4f880) 3 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 3 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 16 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 16 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 0 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 0 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 16 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 0 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 0 108 | antiAliasing: 0 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 0 112 | billboardsFaceCameraPosition: 0 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 16 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 0 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 70 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 0 136 | antiAliasing: 0 137 | softParticles: 0 138 | softVegetation: 1 139 | realtimeReflectionProbes: 0 140 | billboardsFaceCameraPosition: 0 141 | vSyncCount: 1 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 16 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 0 153 | shadowResolution: 0 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 0 164 | antiAliasing: 0 165 | softParticles: 0 166 | softVegetation: 1 167 | realtimeReflectionProbes: 0 168 | billboardsFaceCameraPosition: 0 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 16 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSM: 5 183 | PSP2: 2 184 | Stadia: 5 185 | Standalone: 5 186 | Tizen: 2 187 | WebGL: 3 188 | WiiU: 5 189 | Windows Store Apps: 5 190 | XboxOne: 5 191 | iPhone: 2 192 | tvOS: 2 193 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 1 7 | m_Enabled: 0 8 | m_TestMode: 0 9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events 10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events 11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com 12 | m_TestInitMode: 0 13 | CrashReportingSettings: 14 | m_EventUrl: https://perf-events.cloud.unity3d.com 15 | m_Enabled: 0 16 | m_LogBufferSize: 10 17 | m_CaptureEditorExceptions: 1 18 | UnityPurchasingSettings: 19 | m_Enabled: 0 20 | m_TestMode: 0 21 | UnityAnalyticsSettings: 22 | m_Enabled: 0 23 | m_TestMode: 0 24 | m_InitializeOnStartup: 1 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/VFXManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!937362698 &1 4 | VFXManager: 5 | m_ObjectHideFlags: 0 6 | m_IndirectShader: {fileID: 0} 7 | m_CopyBufferShader: {fileID: 0} 8 | m_SortShader: {fileID: 0} 9 | m_StripUpdateShader: {fileID: 0} 10 | m_RenderPipeSettingsPath: 11 | m_FixedTimeStep: 0.016666668 12 | m_MaxDeltaTime: 0.05 13 | -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/ProjectSettings/XRSettings.asset: -------------------------------------------------------------------------------- 1 | { 2 | "m_SettingKeys": [ 3 | "VR Device Disabled", 4 | "VR Device User Alert" 5 | ], 6 | "m_SettingValues": [ 7 | "False", 8 | "False" 9 | ] 10 | } -------------------------------------------------------------------------------- /Source/Unity/RSE_Assets/RSE_Assets.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp", "Assembly-CSharp.csproj", "{4B4022B4-EBAD-286A-1CE3-ECAB3D1BA7A5}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Assembly-CSharp-Editor", "Assembly-CSharp-Editor.csproj", "{5760BE11-0702-E0FD-F257-3107E3314C0D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {4B4022B4-EBAD-286A-1CE3-ECAB3D1BA7A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {4B4022B4-EBAD-286A-1CE3-ECAB3D1BA7A5}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {4B4022B4-EBAD-286A-1CE3-ECAB3D1BA7A5}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {4B4022B4-EBAD-286A-1CE3-ECAB3D1BA7A5}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {5760BE11-0702-E0FD-F257-3107E3314C0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {5760BE11-0702-E0FD-F257-3107E3314C0D}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {5760BE11-0702-E0FD-F257-3107E3314C0D}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {5760BE11-0702-E0FD-F257-3107E3314C0D}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | # [0.9.11] - 03-25-24 4 | - Fixed missing reentry and wind sounds 5 | 6 | # [0.9.10] - 03-15-24 7 | - Fixed NRE spam when a vessel is unloaded quickly after being loaded (often when crashing into terrain) 8 | - Massively reduce the memory impact of the comb filter 9 | 10 | # [0.9.9] - 03-05-24 11 | - Improved memory leak/exception spam fix when vessels are unloaded 12 | 13 | # [0.9.8] - 09-16-23 14 | - Fixed index out of range exception when a sound layer has no clips 15 | - Potential fix for memory leak due to ongamepaused events 16 | 17 | # [0.9.7] - 03-07-23 18 | ## Changes 19 | - Fixed MachEffectsAmount not saving and causing crashes when set to zero. 20 | - Fixed Sonic Booms being triggered in MapView 21 | - RCS sounds use thruster power 22 | - Major performance optimizations 23 | - Fixed memory leaks from scene changes 24 | 25 | # [0.9.6] - 07-09-22 26 | ## Changes 27 | - Improved AirSimulationFilter Performance 28 | - Added RSE_KerbalEVA with support for jetpack sounds. by @pizzaoverhead in https://github.com/ensou04/RocketSoundEnhancement/pull/16 29 | - Added alternative "SOUNDLAYERGROUP" Node for SoundLayer Groups in RSE_Engines, RSE_RotorEngines & RSE_Wheels 30 | - Renamed "EnableWaveShaperFilter" to "EnableDistortionFilter" 31 | - Tweaked Global AirSim Settings 32 | - Removed "RSE_AUDIO_LOOP". assign a name to "RSE_AUDIO" if used more than once in a single EFFECTS subnode 33 | 34 | # [0.9.5] - 06-22-22 35 | ## Changes 36 | - Fixed OneShot Samples playing with the wrong pitch value 37 | - Fixed AirSim Filter not taking effect sometimes. 38 | - Fixed SonicBoom SoundLayer Support 39 | - Removed AirSim Filters from SonicBoom sources 40 | 41 | # [0.9.4] - 06-08-22 42 | ## Changes 43 | - Added MachEffectsAmount config 44 | - Settings Panel now closes when Save button is pressed 45 | - Fixed RSE_AUDIO AirSim Filter being disabled first before the audiosource causing unwanted behaviour 46 | - Fixed Stock Audio Disappearing bug 47 | - Temporary Fix for Sound Stutters when changing scenes 48 | 49 | # [0.9.3] - 06-05-22 50 | ## Changes 51 | - AirSim Lite muffler quality. mach effects and sonic booms without the airsim filters 52 | - RSE_AUDIO, RSE_AUDIOLOOP, simpler non-SoundLayer version of RSE_Modules for EFFECTS{} nodes. 53 | 54 | ## Fixes 55 | - Fixed code error with ShipEffects 56 | 57 | # [0.9.2] - 06-03-22 58 | ## Changes 59 | - New Settings Panel 60 | - Replaced Audio Limiter with Unity's Audio Compressor/Limiter 61 | - Audio Limiter Presets has been replaced with "Limiter Amount" slider in the Settings Panel. 62 | - Muffling Presets has been replaced with simpler "Muffling Amount" slider in the Settings Panel. (Still saved as a frequency value in the Settings.cfg) 63 | - "ClampActiveVesselMuffling" option for Audio Muffler. Allows the currently active vessel to have separate muffling from regular muffling by clamping the muffling amount to the InternalMode muffling frequency. 64 | - ["CustomMixerRouting" config allows custom routing of existing static sound sources (modded, stock) to the mixer.](https://forum.kerbalspaceprogram.com/index.php?/topic/179579-110x-112x-rocket-sound-enhancement-audio-framework-for-complex-sound-effects-v091-052322-config-pack-v120-052322/&do=findComment&comment=4139319) 65 | - Audio Muffler now considers any sound source that has spatialBlend = 0 or position = 0 as a GUI Source and is ignored from the muffling. Can still be routed back for muffling (for example: wind sounds) via CustomMixerRouting config in Settings.cfg 66 | 67 | ## Performance Improvements/Fixes 68 | - Fixed denormal numbers from AirSimulationFilter causing high CPU usage 69 | - AudioClips, AudioSources and AirSimulationFilters are prepared ahead of time instead of being created dynamically during update. 70 | - SoundLayers can now share AudioSources with each other if the layer has the same name 71 | - One Shot (eg: Engage, Disengage, Flame-out and Bursts) SoundLayers now share one AudioSource with each other. _Issue: sometimes pitch is incorrectly applied._ 72 | - Fixed audio clicking when the sound source is stopped 73 | - Fixed Null Exceptions from ShipEffectsCollisions 74 | - Fixed Loop Randomizer not properlly randomizing causing unwanted Comb-Filtering/Phasing 75 | - Various Refactoring and Optimizations 76 | 77 | **Full Changelog**: https://github.com/ensou04/RocketSoundEnhancement/compare/0.9.1...0.9.2 78 | 79 | # [0.9.1] - 05-23-22 80 | - Added Support for Internal Space Mods ([RPM](https://github.com/JonnyOThan/RasterPropMonitor/releases), [MAS](https://github.com/MOARdV/AvionicsSystems/releases)) 81 | - Fixed Music Getting Muffled at higher Muffler Settings 82 | 83 | # [0.9.0] - 05-23-22 84 | ## New Audio Muffler Quality Settings 85 | - **Lite:** The Old Basic Muffler 86 | - **Full:** Mixer based Audio Muffler with Dedicated channels for Exterior Sounds, Focused Vessel and Interior. With Doppler Effect 87 | - **AirSim:** Works on top of Full Quality, Parts with RSE Modules will simulate realistic sound attenuation over distance, comb-filtering, mach effects, sonic booms and distortion. Stock sound sources has basic mach and distance attenuation (volume or filter based) support. 88 | ## Changes 89 | - **RSE_RotorEngines** Part Module 90 | - **RSE_Propellers**{} Config Node for propeller blades. Works when attached to Rotors with an **RSE_RotorEngines** Part Module 91 | - **Motor{}** Sound Group for **RSE_Wheels**. **Torque** Sound Group has been removed. 92 | - **ShipEffects** now uses Sound Groups for **Physics Controllers** instead of using soundlayer.data 93 | - **DYNAMICPRESSURE{}**, **SONICBOOM{}** and **REENTRYHEAT{}** Sound Group for **ShipEffects** 94 | - Simplified Audio Muffler Settings 95 | - Interior and Exterior Volume Settings 96 | - Support for SoundtrackEditor music sources by @KvaNTy in https://github.com/ensou04/RocketSoundEnhancement/pull/11 97 | - Support for misc Chatterer sound sources by @KvaNTy in https://github.com/ensou04/RocketSoundEnhancement/pull/12 98 | 99 | **Full Changelog**: https://github.com/ensou04/RocketSoundEnhancement/compare/0.7.2...0.9.0 100 | 101 | 0.7.2: 102 | - Potential Fix for Collision Loop Sound Effects Persisting after Impact 103 | - Custom Audio Muffler Settings now react instantly to new settings 104 | - Tweaked Orbit View Muffling 105 | - Removed "MuffleChatterer" from LOWPASSFILTER in Settings.cfg 106 | - Added "AffectChatterer" under RSE_SETTINGS in Settings.cfg 107 | - Code Optimization 108 | 109 | 0.7.1 110 | - Fixed Music being Muffled 111 | 112 | 0.7.0 113 | - New In-game Settings Window 114 | - Audio Limiter/Sound Effects Mastering now has Presets Available through In-Game Settings 115 | - Audio Muffler Presets now Available through In-Game Settings 116 | 117 | Sound Effects Mastering Presets: 118 | - Balanced (The Default Preset, Sounds are balanced with Reasonable Dynamic Range) 119 | - Cinematic (Wide Dynamic Range, Loud Sounds are Louder and Quiet Sound Are Quieter than Balanced) 120 | - NASA-Reels (Inspired by Real Rocket Launch Footage, This is the Loudest Preset with minimal Dynamic Range) 121 | - Custom (User Customizable Preset) 122 | - Add more Presets in [Settings.cfg](https://github.com/ensou04/RocketSoundEnhancement/blob/0.7.1/GameData/RocketSoundEnhancement/Settings.cfg) 123 | 124 | Audio Muffler Presets: 125 | - Interior-Only (Only Muffle sounds when the Camera is in IVA view) 126 | - Muffled-Vacuum 127 | - Silent-Vacuum 128 | - Custom (User Customizable Preset) 129 | - Add more Presets in [Settings.cfg](https://github.com/ensou04/RocketSoundEnhancement/blob/0.7.1/GameData/RocketSoundEnhancement/Settings.cfg) 130 | 131 | Other Changes: 132 | - Handling of Configs has been changed in code. 133 | - Code Cleanup 134 | 135 | 0.6.1 136 | - Setting Muffling to 0 now goes to silent. 137 | - Code Optimization on Audio Limiter 138 | 139 | 0.6.0 140 | - Compiled on 1.12.3 141 | - Implemented a new Audio Limiter (Fairly Childish Limiter/Compressor) 142 | - Added RCS Part Module 143 | - Volume Settings are now controlled by Stock In-game Settings 144 | - Moved Audio Limiter and Muffler Settings to Settings.cfg 145 | - Increased KSP Real Voices/Sound Limit to 64 (originally was only 15) 146 | - Fixed Engage/Disengage Not Working Together 147 | - Fixed "Volume" Config Node for RSE_Wheels and RSE_Engines not being in code. 148 | - Change Muffling Settings to Internal Muffling only by Default 149 | 150 | 151 | --------------------------------------------------------------------------------