All Windows calculated with pyfda (Python Filter Design Analysis Tool)
https://github.com/chipmuenk/pyfda
Window = Kaiser
beta = 8.6 (Similar to a Blackman Window)
fc = 22.5kHz
-86dB by 23kHz
This also gets rid of Linear Interpolation which leaves only Low and High both being Windowed Sinc.
The resample_factor_reciprocal also happens to be our
anti-alias cutoff. In this case it represents the minimum
output bandwidth needed to fully represent the input.
Cap the output bandwidth to 92%.
Even at 48kHz it still translates to 100% source bandwidth.
This just provides a little bit of anti-alias filtering.
There is more then likely nothing there to filter,
but it doesn't hurt or cost us anything to make sure.
Since we are including the pipeline latency in the position we need to seek to the correct position when going from paused to play.
We can also drop the ALSA and PulseAudio buffers instead of draining them since their latency's are factored in.
Time impl's from f64 (as secs) so there's no need to manually calculate it beyond converting ms to sec.
If we grab the TimeBase in new we don't need to continually call decoder.codec_params().time_base everytime we want to convert ts to ms.
Collect is probably fine but for code that's this hot it's worth the couple extra lines to make certain there's only ever one allocation when it comes to the returned Vec.
It would be so much easier to use elapsed but elapsed could potentially panic is rare cases.
See: https://doc.rust-lang.org/std/time/struct.Instant.html#monotonicity
Otherwise this is pretty straight forward.
If anything fails getting expected_position_ms it will return 0 which will trigger a notify if either stream_position_ms or decoder_position_ms is > 1000.
If all goes well it's simply a matter of calculating the max delta of expected_position_ms and stream_position_ms and expected_position_ms and decoder_position_ms.
So if the decoder or the sample pipeline are off by more than 1 sec we notify.