fix premature pause at end of last track of queue

The SetTrack event is sent when *decoding* finishes, not when
*playback* finishes so the decoder can start buffering the next
track in advance of its playback to ensure gapless playback.
Clearing StreamCues causes
Playback::react(const internal::StreamHeartbeat& ev)
to transit the Playback FSM to Standby, which sets the
IAudioOutput to stop reading from the output buffer. Thus,
clearing StreamCues in response to the SetTrack event paused
playback with the end of the track stuck waiting in the output
buffer. When a new queue was loaded and started playing, the
end of the previous track would be played before the new track
was played.

Fixes https://codeberg.org/cool-tech-zone/tangara-fw/issues/313
custom-try-329
Be 1 week ago
parent 71ac67bad3
commit c4c6c9df7b
  1. 3
      src/tangara/audio/audio_fsm.cpp
  2. 5
      src/tangara/audio/stream_cues.cpp
  3. 2
      src/tangara/audio/stream_cues.hpp

@ -148,9 +148,7 @@ void AudioState::react(const QueueUpdate& ev) {
void AudioState::react(const SetTrack& ev) { void AudioState::react(const SetTrack& ev) {
if (std::holds_alternative<std::monostate>(ev.new_track)) { if (std::holds_alternative<std::monostate>(ev.new_track)) {
ESP_LOGI(kTag, "playback finished, awaiting drain");
sDecoder->open({}); sDecoder->open({});
sStreamCues.clear();
return; return;
} }
@ -212,6 +210,7 @@ void AudioState::react(const TtsPlaybackChanged& ev) {
} }
void AudioState::react(const internal::DecodingFinished& ev) { void AudioState::react(const internal::DecodingFinished& ev) {
ESP_LOGD(kTag, "end of file decoded; awaiting playback of buffered audio");
// If we just finished playing whatever's at the front of the queue, then we // If we just finished playing whatever's at the front of the queue, then we
// need to advanve and start playing the next one ASAP in order to continue // need to advanve and start playing the next one ASAP in order to continue
// gaplessly. // gaplessly.

@ -43,11 +43,6 @@ auto StreamCues::addCue(std::shared_ptr<TrackInfo> track, uint32_t sample)
} }
} }
auto StreamCues::clear() -> void {
upcoming_.clear();
current_ = {};
}
auto StreamCues::current() -> std::pair<std::shared_ptr<TrackInfo>, uint32_t> { auto StreamCues::current() -> std::pair<std::shared_ptr<TrackInfo>, uint32_t> {
if (!current_) { if (!current_) {
return {}; return {};

@ -34,8 +34,6 @@ class StreamCues {
auto addCue(std::shared_ptr<TrackInfo>, uint32_t start_at) -> void; auto addCue(std::shared_ptr<TrackInfo>, uint32_t start_at) -> void;
auto clear() -> void;
private: private:
uint32_t now_; uint32_t now_;

Loading…
Cancel
Save