#pragma once #include "FluidSim/Silencer.hpp" #include "FluidSim/EngineConfig.hpp" #include "FluidSim/ScenarioSnapshot.hpp" #include "FluidSim/Carburetor.hpp" #include #include "FluidSim/Junction.hpp" #include "FluidSim/AudioProcessing.hpp" #include "FluidSim/Engine.hpp" #include "FluidSim/Ecu.hpp" #include "FluidSim/Fluid.hpp" #include "FluidSim/OutdoorAudio.hpp" #include "FluidSim/Solver.hpp" #include "FluidSim/Vehicle.hpp" #include "FluidSim/MotorcycleTest.hpp" #include #include #include #include #include namespace fluidsim::port { struct ScenarioExample; // Calibrated four-stroke assembly with independent runners and shared plenums. class FourStrokeScenario : public MotorcycleTest { public: explicit FourStrokeScenario(int sample_rate = 44100, FourStrokePreset preset = FourStrokePreset::Twin); FourStrokeScenario(int sample_rate, const ScenarioExample& definition); FourStrokeScenario(int sample_rate, EngineConfig engine, ExhaustConfig exhaust = {}, JunctionConfig junctions = {}); const ExhaustConfig exhaust_config; const JunctionConfig junction_config; const EngineConfig engine_config; int cylinder_count() const { return engine_config.cylinders; } std::array cylinders() { return {&cylinder1, &cylinder2, &cylinder3, &cylinder4, &cylinder5, &cylinder6, &cylinder7, &cylinder8,&cylinder9,&cylinder10,&cylinder11,&cylinder12}; } AudioFrame process(); void set_controls(float throttle_value, float load_value, float clutch_value); void set_audio_scene(OutdoorScene scene); void set_listener(AudioListener listener); void set_pipe_solver(PipeSolver solver); void set_monitor_filter(bool enabled); void set_starter(bool engaged); AudioFrame dry_audio() const; AudioFrame unfiltered_audio() const; void shift_up(); void shift_down(); void set_neutral(); void set_first_gear(); ScenarioSnapshot snapshot() const; float throttle{}; Ecu ecu{}; Crankshaft crankshaft{}; FourStrokeCylinder cylinder1{}, cylinder2{}, cylinder3{}, cylinder4{}; FourStrokeCylinder cylinder5{}, cylinder6{}, cylinder7{}, cylinder8{}; FourStrokeCylinder cylinder9{}, cylinder10{}, cylinder11{}, cylinder12{}; Volume0D intake_plenum; Junction exhaust_collector; std::vector pipes; float intake_flow{}, exhaust_flow{}; std::uint64_t sample_count{}; private: float throttle_area_{}, runner_area_{}, header_area_{}, tail_area_{}; std::array intake_valve_areas_{}, exhaust_valve_areas_{}; float dt_{}; BoundarySystem boundaries_; Solver solver_; OutdoorAudio audio_; mutable std::mutex mutex_; std::vector> exhaust_junctions_; std::unique_ptr carb_; Port* throttle_port_{}; static float area_for_diameter(float diameter); static std::vector create_pipes(const EngineConfig& engine, const ExhaustConfig& exhaust); }; using FourStrokeTwinScenario = FourStrokeScenario; class AmericanV8Scenario : public FourStrokeScenario { public: explicit AmericanV8Scenario(int sample_rate = 44100) : FourStrokeScenario(sample_rate, FourStrokePreset::AmericanV8) {} }; class SaabB205Scenario : public FourStrokeScenario { public: explicit SaabB205Scenario(int sample_rate = 44100) : FourStrokeScenario(sample_rate, FourStrokePreset::SaabB205) {} }; } // namespace fluidsim::port