using System; using FluidSim.Core; namespace FluidSim.Core { /// /// Synthesises far‑field exhaust sound using the monopole model /// of Jones (1978). The radiated pressure is proportional to the /// time derivative of the mass flow at the pipe exit. /// /// Reference: /// Jones, A.D. (1978) "Noise characteristics and exhaust process /// gas dynamics of a small 2-stroke engine", PhD thesis, Univ. Adelaide. /// public class SoundProcessor { private readonly double dt; private readonly double r; // listener distance (m) private readonly double scaleFactor; // 1 / (4π r) (free-field monopole) // ---------- Mass‑flow derivative (identical to original) ---------- private double flowLP; private readonly double lpAlpha; private double prevMassFlowOut; private double smoothDMdt; private readonly double alpha; public float Gain { get; set; } = 1.0f; /// /// /// Audio sample rate (Hz). /// Listener distance (m). /// Ignored in this model; kept for compatibility. public SoundProcessor(int sampleRate, double listenerDistanceMeters = 1.0, double pipeDiameterMeters = 0.0217) { dt = 1.0 / sampleRate; r = listenerDistanceMeters; scaleFactor = 1.0 / (4.0 * Math.PI * r); // free‑field monopole // ---- Smoothing time constants (unchanged) ---- double tau = 0.02; // 2 ms for derivative alpha = Math.Exp(-dt / tau); double tauLP = 0.00001; // 5 ms low‑pass on mass flow lpAlpha = Math.Exp(-dt / tauLP); } /// /// Process one sample. The OpenEndLink provides the instantaneous /// exit‑plane mass flow. /// public float Process(OpenEndLink openEnd) { double flowOut = openEnd.LastMassFlowRate; // kg/s, positive = leaving pipe // Low‑pass the mass flow signal flowLP = lpAlpha * flowLP + (1.0 - lpAlpha) * flowOut; // Derivative of the smoothed mass flow double rawDerivative = (flowLP - prevMassFlowOut) / dt; prevMassFlowOut = flowLP; // Smooth the derivative smoothDMdt = alpha * smoothDMdt + (1.0 - alpha) * rawDerivative; // Far‑field monopole pressure (free‑field, Jones eq. 2.15 adapted) double pressure = smoothDMdt * scaleFactor * Gain; // Soft clip to ±1 return (float)pressure; } } }