SimpleDopplerEstimator.java
package org.hammer.audio.experimental.acoustic.doppler;
/**
* Linearized small-velocity Doppler estimator using {@code v_r ~= c * (f_observed - f_reference) /
* f_reference}.
*
* <p>This approximation is intended for source speeds much smaller than the speed of sound.
* Positive radial velocity means the source moves toward the microphone.
*/
public final class SimpleDopplerEstimator implements DopplerEstimator {
/** Default speed of sound in air in m/s. */
public static final double DEFAULT_SPEED_OF_SOUND_METERS_PER_SECOND = 343.0;
private final double speedOfSoundMetersPerSecond;
/** Create an estimator with the default speed of sound. */
public SimpleDopplerEstimator() {
this(DEFAULT_SPEED_OF_SOUND_METERS_PER_SECOND);
}
/** Create an estimator with a configurable speed of sound. */
public SimpleDopplerEstimator(double speedOfSoundMetersPerSecond) {
if (!(speedOfSoundMetersPerSecond > 0.0) || !Double.isFinite(speedOfSoundMetersPerSecond)) {
throw new IllegalArgumentException("speedOfSoundMetersPerSecond must be finite and > 0");
}
this.speedOfSoundMetersPerSecond = speedOfSoundMetersPerSecond;
}
@Override
public double estimateRadialVelocity(double observedFrequencyHz, double referenceFrequencyHz) {
if (!Double.isFinite(observedFrequencyHz) || observedFrequencyHz < 0.0) {
throw new IllegalArgumentException("observedFrequencyHz must be finite and >= 0");
}
if (!(referenceFrequencyHz > 0.0) || !Double.isFinite(referenceFrequencyHz)) {
throw new IllegalArgumentException("referenceFrequencyHz must be finite and > 0");
}
return speedOfSoundMetersPerSecond
* (observedFrequencyHz - referenceFrequencyHz)
/ referenceFrequencyHz;
}
/** Configured speed of sound in m/s. */
public double speedOfSoundMetersPerSecond() {
return speedOfSoundMetersPerSecond;
}
}