summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2023-07-31 11:00:17 +1000
committerjacqueline <me@jacqueline.id.au>2023-07-31 11:06:27 +1000
commitcdaa2ac97ac663de7c0c2b0361871c97269b1675 (patch)
treec7ac2908d9294613db6f11138fc54786f4d78dab /src
parent0a8d2fd12e0781c32d23b67dd938e3ba8caf782e (diff)
downloadtangara-fw-cdaa2ac97ac663de7c0c2b0361871c97269b1675.tar.gz
Add duration for flacs
Diffstat (limited to 'src')
-rw-r--r--src/audio/audio_task.cpp68
-rw-r--r--src/audio/include/audio_task.hpp19
-rw-r--r--src/codecs/foxenflac.cpp22
3 files changed, 63 insertions, 46 deletions
diff --git a/src/audio/audio_task.cpp b/src/audio/audio_task.cpp
index 4fad3114..7e0fb207 100644
--- a/src/audio/audio_task.cpp
+++ b/src/audio/audio_task.cpp
@@ -53,20 +53,23 @@ static const char* kTag = "audio_dec";
static constexpr std::size_t kSampleBufferSize = 16 * 1024;
-Timer::Timer(StreamInfo::Pcm format)
- : format_(format),
- current_seconds_(0),
- current_sample_in_second_(0),
- total_duration_seconds_(0) {}
-
-auto Timer::SetLengthSeconds(uint32_t len) -> void {
- total_duration_seconds_ = len;
- has_duration_ = true;
-}
-
-auto Timer::SetLengthBytes(uint32_t len) -> void {
- total_duration_seconds_ = bytes_to_samples(len) / format_.sample_rate;
- has_duration_ = true;
+Timer::Timer(const StreamInfo::Pcm& format, const Duration& duration)
+ : format_(format), current_seconds_(0), current_sample_in_second_(0) {
+ switch (duration.src) {
+ case Duration::Source::kLibTags:
+ ESP_LOGI(kTag, "using duration from libtags");
+ total_duration_seconds_ = duration.duration;
+ break;
+ case Duration::Source::kCodec:
+ ESP_LOGI(kTag, "using duration from decoder");
+ total_duration_seconds_ = duration.duration;
+ break;
+ case Duration::Source::kFileSize:
+ ESP_LOGW(kTag, "calculating duration from filesize");
+ total_duration_seconds_ =
+ bytes_to_samples(duration.duration) / format_.sample_rate;
+ break;
+ }
}
auto Timer::AddBytes(std::size_t bytes) -> void {
@@ -137,14 +140,6 @@ void AudioTask::Main() {
if (ForwardPcmStream(*pcm, stream.data())) {
stream.consume(stream.data().size_bytes());
}
- if (!timer_->has_duration()) {
- if (stream.info().total_length_seconds()) {
- timer_->SetLengthSeconds(*stream.info().total_length_seconds());
- } else {
- timer_->SetLengthBytes(
- stream.info().total_length_bytes().value_or(0));
- }
- }
return;
}
@@ -235,16 +230,20 @@ auto AudioTask::BeginDecoding(InputStream& stream) -> bool {
.sample_rate = format.sample_rate_hz,
};
- if (!ConfigureSink(new_format)) {
- return false;
- }
-
+ Duration duration;
if (format.duration_seconds) {
- timer_->SetLengthSeconds(*format.duration_seconds);
+ duration.src = Duration::Source::kCodec;
+ duration.duration = *format.duration_seconds;
} else if (stream.info().total_length_seconds()) {
- timer_->SetLengthSeconds(*stream.info().total_length_seconds());
+ duration.src = Duration::Source::kLibTags;
+ duration.duration = *stream.info().total_length_seconds();
} else {
- timer_->SetLengthBytes(stream.info().total_length_bytes().value_or(0));
+ duration.src = Duration::Source::kFileSize;
+ duration.duration = *stream.info().total_length_bytes();
+ }
+
+ if (!ConfigureSink(new_format, duration)) {
+ return false;
}
return true;
@@ -307,7 +306,11 @@ auto AudioTask::ForwardPcmStream(StreamInfo::Pcm& format,
cpp::span<const std::byte> samples) -> bool {
// First we need to reconfigure the sink for this sample format.
if (format != current_output_format_) {
- if (!ConfigureSink(format)) {
+ Duration d{
+ .src = Duration::Source::kFileSize,
+ .duration = samples.size_bytes(),
+ };
+ if (!ConfigureSink(format, d)) {
return false;
}
}
@@ -319,7 +322,8 @@ auto AudioTask::ForwardPcmStream(StreamInfo::Pcm& format,
return true;
}
-auto AudioTask::ConfigureSink(const StreamInfo::Pcm& format) -> bool {
+auto AudioTask::ConfigureSink(const StreamInfo::Pcm& format,
+ const Duration& duration) -> bool {
if (format != current_output_format_) {
// The new format is different to the old one. Wait for the sink to drain
// before continuing.
@@ -337,7 +341,7 @@ auto AudioTask::ConfigureSink(const StreamInfo::Pcm& format) -> bool {
}
current_output_format_ = format;
- timer_.reset(new Timer(format));
+ timer_.reset(new Timer(format, duration));
return true;
}
diff --git a/src/audio/include/audio_task.hpp b/src/audio/include/audio_task.hpp
index 72732021..f6e9789b 100644
--- a/src/audio/include/audio_task.hpp
+++ b/src/audio/include/audio_task.hpp
@@ -18,15 +18,21 @@
namespace audio {
+struct Duration {
+ enum class Source {
+ kLibTags,
+ kCodec,
+ kFileSize,
+ };
+ Source src;
+ uint32_t duration;
+};
+
class Timer {
public:
- explicit Timer(StreamInfo::Pcm);
-
- auto SetLengthSeconds(uint32_t) -> void;
- auto SetLengthBytes(uint32_t) -> void;
+ Timer(const StreamInfo::Pcm&, const Duration&);
auto AddBytes(std::size_t) -> void;
- auto has_duration() const -> bool { return has_duration_; }
private:
auto bytes_to_samples(uint32_t) -> uint32_t;
@@ -36,7 +42,6 @@ class Timer {
uint32_t current_seconds_;
uint32_t current_sample_in_second_;
- bool has_duration_;
uint32_t total_duration_seconds_;
};
@@ -57,7 +62,7 @@ class AudioTask {
auto ForwardPcmStream(StreamInfo::Pcm&, cpp::span<const std::byte>) -> bool;
- auto ConfigureSink(const StreamInfo::Pcm&) -> bool;
+ auto ConfigureSink(const StreamInfo::Pcm&, const Duration&) -> bool;
IAudioSource* source_;
IAudioSink* sink_;
diff --git a/src/codecs/foxenflac.cpp b/src/codecs/foxenflac.cpp
index ce18975c..3a727ce2 100644
--- a/src/codecs/foxenflac.cpp
+++ b/src/codecs/foxenflac.cpp
@@ -6,6 +6,7 @@
#include "foxenflac.hpp"
#include <stdint.h>
+#include <sys/_stdint.h>
#include <cstdlib>
@@ -44,13 +45,20 @@ auto FoxenFlacDecoder::BeginStream(const cpp::span<const std::byte> input)
return {bytes_used, cpp::fail(Error::kMalformedData)};
}
- return {bytes_used,
- OutputFormat{
- .num_channels = static_cast<uint8_t>(channels),
- .bits_per_sample = 32, // libfoxenflac output is fixed-size.
- .sample_rate_hz = static_cast<uint32_t>(fs),
- .duration_seconds = {},
- }};
+ OutputFormat format{
+ .num_channels = static_cast<uint8_t>(channels),
+ .bits_per_sample = 32, // libfoxenflac output is fixed-size.
+ .sample_rate_hz = static_cast<uint32_t>(fs),
+ .duration_seconds = {},
+ .bits_per_second = {},
+ };
+
+ uint64_t num_samples = fx_flac_get_streaminfo(flac_, FLAC_KEY_N_SAMPLES);
+ if (num_samples > 0) {
+ format.duration_seconds = num_samples / fs;
+ }
+
+ return {bytes_used, format};
}
auto FoxenFlacDecoder::ContinueStream(cpp::span<const std::byte> input,