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;
}
}
}