Add current playback timestamps
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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) /
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user