namespace ytLive.Services.Audio;
///
/// A tiny stateful linear-interpolation sample-rate converter (TASK 9). NAudio's
/// WASAPI capture rate follows the device mix format; the stream needs a fixed
/// 48 kHz, so each source normalizes through one of these. Purely a fallback —
/// the mic requests 48 kHz float up front, and most loopback mix formats are
/// already 48 kHz, in which case is false and the
/// chunk passes through untouched. Pure — unit-tested.
///
public sealed class TinyResampler
{
private readonly double _ratio;
private double _pos;
/// The source sample rate.
/// The target sample rate (48 kHz for the stream).
public TinyResampler(int inputRate, int outputRate)
{
if (inputRate <= 0 || outputRate <= 0)
throw new ArgumentOutOfRangeException();
_ratio = (double)inputRate / outputRate;
}
public bool NeedsResampling => Math.Abs(_ratio - 1.0) > 1e-9;
/// Converts one interleaved chunk, keeping the phase across calls.
public float[] Process(float[] input)
{
if (!NeedsResampling)
return input;
var outLen = (int)((_pos + input.Length) / _ratio);
var output = new float[outLen];
for (var i = 0; i < outLen; i++)
{
var inPos = _pos + i * _ratio;
var idx = (int)inPos;
if (idx >= input.Length)
{
output[i] = input[input.Length - 1];
continue;
}
var frac = (float)(inPos - idx);
var a = input[idx];
var b = idx + 1 < input.Length ? input[idx + 1] : a;
output[i] = a + (b - a) * frac;
}
_pos += outLen * _ratio - input.Length;
return output;
}
public void Reset() => _pos = 0;
}