From b58b072d2d42cc1a9dab3e6b27f2f3ae70fe7610 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 21 Jun 2023 15:33:51 +1000 Subject: [PATCH] Add current playback timestamps --- src/audio/audio_fsm.cpp | 4 ++++ src/audio/audio_task.cpp | 36 ++++++++++++++++++++++++++++++ src/audio/i2s_audio_output.cpp | 4 ++-- src/audio/include/audio_events.hpp | 5 +++++ src/audio/include/audio_fsm.hpp | 4 ++++ 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/audio/audio_fsm.cpp b/src/audio/audio_fsm.cpp index a65b9f3b..ffd0d5c3 100644 --- a/src/audio/audio_fsm.cpp +++ b/src/audio/audio_fsm.cpp @@ -111,6 +111,10 @@ void Playback::react(const PlayFile& ev) { sTrackQueue.push_back(EnqueuedItem(ev.filename)); } +void Playback::react(const PlaybackUpdate& ev) { + ESP_LOGI(kTag, "elapsed: %lu", ev.seconds_elapsed); +} + void Playback::react(const InputFileOpened& ev) {} void Playback::react(const InputFileFinished& ev) { diff --git a/src/audio/audio_task.cpp b/src/audio/audio_task.cpp index 10bed656..d4c1d27a 100644 --- a/src/audio/audio_task.cpp +++ b/src/audio/audio_task.cpp @@ -62,6 +62,10 @@ void AudioTaskMain(std::unique_ptr pipeline, IAudioSink* sink) { std::vector all_elements = pipeline->GetIterationOrder(); + float current_sample_in_second = 0; + uint32_t previous_second = 0; + uint32_t current_second = 0; + bool previously_had_work = false; events::EventQueue& event_queue = events::EventQueue::GetInstance(); while (1) { @@ -78,6 +82,10 @@ void AudioTaskMain(std::unique_ptr pipeline, IAudioSink* sink) { } } + if (!has_work) { + has_work = !xStreamBufferIsEmpty(sink->buffer()); + } + if (previously_had_work && !has_work) { events::Dispatch({}); } @@ -127,6 +135,10 @@ void AudioTaskMain(std::unique_ptr pipeline, IAudioSink* sink) { if (sink_stream.info().bytes_in_stream == 0) { if (sink_stream.is_producer_finished()) { sink_stream.mark_consumer_finished(); + + current_second = 0; + previous_second = 0; + current_sample_in_second = 0; } else { // The user is probably about to hear a skip :( ESP_LOGW(kTag, "!! audio sink is underbuffered !!"); @@ -155,6 +167,30 @@ void AudioTaskMain(std::unique_ptr pipeline, IAudioSink* sink) { xStreamBufferSend(sink->buffer(), sink_stream.data().data(), sink_stream.data().size_bytes(), 0); + if (std::holds_alternative(*output_format)) { + StreamInfo::Pcm pcm = std::get(*output_format); + + float samples_sunk = bytes_sunk; + samples_sunk /= pcm.channels; + + int8_t bps = pcm.bits_per_sample; + if (bps == 24) { + bps = 32; + } + samples_sunk /= (bps / 8); + + current_sample_in_second += samples_sunk; + while (current_sample_in_second >= pcm.sample_rate) { + current_second++; + current_sample_in_second -= pcm.sample_rate; + } + if (previous_second != current_second) { + events::Dispatch( + {.seconds_elapsed = current_second}); + } + previous_second = current_second; + } + // Adjust how long we wait for the next iteration if we're getting too far // ahead or behind. float sunk_percent = static_cast(bytes_sunk) / diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp index 982499a0..b61259ad 100644 --- a/src/audio/i2s_audio_output.cpp +++ b/src/audio/i2s_audio_output.cpp @@ -129,8 +129,8 @@ auto I2SAudioOutput::Configure(const StreamInfo::Format& format) -> bool { return true; } - ESP_LOGI(kTag, "incoming audio stream: %u bpp @ %lu Hz", pcm.bits_per_sample, - pcm.sample_rate); + ESP_LOGI(kTag, "incoming audio stream: %u ch %u bpp @ %lu Hz", pcm.channels, + pcm.bits_per_sample, pcm.sample_rate); drivers::I2SDac::Channels ch; switch (pcm.channels) { diff --git a/src/audio/include/audio_events.hpp b/src/audio/include/audio_events.hpp index 60a0740c..7359e8ac 100644 --- a/src/audio/include/audio_events.hpp +++ b/src/audio/include/audio_events.hpp @@ -6,6 +6,7 @@ #pragma once +#include #include #include "tinyfsm.hpp" @@ -23,6 +24,10 @@ struct PlayTrack : tinyfsm::Event { std::optional data; }; +struct PlaybackUpdate : tinyfsm::Event { + uint32_t seconds_elapsed; +}; + struct InputFileOpened : tinyfsm::Event {}; struct InputFileFinished : tinyfsm::Event {}; struct AudioPipelineIdle : tinyfsm::Event {}; diff --git a/src/audio/include/audio_fsm.hpp b/src/audio/include/audio_fsm.hpp index bd902706..1f3b1dbd 100644 --- a/src/audio/include/audio_fsm.hpp +++ b/src/audio/include/audio_fsm.hpp @@ -44,6 +44,8 @@ class AudioState : public tinyfsm::Fsm { virtual void react(const PlayTrack&) {} virtual void react(const PlayFile&) {} + virtual void react(const PlaybackUpdate&) {} + virtual void react(const InputFileOpened&) {} virtual void react(const InputFileFinished&) {} virtual void react(const AudioPipelineIdle&) {} @@ -87,6 +89,8 @@ class Playback : public AudioState { void react(const PlayTrack&) override; void react(const PlayFile&) override; + void react(const PlaybackUpdate&) override; + void react(const InputFileOpened&) override; void react(const InputFileFinished&) override; void react(const AudioPipelineIdle&) override;