Причина найдена и устранена.
HeartRateEstimator считал частоту кадров от метки первого образца, попавшего в окно, а после заполнения окна (300 образцов) каждый новый вытеснял старый, метка первого не двигалась. Число образцов стояло на 300, промежуток рос с каждой секундой — частота кадров, разрешение спектра и показание падали без конца.
Воспроизведено на ровных 72 уд/мин: 71–72 до 10 секунд, затем 66, 60, 56, 52, 48, минута на нижней границе 45, скачок к 180 и новое сползание до 96 к третьей минуте.
Правка: у каждого образца своя метка времени, метки сдвигаются вместе с образцами, частота кадров считается по окну.
Тесты: a_steady_pulse_reads_steady_for_minutes (три минуты, чтение каждый кадр, отклонение не больше 3 уд/мин), the_pulse_does_not_drift_with_the_frame_rate (15, 24, 30 кадров в секунду). Прежние тесты подавали ровно одно окно и сдвиг не видели.