namespace DeepDrftContent.Processors;
///
/// Strategy for reducing a stream of PCM samples to a fixed-length, peak-normalized loudness
/// envelope. Swappable so the loudness measure (RMS today, LUFS later) can change without
/// touching WaveformProfileService, the stored wire format, or the frontend renderer.
///
public interface ILoudnessAlgorithm
{
///
/// Computes a peak-normalized loudness profile from raw interleaved PCM.
///
/// Interleaved, little-endian PCM sample bytes (the WAV data chunk).
/// Number of interleaved channels; averaged to mono per sample.
/// Samples per second (unused by RMS but part of the contract for measures that need it).
/// Bit depth (8 unsigned, 16/24/32 signed) used to decode samples.
/// Number of equal time slices to reduce the signal to.
///
/// A double[bucketCount], each value in [0, 1], peak-normalized so the loudest bucket
/// is 1. All zeros when the signal is silent (peak is 0) or no samples are present.
///
double[] Compute(ReadOnlySpan pcmData, int channels, int sampleRate, int bitsPerSample, int bucketCount);
///
/// Creates a stateful accumulator that reduces the same loudness profile from PCM fed in bounded
/// chunks rather than from one contiguous buffer. The streaming waveform path uses this so a long
/// track's PCM is never materialized whole in a managed byte[]. The accumulator's output is
/// byte-identical to for the same total PCM, because is
/// itself defined in terms of one — the single source of truth for the loudness reduction.
///
///
/// Total length of the PCM data region in bytes. Required up front because the bucket each frame
/// lands in is derived from the frame's position relative to the total frame count.
///
/// Number of interleaved channels; averaged to mono per frame.
/// Samples per second (used for the envelope-smoothing time base).
/// Bit depth (8 unsigned, 16/24/32 signed) used to decode samples.
/// Number of equal time slices to reduce the signal to.
ILoudnessAccumulator CreateAccumulator(
long pcmByteLength, int channels, int sampleRate, int bitsPerSample, int bucketCount);
}
///
/// Stateful, single-pass reducer for one loudness profile. Frames are fed via in
/// arbitrary (non-frame-aligned) chunks — a partial frame straddling a chunk boundary is carried
/// internally — and emits the peak-normalized double[bucketCount]. Not
/// thread-safe; feed one stream sequentially. Reusable across the same stream's chunks only, not
/// across streams.
///
public interface ILoudnessAccumulator
{
///
/// Feeds the next run of PCM bytes (interleaved, little-endian). Need not be frame-aligned; bytes
/// that do not complete a frame are retained until the next call. Bytes past the total frame count
/// declared at construction are ignored, matching the whole-buffer path's trailing-partial-frame drop.
///
void Add(ReadOnlySpan pcmChunk);
///
/// Finalizes and returns the peak-normalized loudness profile (double[bucketCount], each in
/// [0, 1]). All zeros for silence or a degenerate (no-frame) input. Call once, after the last
/// .
///
double[] Finish();
}