RmsPeakAnalyzer.java
package org.hammer.audio.analysis;
import org.hammer.audio.core.AudioBlock;
/**
* Computes per-channel RMS (root-mean-square) and peak (max absolute) values for an audio block.
*
* <p>The RMS of an N-frame signal {@code x[i]} is
*
* <pre>{@code rms = sqrt( (1/N) * sum( x[i]^2 ) )}</pre>
*
* and the peak is {@code max(|x[i]|)}. Both are reported in the same normalized linear units as the
* input samples ({@code [0, 1]} for a unit-amplitude signal).
*
* <p>This analyzer is stateless and thread-safe: a single instance can be safely shared between
* threads.
*
* @author refactoring
*/
public final class RmsPeakAnalyzer implements AnalysisModule<RmsPeakSnapshot> {
@Override
public RmsPeakSnapshot analyze(AudioBlock block) {
int channels = block.channels();
int frames = block.frames();
float[] rms = new float[channels];
float[] peak = new float[channels];
for (int c = 0; c < channels; c++) {
float[] samples = block.channelView(c);
double sumSq = 0.0;
float p = 0f;
for (int i = 0; i < frames; i++) {
float s = samples[i];
float a = s < 0 ? -s : s;
if (a > p) {
p = a;
}
sumSq += (double) s * (double) s;
}
rms[c] = frames == 0 ? 0f : (float) Math.sqrt(sumSq / frames);
peak[c] = p;
}
return new RmsPeakSnapshot(block.frameIndex(), block.timestampNanos(), rms, peak);
}
}