EngineSim
An engine sound simulator that works the sound out from how gas flows through the engine, instead of playing back recordings.

This started with engine-sim community edition, an open-source engine simulator. I played with it, liked it a lot, and wanted to see how far the idea goes if you simulate more of the engine than it does. Everything below is my own take on that, and the inspiration is theirs.
Most engine sounds in games and apps are recordings. Someone records a real car at a few speeds and the software blends between the clips. That works for the car they recorded and falls apart for everything else: another engine, another gear, a stab of throttle nobody captured.
I wanted to build the engine instead of recording it. EngineSim models each cylinder, the pipes that carry the exhaust away, the muffler, and the way air pressure moves through all of it. Most of the sound is what that pressure does when it reaches open air at the end of the tailpipe. The rest is the hiss of air rushing through valves and pipes, and the ticking of the engine itself. It is a bit like a pipe organ. If you know how long the pipes are and how the air is pushed through them, you can work out the note without recording anything. An engine is the same, except the air is hot and arrives in bangs.
Here is thirteen seconds of it, a four-cylinder revving up and back down, straight from the simulator with the volume turned down. It is a fair test of whether the pitch follows the revs, and nothing more.
You pick an engine from a library that runs from a lawnmower motor to V8s, motorcycles, diesels and light aircraft, press the throttle and it runs. There is a desktop app around it where you drive the engine and choose where you are standing: in the cabin, by the exhaust, or as the car goes past. I have run it live in the app, and it works, but it is still a work in progress and it asks a lot of the computer.

The physics holds up better than I expected. I ran several engines on a virtual dynamometer, the machine that measures how hard an engine pulls. For the three where I could find published figures for a similar real engine, a V8, a six and a motorcycle twin, the power and torque land within about 20 per cent. I did not tune anything to those figures.
Whether it sounds right is the harder question, and I can't say it is solved. To test it without a room full of listeners I built a stand-in: a program that hears short clips and guesses whether each one is the simulator or a real recording, scored on engines it has never heard. 50 per cent would mean it can't tell. The best of my judges still gets 91 to 100 per cent. I haven't run a listening test with people yet, so I don't know how it sounds to an ear.
Fitting the sound to real recordings mostly didn't work. Each change that helped one part of the sound made another part worse, and when I looked closer, a lot of the apparent improvement was just differences in how the recordings themselves were made. It also needs a lot of computing. On an ordinary processor it keeps up in real time only with a coarse model, and the finer ones need the graphics card or have to be rendered ahead of time.
What's next: a proper listening test with real people, a carefully calibrated recording to fit against, and a graphics-card path that can run finer models live. The app also still needs MIDI keyboard support and a rebuilt installer. A browser version and the code itself will be public soon, under a licence I haven't chosen yet.
What I wanted
I got into this through engine-sim community edition, the open-source engine simulator that inspired it. The community edition carries on the original engine-sim, which simulates the cylinders as lumped volumes of gas, then takes the pressure in the runners, low-passes it at 1.9 kHz and convolves it with a hand-picked impulse response. So the pipe acoustics are canned. I wanted to simulate the pipes as well, so that torque, exhaust resonances and the crossplane burble come out of the model instead of being drawn in. Most engine sound in games and tools is recordings, played back and blended, which is the other thing I wanted to get away from.
Before this I had a JavaScript synthesizer whose cylinder pulses are hand-shaped. It covers 26 vehicles, including turbos, superchargers and jets, and it is still useful as a sketchpad. The Rust simulator is the version where the pulses are the result of actual gas flow.
How it works
Each cylinder is a thermodynamic gas volume: slider-crank geometry, a Wiebe curve for how fast the fuel burns, heat loss to the walls. Every intake and exhaust pipe solves compressible one-dimensional flow, and valves, throttle, plenums, collectors and mufflers are the boundaries between them. The sound is the pressure radiated from the open ends, plus flow noise at the valves, throttle and tailpipe, plus structure noise from valve and piston impacts and combustion pressure. All of it is driven by the simulated flows and pressures. Nothing is looped.
What does one-dimensional mean here?
A pipe is long and thin, so instead of tracking the air in three dimensions I only track pressure, speed and temperature along its length, in a row of small cells. Each step, neighbouring cells swap mass, momentum and energy. That is cheap, and it is enough for sound, because the waves that matter travel along the pipe.
What are MUSCL-Hancock and HLLC?
Two pieces of maths for one job: working out what flows between two neighbouring cells when they hold gas at different pressures. HLLC is an approximate solution of that jump between two states. MUSCL-Hancock makes the values inside each cell vary smoothly, so that sharp pressure fronts stay sharp instead of smearing out.
The gas solver runs on its own 32 kHz clock and its grid resolves roughly 2 kHz, with the cell size following the speed of sound in each pipe, so hot pipes cost less. Above that, the sound comes from source models: the standard valve-noise regimes from IEC 60534-8-3, Lighthill jet noise at the tailpipe, and a statistical-energy model of the block. Most of their constants are scaled from physics. A few, like the casting loss factors, the 15 per cent impact share and the silencer volumes, were fitted to recordings in the early rounds, and the later fit rounds (more on that below) changed nothing. For cars, how the sound gets around the body comes from a 3-D wave simulation that I run once on the GPU, about three minutes on my 5070 Ti, and bake into the simulator.

Grid size is the main quality dial. The same four-cylinder on three grids shows what a finer one buys: the low harmonics land on top of each other whatever the cell size, and the finer the grid, the further up the upper harmonics survive.

Results
Here is the sound behind the spectrogram at the top: the four-cylinder pull, 13 seconds, straight from the simulator with the volume turned down. In that run the throttle is wide open while the dyno, the rig that holds the engine at a set speed, ramps the revs from 1500 rpm to the redline over 9 seconds, then the throttle comes off and the speed ramps back down over 3. The fan of lines in the spectrogram is the engine's harmonics, the whole-number multiples of its firing pitch. It is a fair test of whether the pitch follows the revs, and nothing more.
Several things come out of the pipes that I did not draw in. The torque curve ripples where pressure waves arrive at the valves at the right moment. The harmonics brighten through the exhaust resonances, which is the drone. The two banks of a V8 give separate signals. The rev limiter cracks. And the firing order shows up in the sound: below, both V8s do the same pull, idle, then full throttle from 1500 rpm to the limiter, then off.

Crossplane V8Flat-plane V8Spectrograms of the 5.7 L crossplane V8 (left) and the 4.5 L flat-plane V8 (right) on the same pull, up to 1.5 kHz. The flat-plane fires evenly and its lines are clean. The crossplane fires unevenly on each bank, and that smears into a thick ladder of half orders. The flat-plane also runs to a higher speed (the rpm trace under each plot), so its lines sit higher.
Crossplane or flat-plane?
It is how the crankshaft is built. A crossplane V8 has its crank throws at 90 degrees, which gives the classic burble because the firing gaps on each bank are uneven. A flat-plane crank puts the throws in one plane, the firings alternate evenly between the banks, and the sound is smoother and higher-pitched.
| Preset | Simulated | Published |
|---|---|---|
| 2.0 L inline four | 221 Nm, 137 kW | – |
| 5.7 L crossplane V8 | 506 Nm, 288 kW | LS1: 465–495 Nm, about 260 kW |
| 4.5 L flat-plane V8 | 473 Nm, 338 kW | – |
| 3.2 L inline six, throttle bodies | 318 Nm, 211 kW | BMW S54: 365 Nm, 252 kW |
| 1.8 L V-twin | 175 Nm, 62 kW | Harley-Davidson Twin Cam: about 150–160 Nm, 65–70 kW |
Where there is a reference it is within about 20%. Each preset uses its own geometry and cam data, and I did not tune anything to those dyno figures. The V8 comes out high and the six comes out low; my simulated six has tamer cams and runners than the BMW it is compared with.
| Engine | Peak torque | Peak power |
|---|---|---|
| 2.0 L inline four | 221 Nm at about 5400 rpm | 140 kW at about 6400 rpm |
| 3.2 L inline six | 321 Nm at about 5900 rpm | 216 kW at about 6900 rpm |
| 0.65 L single | 65 Nm at about 2600 rpm | 24 kW at about 4100 rpm |
Speed is the catch. These numbers were measured on a Ryzen 9 9900X with a fast build profile that may be a few percent slower than a full release build, on the Mustang 5.0 preset. The CPU rows are 4 seconds of audio at idle, the GPU row is 10 seconds. A value below 1.00 means faster than real time.
| Setup | 25 mm cells | 14 mm cells | 10 mm cells |
|---|---|---|---|
| CPU, one thread | 0.65 | 1.66 | – |
| CPU, four threads | 0.53 | 1.10 | – |
| GPU, RTX 5070 Ti, Vulkan | – | – | 0.94 27 of 938 chunks late |
On the CPU, real time only works on a coarse grid, and the cost climbs steeply as cells shrink (a fitted exponent of 1.63 on one thread). Four threads still leave 14 mm above real time. The middle quality setting in the app is 21 mm cells on four threads, which runs at about 0.64, so there is not much headroom. Finer grids need the graphics card or an offline render, and I render the 4 mm grid I use for benchmarking offline. The GPU run only just passed: 27 of 938 chunks came late, so I rate 10 mm as marginal. The kernel is latency-bound, so a bigger GPU would not help much.
Whether it sounds right is not proven. I have not run a listening test yet, and in my own benchmark, the best machine judges (the ones built on audio embeddings) still tell the simulation from real recordings 91 to 100% of the time.
That benchmark is my stand-in for a blind listening test. I train judges to separate simulated renders from real clips, and from version 9 on each judge is scored on a vehicle it never saw during training. 50% would mean it can't tell the difference. My target for calling the sound done is 60% or lower on engines the physics was never tuned on, plus a blind listening test that people pass. The recordings belong to other people, so I don't republish them. The scores for each version are my own.
What is an embedding-based judge?
A pretrained audio network turns a few seconds of sound into a list of numbers that captures how it sounds. I then train a simple classifier on those numbers to say real or simulated. If it can, the simulator has some tell that a human ear might catch too, and I can look at which features give it away.
What didn't work
Early on, the engine breathed at half capacity. Coupling a pipe to a volume through a Riemann problem against gas at rest charged a spurious pressure drop about 20 times the physical one. A boundary built on the pipe's characteristics fixed it, and now every boundary is solved together with the pipe's outgoing characteristic, because boundaries that are not smooth at zero flow chattered at the Nyquist frequency.
Tuning against real clips mostly failed. In the first fit round none of the constants I tried passed my acceptance rule on held-out engines, so every new realism option stays off. Two of them improved the high-frequency slope but added bass excess at 80 to 315 Hz (about 1 to 3 dB on the engines I tuned on, 5 to 9 dB on the held-out ones): one error traded for another. The second round found that each recording has its own level offset, with a spread of 7 to 8 dB between vehicles, that can't be worked out from the references. The apparent gains were that offset. Going further needs a properly calibrated recording.
A comparison of a twin-turbo V8 preset against one clip first looked like a big deficit in the harmonics. On closer inspection two of the orders were the clip's own noise floor and a ridge was the microphone chain, not the exhaust. A real deficit at higher orders remains. The tyre and road coefficients in the cabin model are unchecked.
On the GPU path, the four-cylinder run fails the parity check against the CPU on a software Vulkan driver, with intake pressure about 2% off. DX12 on a software renderer silently did nothing, so the code falls back to the CPU.
I also lost work. A clean-up step in my setup followed directory links into the main folder and emptied the reference recordings and every old benchmark render. I rebuilt the reference clips from the raw downloads and checked them feature for feature. The renders from versions 0 to 13 are gone for good, and the code that made them was not kept anywhere I can get it back from. That is why the history above is only numbers.
What is unfinished
There is a desktop app built with Tauri, around 90,000 lines of Rust across the simulator and the app, tests included. A release build (18.8 MiB) passed an automated launch check of about 20 seconds: engine loaded, then the first-run benchmark, no audio dropouts. That check ran with the master volume at -120 dB, so it shows the app starts and keeps up, not that it sounds right. An unsigned 6.9 MiB Windows installer builds, but it has not been through a full install test yet. I have also run it live myself, driving an engine in the app. It works, but it is a work in progress and pretty compute-heavy, in line with the speed numbers above. Still open: MIDI input, rebuilding the installer with the keyboard and gamepad input and the head-related transfer table (for binaural headphone sound) added since, a ten-minute run with no underruns, and the GPU quality tier measurements. A browser version and the repository will both be public soon. I haven't chosen the licence yet.


The bigger gaps are a listening test with people, and calibrated recordings to fit the source gains against.
- Stack
- Rust (dependency-free core), WebAssembly, WGSL GPU kernels, wgpu, Tauri, Python for analysis and the benchmark
- Status
- In progress
- Code
- Not public yet. The repository goes public soon, with a licence still to be chosen. Inspired by engine-sim community edition.