namespace ytLive.Services.Audio;

/// <summary>
/// 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 <see cref="NeedsResampling"/> is false and the
/// chunk passes through untouched. Pure — unit-tested.
/// </summary>
public sealed class TinyResampler
{
    private readonly double _ratio;
    private double _pos;

    /// <param name="inputRate">The source sample rate.</param>
    /// <param name="outputRate">The target sample rate (48 kHz for the stream).</param>
    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;

    /// <summary>Converts one interleaved chunk, keeping the phase across calls.</summary>
    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;
}
