summaryrefslogtreecommitdiff
path: root/src/audio/audio_decoder.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-03-25 17:34:41 +1100
committerjacqueline <me@jacqueline.id.au>2024-03-25 17:34:41 +1100
commit175bfc4e3e9f7aa39e084d3f1625347f1d5711ec (patch)
treef71b458f19acca855815ab876944d48a3c5acbcb /src/audio/audio_decoder.cpp
parent5c985afd258a96b68d6bd5a4fade17ed998d2c07 (diff)
downloadtangara-fw-175bfc4e3e9f7aa39e084d3f1625347f1d5711ec.tar.gz
WIP rewrie audio pipeline+fsm guts for more reliability
Diffstat (limited to 'src/audio/audio_decoder.cpp')
-rw-r--r--src/audio/audio_decoder.cpp78
1 files changed, 22 insertions, 56 deletions
diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp
index 68a8a86b..55ebc0ec 100644
--- a/src/audio/audio_decoder.cpp
+++ b/src/audio/audio_decoder.cpp
@@ -5,6 +5,7 @@
*/
#include "audio_decoder.hpp"
+#include <stdint.h>
#include <cstdint>
#include <cstdlib>
@@ -50,39 +51,6 @@ namespace audio {
static constexpr std::size_t kCodecBufferLength =
drivers::kI2SBufferLengthFrames * sizeof(sample::Sample);
-Timer::Timer(std::shared_ptr<Track> t,
- const codecs::ICodec::OutputFormat& format,
- uint32_t current_seconds)
- : track_(t),
- current_seconds_(current_seconds),
- current_sample_in_second_(0),
- samples_per_second_(format.sample_rate_hz * format.num_channels),
- total_duration_seconds_(format.total_samples.value_or(0) /
- format.num_channels / format.sample_rate_hz) {
- track_->duration = total_duration_seconds_;
-}
-
-auto Timer::AddSamples(std::size_t samples) -> void {
- bool incremented = false;
- current_sample_in_second_ += samples;
- while (current_sample_in_second_ >= samples_per_second_) {
- current_seconds_++;
- current_sample_in_second_ -= samples_per_second_;
- incremented = true;
- }
-
- if (incremented) {
- if (total_duration_seconds_ < current_seconds_) {
- total_duration_seconds_ = current_seconds_;
- track_->duration = total_duration_seconds_;
- }
-
- PlaybackUpdate ev{.seconds_elapsed = current_seconds_, .track = track_};
- events::Audio().Dispatch(ev);
- events::Ui().Dispatch(ev);
- }
-}
-
auto Decoder::Start(std::shared_ptr<IAudioSource> source,
std::shared_ptr<SampleConverter> sink) -> Decoder* {
Decoder* task = new Decoder(source, sink);
@@ -92,11 +60,7 @@ auto Decoder::Start(std::shared_ptr<IAudioSource> source,
Decoder::Decoder(std::shared_ptr<IAudioSource> source,
std::shared_ptr<SampleConverter> mixer)
- : source_(source),
- converter_(mixer),
- codec_(),
- timer_(),
- current_format_() {
+ : source_(source), converter_(mixer), codec_(), current_format_() {
ESP_LOGI(kTag, "allocating codec buffer, %u KiB", kCodecBufferLength / 1024);
codec_buffer_ = {
reinterpret_cast<sample::Sample*>(heap_caps_calloc(
@@ -117,7 +81,6 @@ void Decoder::Main() {
}
if (ContinueDecoding()) {
- events::Audio().Dispatch(internal::InputFileFinished{});
stream_.reset();
}
}
@@ -129,6 +92,7 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
codec_.reset(codecs::CreateCodecForType(stream->type()).value_or(nullptr));
if (!codec_) {
ESP_LOGE(kTag, "no codec found");
+ events::Audio().Dispatch(internal::DecoderError{});
return false;
}
@@ -136,6 +100,7 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
if (open_res.has_error()) {
ESP_LOGE(kTag, "codec failed to start: %s",
codecs::ICodec::ErrorString(open_res.error()).c_str());
+ events::Audio().Dispatch(internal::DecoderError{});
return false;
}
stream->SetPreambleFinished();
@@ -146,20 +111,23 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
};
ESP_LOGI(kTag, "stream started ok");
- events::Audio().Dispatch(internal::InputFileOpened{});
-
- auto tags = std::make_shared<Track>(Track{
- .tags = stream->tags(),
- .db_info = {},
- .bitrate_kbps = open_res->sample_rate_hz,
- .encoding = stream->type(),
- .filepath = stream->Filepath(),
- });
- timer_.reset(new Timer(tags, open_res.value(), stream->Offset()));
- PlaybackUpdate ev{.seconds_elapsed = stream->Offset(), .track = tags};
- events::Audio().Dispatch(ev);
- events::Ui().Dispatch(ev);
+ std::optional<uint32_t> duration;
+ if (open_res->total_samples) {
+ duration = open_res->total_samples.value() / open_res->num_channels /
+ open_res->sample_rate_hz;
+ }
+
+ events::Audio().Dispatch(internal::DecoderOpened{
+ .track = std::make_shared<TrackInfo>(TrackInfo{
+ .tags = stream->tags(),
+ .uri = stream->Filepath(),
+ .duration = duration,
+ .start_offset = stream->Offset(),
+ .bitrate_kbps = open_res->sample_rate_hz,
+ .encoding = stream->type(),
+ }),
+ });
return true;
}
@@ -167,6 +135,7 @@ auto Decoder::BeginDecoding(std::shared_ptr<TaggedStream> stream) -> bool {
auto Decoder::ContinueDecoding() -> bool {
auto res = codec_->DecodeTo(codec_buffer_);
if (res.has_error()) {
+ events::Audio().Dispatch(internal::DecoderError{});
return true;
}
@@ -176,11 +145,8 @@ auto Decoder::ContinueDecoding() -> bool {
res->is_stream_finished);
}
- if (timer_) {
- timer_->AddSamples(res->samples_written);
- }
-
if (res->is_stream_finished) {
+ events::Audio().Dispatch(internal::DecoderClosed{});
codec_.reset();
}