76 lines
2.8 KiB
C#
76 lines
2.8 KiB
C#
using System;
|
||
using FluidSim.Core;
|
||
|
||
namespace FluidSim.Core
|
||
{
|
||
/// <summary>
|
||
/// 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.
|
||
/// </summary>
|
||
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;
|
||
|
||
/// <summary>
|
||
/// </summary>
|
||
/// <param name="sampleRate">Audio sample rate (Hz).</param>
|
||
/// <param name="listenerDistanceMeters">Listener distance (m).</param>
|
||
/// <param name="pipeDiameterMeters">Ignored in this model; kept for compatibility.</param>
|
||
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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Process one sample. The OpenEndLink provides the instantaneous
|
||
/// exit‑plane mass flow.
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
} |