Load engines from TOML and improve scenario audio and carb tuning

Migrate 32 engine definitions into validated startup-loaded TOML files and separate configuration and snapshots from scenario assembly. Add camera-based stereo propagation from shared pipe geometry, preserve exhaust character, tune carburetor mixtures and idle, use ignition cuts for carb engines, and support returning to the scenario menu.

Validation: full Windows build and all 14 CTest checks passed.
This commit is contained in:
max
2026-10-24 03:24:35 +02:00
parent 5607dcf2b5
commit bf8621ad39
82 changed files with 24084 additions and 648 deletions

View File

@@ -0,0 +1,71 @@
# Carburetor calibration
The catalog contains seven carbureted two-strokes and two carbureted
four-strokes. The 450 cc four-stroke is now carbureted; the 650 cc stays EFI.
The 125 variants use a 3% fixed slide stop plus closed-throttle ignition trim;
the 50/500 singles use 4.5%. The big-block uses 7%.
## Measurement
The `fluidsim_carb_calibration` tool imposes crankshaft RPM with an external
motoring/absorbing dyno, runs 1 s to settle, and averages the following 0.25 s.
Each operating point starts from a fresh warm scenario. At idle, the dyno is then
removed for a further 3 s to check that the engine continues running without
starter assistance or artificial sustaining torque.
| Family | Idle RPM | Low RPM | Mid RPM | Full-throttle RPM |
| --- | ---: | ---: | ---: | ---: |
| Two-strokes | 3000 | 4000 | 6500 | 9000 |
| 450 single | 1400 | 2500 | 4000 | 6000 |
| Big-block | 800 | 1800 | 3000 | 5000 |
Low points use 5%, 10%, 15% and 25% pedal; mid points use 50% and 75%.
The mechanical stop remains in force if pedal demand is lower than it.
AFR acceptance is 11.5?15.5, narrowed to 11.5?14.5 at full throttle. Free-idle
AFR must also stay within 11.5?15.5, with positive running RPM (300?10000).
The fixed slide sets idle airflow. Closed-throttle ignition timing trims speed
toward 3,000 RPM on the 125s, 3,000 RPM on the 50, and 3,000 RPM on the 500.
Four-stroke targets are 1,400 RPM for the 450 and 800 RPM for the big-block.
## Settled idle and carb-outlet AFR
| Scenario | Stop | Unloaded idle RPM | Idle AFR | 15% AFR | 50% AFR | Full AFR |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| Racing 125 | 3% | 3603 | 13.49 | 14.56 | 13.56 | 13.27 |
| Straight 125 | 3% | 3754 | 13.48 | 14.70 | 13.32 | 13.27 |
| Long chamber 125 | 3% | 3598 | 13.37 | 14.64 | 13.42 | 13.21 |
| Short chamber 125 | 3% | 3657 | 13.61 | 14.58 | 13.66 | 13.26 |
| Wide chamber 125 | 3% | 3679 | 13.44 | 14.37 | 13.58 | 13.27 |
| 50 two-stroke | 4.5% | 3591 | 14.46 | 14.71 | 13.64 | 12.92 |
| 500 two-stroke | 4.5% | 3128 | 13.63 | 13.23 | 13.85 | 13.26 |
| 450 four-stroke | 4.5% | 1362 | 13.54 | 14.10 | 13.67 | 13.07 |
| Big-block | 7% | 763 | 13.52 | 14.68 | 13.12 | 13.17 |
The previous 125 calibration measured approximately 7.6 at idle, 22.6 at low
pedal and 20.2 at full pedal. The previous big-block reached approximately 28.7
at full pedal. Independent pilot and main jet dimensions plus a continuous,
monotone needle annulus profile correct the off-idle and upper-throttle gaps.
These are effective flow calibrations, not measured commercial jet sizes.
The tool reports `charge_afr` separately: crankcase air/fuel for two-strokes,
intake-plenum air/fuel for four-strokes. Reverse flow, residual oxygen depletion,
wet-wall transients and transported unburned fuel make that differ from fresh
carb-outlet AFR. It is diagnostic rather than the calibration target. Combustion
still consumes only the oxygen and fuel actually present; AFR is not clamped to
hide a bad mixture and no feedback loop forces the target values.
## Reproduction
```powershell
cmake --build --preset windows
ctest --preset windows -R carb_calibration --output-on-failure
./out/build/windows-gcc/fluidsim_carb_calibration.exe --sweep yz-racing
```
The calibration sweep includes all eight throttle positions for every carb scenario,
target idle RPM and AFR, zero pipe positivity repairs, the catalog slide-stop settings,
and transported fueling on the 450. Catalog and two-stroke regressions also
exercise throttle changes, coast-down, clutch/gear operation and finite audio.
[Four-point AFR, charge, and idle measurements](carb_calibration.csv) include charge AFR,
actual idle opening, free-running idle RPM and pipe repair counts.

View File

@@ -0,0 +1,38 @@
# Custom exhaust pulse character
Compared the previous `src/scenario.cpp` from HEAD with the updated implementation
using the same capture tool, default Rusanov solver, dry scene, 55% pedal,
3,000 RPM, 0.6 s warmup and 0.5 s recording. No gain normalization or added
noise/distortion was applied. Captures are in `out/audio-character/`.
Energy fractions below use both channels, discard the first 20% of the recording,
remove DC and apply a Hann window. The denominator is spectral energy from 20 Hz
to 6 kHz. Upper harmonics are above 1.5 times the aggregate firing frequency
(RPM / 120 * cylinders); low orders are below 0.8 times that frequency. These
are engineering checks on pulse character, not a perceptual realism score.
| Example | Upper harmonics, before ? after | Low orders, before ? after |
| --- | --- | --- |
| Inline three | 78.6% ? 85.6% | <0.1% ? <0.1% |
| F20 inline four | 53.2% ? 87.0% | <0.1% ? 1.1% |
| Inline five | 51.6% ? 92.5% | <0.1% ? 0.3% |
| RB26 inline six | 21.4% ? 88.4% | <0.1% ? <0.1% |
| Long-stroke inline six | 29.0% ? 81.3% | <0.1% ? <0.1% |
| Big-block V8 | 40.3% ? 59.6% | <0.1% ? 23.2% |
| V10 | 84.6% ? 31.0% | <0.1% ? 14.4% |
| V12 | 52.2% ? 55.1% | 0.1% ? 19.7% |
The V10's energy shifts toward lower bank orders rather than simply becoming
brighter. All eight updated examples also completed fixed-RPM captures at 1,000
and 6,000 RPM using the same warmup/duration/pedal. All 24 updated captures
produced finite audio with zero clipping samples. Maximum rendered absolute
amplitude across these captures was 0.524 full scale.
The catalog regression runs each example through one second of throttle and one
second of pedal release. It checks finite audio, sustained positive RPM, zero
pipe positivity repairs, big-block power, and the new topology flags. The desktop
UI and physics regression tests cover the existing controls and base simulation.
For listening comparisons, match playback loudness: removing large collector
volumes increases level as well as changing spectrum. Geometry and calibration
remain estimates; these measurements do not establish a match to recorded engines.

View File

@@ -0,0 +1,37 @@
example,pedal,rpm,opening,carb_afr,charge_afr,free_idle_rpm,free_idle_afr,repairs
yz-racing,0,3000,0.03,13.4852,17.6506,3602.68,13.2998,0
yz-racing,0.15,4000,0.15,14.5615,14.5141,0,0,0
yz-racing,0.5,6500,0.5,13.5614,11.0273,0,0,0
yz-racing,1,9000,1,13.2665,9.14679,0,0,0
yz-straight,0,3000,0.03,13.4847,13.8691,3753.7,13.4844,0
yz-straight,0.15,4000,0.15,14.6983,14.6936,0,0,0
yz-straight,0.5,6500,0.5,13.3192,8.37308,0,0,0
yz-straight,1,9000,1,13.2662,8.6134,0,0,0
yz-torque,0,3000,0.03,13.3698,17.2726,3597.72,13.4608,0
yz-torque,0.15,4000,0.15,14.6447,14.6351,0,0,0
yz-torque,0.5,6500,0.5,13.4205,9.57616,0,0,0
yz-torque,1,9000,1,13.2114,9.72874,0,0,0
yz-short,0,3000,0.03,13.6119,18.2684,3657.15,12.7677,0
yz-short,0.15,4000,0.15,14.5772,14.5825,0,0,0
yz-short,0.5,6500,0.5,13.6625,11.2674,0,0,0
yz-short,1,9000,1,13.258,8.56493,0,0,0
yz-fat,0,3000,0.03,13.4371,18.0872,3679.1,13.3084,0
yz-fat,0.15,4000,0.15,14.3698,14.3344,0,0,0
yz-fat,0.5,6500,0.5,13.583,11.1147,0,0,0
yz-fat,1,9000,1,13.2664,9.04608,0,0,0
fifty,0,3000,0.045,14.4588,18.5582,3590.97,14.3795,0
fifty,0.15,4000,0.15,14.7126,14.8354,0,0,0
fifty,0.5,6500,0.5,13.6415,13.2838,0,0,0
fifty,1,9000,1,12.9222,9.32989,0,0,0
fivehundred,0,3000,0.045,13.6326,15.6191,3128.38,13.6017,0
fivehundred,0.15,4000,0.15,13.2298,13.1972,0,0,0
fivehundred,0.5,6500,0.5,13.8488,12.409,0,0,0
fivehundred,1,9000,1,13.2616,10.1366,0,0,0
single-450,0,1400,0.0449999,13.5449,14.5374,1362.41,13.4177,0
single-450,0.15,2500,0.15,14.103,14.0662,0,0,0
single-450,0.5,4000,0.499999,13.668,13.9308,0,0,0
single-450,1,6000,0.999999,13.0708,10.7667,0,0,0
big-carb,0,800,0.0699998,13.5196,13.7285,763.257,13.5412,0
big-carb,0.15,1800,0.15,14.6817,14.6857,0,0,0
big-carb,0.5,3000,0.499999,13.1217,13.1227,0,0,0
big-carb,1,5000,0.999999,13.1704,13.174,0,0,0
1 example pedal rpm opening carb_afr charge_afr free_idle_rpm free_idle_afr repairs
2 yz-racing 0 3000 0.03 13.4852 17.6506 3602.68 13.2998 0
3 yz-racing 0.15 4000 0.15 14.5615 14.5141 0 0 0
4 yz-racing 0.5 6500 0.5 13.5614 11.0273 0 0 0
5 yz-racing 1 9000 1 13.2665 9.14679 0 0 0
6 yz-straight 0 3000 0.03 13.4847 13.8691 3753.7 13.4844 0
7 yz-straight 0.15 4000 0.15 14.6983 14.6936 0 0 0
8 yz-straight 0.5 6500 0.5 13.3192 8.37308 0 0 0
9 yz-straight 1 9000 1 13.2662 8.6134 0 0 0
10 yz-torque 0 3000 0.03 13.3698 17.2726 3597.72 13.4608 0
11 yz-torque 0.15 4000 0.15 14.6447 14.6351 0 0 0
12 yz-torque 0.5 6500 0.5 13.4205 9.57616 0 0 0
13 yz-torque 1 9000 1 13.2114 9.72874 0 0 0
14 yz-short 0 3000 0.03 13.6119 18.2684 3657.15 12.7677 0
15 yz-short 0.15 4000 0.15 14.5772 14.5825 0 0 0
16 yz-short 0.5 6500 0.5 13.6625 11.2674 0 0 0
17 yz-short 1 9000 1 13.258 8.56493 0 0 0
18 yz-fat 0 3000 0.03 13.4371 18.0872 3679.1 13.3084 0
19 yz-fat 0.15 4000 0.15 14.3698 14.3344 0 0 0
20 yz-fat 0.5 6500 0.5 13.583 11.1147 0 0 0
21 yz-fat 1 9000 1 13.2664 9.04608 0 0 0
22 fifty 0 3000 0.045 14.4588 18.5582 3590.97 14.3795 0
23 fifty 0.15 4000 0.15 14.7126 14.8354 0 0 0
24 fifty 0.5 6500 0.5 13.6415 13.2838 0 0 0
25 fifty 1 9000 1 12.9222 9.32989 0 0 0
26 fivehundred 0 3000 0.045 13.6326 15.6191 3128.38 13.6017 0
27 fivehundred 0.15 4000 0.15 13.2298 13.1972 0 0 0
28 fivehundred 0.5 6500 0.5 13.8488 12.409 0 0 0
29 fivehundred 1 9000 1 13.2616 10.1366 0 0 0
30 single-450 0 1400 0.0449999 13.5449 14.5374 1362.41 13.4177 0
31 single-450 0.15 2500 0.15 14.103 14.0662 0 0 0
32 single-450 0.5 4000 0.499999 13.668 13.9308 0 0 0
33 single-450 1 6000 0.999999 13.0708 10.7667 0 0 0
34 big-carb 0 800 0.0699998 13.5196 13.7285 763.257 13.5412 0
35 big-carb 0.15 1800 0.15 14.6817 14.6857 0 0 0
36 big-carb 0.5 3000 0.499999 13.1217 13.1227 0 0 0
37 big-carb 1 5000 0.999999 13.1704 13.174 0 0 0