summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-06-21 15:33:51 +1000
committerjacqueline <me@jacqueline.id.au>2023-06-21 15:33:51 +1000
commitb58b072d2d42cc1a9dab3e6b27f2f3ae70fe7610 (patch)
treeea057f6ad3b9be91f098a49598219d7217740a4d
parent23ecff10112ffd8cace0a0f41f4abd45222af2d8 (diff)
downloadtangara-fw-b58b072d2d42cc1a9dab3e6b27f2f3ae70fe7610.tar.gz
Add current playback timestamps
-rw-r--r--src/audio/audio_fsm.cpp4
-rw-r--r--src/audio/audio_task.cpp36
-rw-r--r--src/audio/i2s_audio_output.cpp4
-rw-r--r--src/audio/include/audio_events.hpp5
-rw-r--r--src/audio/include/audio_fsm.hpp4
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> pipeline, IAudioSink* sink) {
std::vector<Pipeline*> 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> pipeline, IAudioSink* sink) {
}
}
+ if (!has_work) {
+ has_work = !xStreamBufferIsEmpty(sink->buffer());
+ }
+
if (previously_had_work && !has_work) {
events::Dispatch<AudioPipelineIdle, AudioState>({});
}
@@ -127,6 +135,10 @@ void AudioTaskMain(std::unique_ptr<Pipeline> 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> pipeline, IAudioSink* sink) {
xStreamBufferSend(sink->buffer(), sink_stream.data().data(),
sink_stream.data().size_bytes(), 0);
+ if (std::holds_alternative<StreamInfo::Pcm>(*output_format)) {
+ StreamInfo::Pcm pcm = std::get<StreamInfo::Pcm>(*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<PlaybackUpdate, AudioState>(
+ {.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<float>(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 <stdint.h>
#include <string>
#include "tinyfsm.hpp"
@@ -23,6 +24,10 @@ struct PlayTrack : tinyfsm::Event {
std::optional<database::TrackData> 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<AudioState> {
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;