From 175bfc4e3e9f7aa39e084d3f1625347f1d5711ec Mon Sep 17 00:00:00 2001 From: jacqueline Date: Mon, 25 Mar 2024 17:34:41 +1100 Subject: WIP rewrie audio pipeline+fsm guts for more reliability --- src/audio/audio_decoder.cpp | 78 +++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 56 deletions(-) (limited to 'src/audio/audio_decoder.cpp') 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 #include #include @@ -50,39 +51,6 @@ namespace audio { static constexpr std::size_t kCodecBufferLength = drivers::kI2SBufferLengthFrames * sizeof(sample::Sample); -Timer::Timer(std::shared_ptr 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 source, std::shared_ptr sink) -> Decoder* { Decoder* task = new Decoder(source, sink); @@ -92,11 +60,7 @@ auto Decoder::Start(std::shared_ptr source, Decoder::Decoder(std::shared_ptr source, std::shared_ptr 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(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 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 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 stream) -> bool { }; ESP_LOGI(kTag, "stream started ok"); - events::Audio().Dispatch(internal::InputFileOpened{}); - - auto tags = std::make_shared(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 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{ + .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 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(); } -- cgit v1.2.3 From 078b77d0f796be3c787f62b9b830512e38d3b076 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Tue, 26 Mar 2024 12:12:42 +1100 Subject: pass stream start/update/end events through the whole pipeline --- src/audio/audio_decoder.cpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) (limited to 'src/audio/audio_decoder.cpp') diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp index 55ebc0ec..90c69c16 100644 --- a/src/audio/audio_decoder.cpp +++ b/src/audio/audio_decoder.cpp @@ -72,7 +72,6 @@ void Decoder::Main() { for (;;) { if (source_->HasNewStream() || !stream_) { std::shared_ptr new_stream = source_->NextStream(); - ESP_LOGI(kTag, "decoder has new stream"); if (new_stream && BeginDecoding(new_stream)) { stream_ = new_stream; } else { @@ -91,8 +90,7 @@ auto Decoder::BeginDecoding(std::shared_ptr stream) -> bool { codec_.reset(); codec_.reset(codecs::CreateCodecForType(stream->type()).value_or(nullptr)); if (!codec_) { - ESP_LOGE(kTag, "no codec found"); - events::Audio().Dispatch(internal::DecoderError{}); + ESP_LOGE(kTag, "no codec found for stream"); return false; } @@ -100,7 +98,6 @@ auto Decoder::BeginDecoding(std::shared_ptr 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(); @@ -110,24 +107,21 @@ auto Decoder::BeginDecoding(std::shared_ptr stream) -> bool { .bits_per_sample = 16, }; - ESP_LOGI(kTag, "stream started ok"); - std::optional 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{ - .tags = stream->tags(), - .uri = stream->Filepath(), - .duration = duration, - .start_offset = stream->Offset(), - .bitrate_kbps = open_res->sample_rate_hz, - .encoding = stream->type(), - }), - }); + converter_->beginStream(std::make_shared(TrackInfo{ + .tags = stream->tags(), + .uri = stream->Filepath(), + .duration = duration, + .start_offset = stream->Offset(), + .bitrate_kbps = open_res->sample_rate_hz, + .encoding = stream->type(), + .format = *current_sink_format_, + })); return true; } @@ -135,18 +129,16 @@ auto Decoder::BeginDecoding(std::shared_ptr stream) -> bool { auto Decoder::ContinueDecoding() -> bool { auto res = codec_->DecodeTo(codec_buffer_); if (res.has_error()) { - events::Audio().Dispatch(internal::DecoderError{}); + converter_->endStream(); return true; } if (res->samples_written > 0) { - converter_->ConvertSamples(codec_buffer_.first(res->samples_written), - current_sink_format_.value(), - res->is_stream_finished); + converter_->continueStream(codec_buffer_.first(res->samples_written)); } if (res->is_stream_finished) { - events::Audio().Dispatch(internal::DecoderClosed{}); + converter_->endStream(); codec_.reset(); } -- cgit v1.2.3