SpectrumDisplayState.java
package org.hammer.audio.analysis;
/**
* Aggregated display state for the spectrum panel: combines the live spectrum with optional
* peak-hold and exponential-average traces.
*
* <p>{@link #update(SpectrumSnapshot)} feeds the latest snapshot into all enabled traces. The
* traces are exposed through accessor methods; callers decide whether and how to render them.
*
* <p>Instances are <strong>not thread-safe</strong>; intended to be driven by the Swing EDT.
*/
public final class SpectrumDisplayState {
private final SpectrumAverager averager;
private final PeakHoldSpectrum peakHold;
private boolean averagingEnabled;
private boolean peakHoldEnabled;
private SpectrumSnapshot latest;
/** Create a display state with averaging and peak-hold disabled by default. */
public SpectrumDisplayState() {
this(new SpectrumAverager(), new PeakHoldSpectrum());
}
/**
* Create a display state with the supplied averager and peak-hold trace.
*
* @param averager spectrum averager; must not be {@code null}
* @param peakHold peak-hold trace; must not be {@code null}
*/
public SpectrumDisplayState(SpectrumAverager averager, PeakHoldSpectrum peakHold) {
if (averager == null) {
throw new IllegalArgumentException("averager must not be null");
}
if (peakHold == null) {
throw new IllegalArgumentException("peakHold must not be null");
}
this.averager = averager;
this.peakHold = peakHold;
}
/**
* @return true if exponential averaging is enabled
*/
public boolean isAveragingEnabled() {
return averagingEnabled;
}
/**
* Enable or disable exponential averaging. Disabling also resets the averager state so it does
* not display a stale frozen trace next time it is re-enabled.
*
* @param enabled true to enable averaging
*/
public void setAveragingEnabled(boolean enabled) {
if (!enabled && averagingEnabled) {
averager.reset();
}
this.averagingEnabled = enabled;
}
/**
* @return true if peak-hold display is enabled
*/
public boolean isPeakHoldEnabled() {
return peakHoldEnabled;
}
/**
* Enable or disable the peak-hold trace. Disabling also resets the held peaks.
*
* @param enabled true to enable peak hold
*/
public void setPeakHoldEnabled(boolean enabled) {
if (!enabled && peakHoldEnabled) {
peakHold.reset();
}
this.peakHoldEnabled = enabled;
}
/**
* @return the underlying averager (never {@code null})
*/
public SpectrumAverager averager() {
return averager;
}
/**
* @return the underlying peak-hold trace (never {@code null})
*/
public PeakHoldSpectrum peakHold() {
return peakHold;
}
/**
* @return the most recent snapshot pushed via {@link #update(SpectrumSnapshot)}, or {@code null}
* if none
*/
public SpectrumSnapshot latestSnapshot() {
return latest;
}
/**
* Feed a new spectrum snapshot into the enabled traces.
*
* @param snapshot latest spectrum snapshot; may be {@code null} (no-op)
*/
public void update(SpectrumSnapshot snapshot) {
if (snapshot == null) {
return;
}
this.latest = snapshot;
float[] magnitudes = snapshot.magnitudesView();
if (averagingEnabled) {
averager.update(magnitudes);
}
if (peakHoldEnabled) {
peakHold.update(magnitudes);
}
}
/** Reset the peak-hold trace without disabling it. */
public void resetPeakHold() {
peakHold.reset();
}
/** Reset the averager state without disabling it. */
public void resetAverager() {
averager.reset();
}
/** Reset both auxiliary traces and forget the latest snapshot. */
public void clear() {
averager.reset();
peakHold.reset();
latest = null;
}
}