diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-08-16 15:11:30 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-08-16 15:11:44 +1000 |
| commit | f3c5eec0251ec98f90d324c88d3519de2e6ee5e0 (patch) | |
| tree | 90cd471dd980c77440e1b901dd5c6c91492d27d6 | |
| parent | c635d5011c37c02246135fe0df404631ec111bd6 (diff) | |
| download | tangara-fw-f3c5eec0251ec98f90d324c88d3519de2e6ee5e0.tar.gz | |
Rename the main audio tasks to be more sensible
| -rw-r--r-- | src/audio/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/audio/audio_converter.cpp (renamed from src/audio/sink_mixer.cpp) | 20 | ||||
| -rw-r--r-- | src/audio/audio_decoder.cpp (renamed from src/audio/audio_task.cpp) | 31 | ||||
| -rw-r--r-- | src/audio/audio_fsm.cpp | 15 | ||||
| -rw-r--r-- | src/audio/include/audio_converter.hpp (renamed from src/audio/include/sink_mixer.hpp) | 18 | ||||
| -rw-r--r-- | src/audio/include/audio_decoder.hpp (renamed from src/audio/include/audio_task.hpp) | 24 | ||||
| -rw-r--r-- | src/audio/include/audio_fsm.hpp | 6 |
7 files changed, 66 insertions, 52 deletions
diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index de6c9b64..df5622f5 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -3,8 +3,8 @@ # SPDX-License-Identifier: GPL-3.0-only idf_component_register( - SRCS "audio_task.cpp" "fatfs_audio_input.cpp" "i2s_audio_output.cpp" - "track_queue.cpp" "audio_fsm.cpp" "sink_mixer.cpp" "resample.cpp" + SRCS "audio_decoder.cpp" "fatfs_audio_input.cpp" "i2s_audio_output.cpp" + "track_queue.cpp" "audio_fsm.cpp" "audio_converter.cpp" "resample.cpp" "fatfs_source.cpp" "bt_audio_output.cpp" INCLUDE_DIRS "include" REQUIRES "codecs" "drivers" "cbor" "result" "tasks" "span" "memory" "tinyfsm" diff --git a/src/audio/sink_mixer.cpp b/src/audio/audio_converter.cpp index ad7198dc..c540d821 100644 --- a/src/audio/sink_mixer.cpp +++ b/src/audio/audio_converter.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-only */ -#include "sink_mixer.hpp" +#include "audio_converter.hpp" #include <algorithm> #include <cmath> @@ -28,7 +28,7 @@ static constexpr std::size_t kSampleBufferLength = 240 * 2; namespace audio { -SinkMixer::SinkMixer() +SampleConverter::SampleConverter() : commands_(xQueueCreate(1, sizeof(Args))), resampler_(nullptr), source_(xStreamBufferCreateWithCaps(kSourceBufferLength, @@ -49,21 +49,21 @@ SinkMixer::SinkMixer() tasks::StartPersistent<tasks::Type::kMixer>([&]() { Main(); }); } -SinkMixer::~SinkMixer() { +SampleConverter::~SampleConverter() { vQueueDelete(commands_); vStreamBufferDelete(source_); } -auto SinkMixer::SetOutput(std::shared_ptr<IAudioOutput> output) -> void { +auto SampleConverter::SetOutput(std::shared_ptr<IAudioOutput> output) -> void { // FIXME: We should add synchronisation here, but we should be careful about // not impacting performance given that the output will change only very // rarely (if ever). sink_ = output; } -auto SinkMixer::MixAndSend(cpp::span<sample::Sample> input, - const IAudioOutput::Format& format, - bool is_eos) -> void { +auto SampleConverter::ConvertSamples(cpp::span<sample::Sample> input, + const IAudioOutput::Format& format, + bool is_eos) -> void { Args args{ .format = format, .samples_available = input.size(), @@ -81,7 +81,7 @@ auto SinkMixer::MixAndSend(cpp::span<sample::Sample> input, } } -auto SinkMixer::Main() -> void { +auto SampleConverter::Main() -> void { for (;;) { Args args; while (!xQueueReceive(commands_, &args, portMAX_DELAY)) { @@ -149,8 +149,8 @@ auto SinkMixer::Main() -> void { } } -auto SinkMixer::HandleSamples(cpp::span<sample::Sample> input, bool is_eos) - -> size_t { +auto SampleConverter::HandleSamples(cpp::span<sample::Sample> input, + bool is_eos) -> size_t { if (source_format_ == target_format_) { // The happiest possible case: the input format matches the output // format already. diff --git a/src/audio/audio_task.cpp b/src/audio/audio_decoder.cpp index 99b1c170..03f81124 100644 --- a/src/audio/audio_task.cpp +++ b/src/audio/audio_decoder.cpp @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-only */ -#include "audio_task.hpp" +#include "audio_decoder.hpp" #include <cstdint> #include <cstdlib> @@ -28,6 +28,7 @@ #include "freertos/ringbuf.h" #include "span.hpp" +#include "audio_converter.hpp" #include "audio_events.hpp" #include "audio_fsm.hpp" #include "audio_sink.hpp" @@ -36,7 +37,6 @@ #include "event_queue.hpp" #include "fatfs_audio_input.hpp" #include "sample.hpp" -#include "sink_mixer.hpp" #include "tasks.hpp" #include "track.hpp" #include "types.hpp" @@ -76,23 +76,27 @@ auto Timer::AddSamples(std::size_t samples) -> void { } } -auto AudioTask::Start(std::shared_ptr<IAudioSource> source, - std::shared_ptr<SinkMixer> sink) -> AudioTask* { - AudioTask* task = new AudioTask(source, sink); +auto Decoder::Start(std::shared_ptr<IAudioSource> source, + std::shared_ptr<SampleConverter> sink) -> Decoder* { + Decoder* task = new Decoder(source, sink); tasks::StartPersistent<tasks::Type::kAudio>([=]() { task->Main(); }); return task; } -AudioTask::AudioTask(std::shared_ptr<IAudioSource> source, - std::shared_ptr<SinkMixer> mixer) - : source_(source), mixer_(mixer), codec_(), timer_(), current_format_() { +Decoder::Decoder(std::shared_ptr<IAudioSource> source, + std::shared_ptr<SampleConverter> mixer) + : source_(source), + converter_(mixer), + codec_(), + timer_(), + current_format_() { codec_buffer_ = { reinterpret_cast<sample::Sample*>(heap_caps_calloc( kCodecBufferLength, sizeof(sample::Sample), MALLOC_CAP_SPIRAM)), kCodecBufferLength}; } -void AudioTask::Main() { +void Decoder::Main() { for (;;) { if (source_->HasNewStream() || !stream_) { std::shared_ptr<codecs::IStream> new_stream = source_->NextStream(); @@ -110,7 +114,7 @@ void AudioTask::Main() { } } -auto AudioTask::BeginDecoding(std::shared_ptr<codecs::IStream> stream) -> bool { +auto Decoder::BeginDecoding(std::shared_ptr<codecs::IStream> stream) -> bool { codec_.reset(codecs::CreateCodecForType(stream->type()).value_or(nullptr)); if (!codec_) { ESP_LOGE(kTag, "no codec found"); @@ -140,15 +144,16 @@ auto AudioTask::BeginDecoding(std::shared_ptr<codecs::IStream> stream) -> bool { return true; } -auto AudioTask::ContinueDecoding() -> bool { +auto Decoder::ContinueDecoding() -> bool { auto res = codec_->DecodeTo(codec_buffer_); if (res.has_error()) { return true; } if (res->samples_written > 0) { - mixer_->MixAndSend(codec_buffer_.first(res->samples_written), - current_sink_format_.value(), res->is_stream_finished); + converter_->ConvertSamples(codec_buffer_.first(res->samples_written), + current_sink_format_.value(), + res->is_stream_finished); } if (timer_) { diff --git a/src/audio/audio_fsm.cpp b/src/audio/audio_fsm.cpp index 1ea670af..e68eedaf 100644 --- a/src/audio/audio_fsm.cpp +++ b/src/audio/audio_fsm.cpp @@ -15,8 +15,9 @@ #include "freertos/portmacro.h" #include "freertos/projdefs.h" +#include "audio_converter.hpp" +#include "audio_decoder.hpp" #include "audio_events.hpp" -#include "audio_task.hpp" #include "bluetooth.hpp" #include "bt_audio_output.hpp" #include "event_queue.hpp" @@ -24,7 +25,6 @@ #include "future_fetcher.hpp" #include "i2s_audio_output.hpp" #include "i2s_dac.hpp" -#include "sink_mixer.hpp" #include "system_events.hpp" #include "track.hpp" #include "track_queue.hpp" @@ -37,10 +37,9 @@ drivers::IGpios* AudioState::sIGpios; std::shared_ptr<drivers::I2SDac> AudioState::sDac; std::weak_ptr<database::Database> AudioState::sDatabase; -std::unique_ptr<AudioTask> AudioState::sTask; - std::shared_ptr<FatfsAudioInput> AudioState::sFileSource; -std::shared_ptr<SinkMixer> AudioState::sMixer; +std::unique_ptr<Decoder> AudioState::sDecoder; +std::shared_ptr<SampleConverter> AudioState::sSampleConverter; std::shared_ptr<IAudioOutput> AudioState::sOutput; TrackQueue* AudioState::sTrackQueue; @@ -65,10 +64,10 @@ auto AudioState::Init(drivers::IGpios* gpio_expander, sOutput.reset(new I2SAudioOutput(sIGpios, sDac)); // sOutput.reset(new BluetoothAudioOutput(bluetooth)); - sMixer.reset(new SinkMixer()); - sMixer->SetOutput(sOutput); + sSampleConverter.reset(new SampleConverter()); + sSampleConverter->SetOutput(sOutput); - AudioTask::Start(sFileSource, sMixer); + Decoder::Start(sFileSource, sSampleConverter); return true; } diff --git a/src/audio/include/sink_mixer.hpp b/src/audio/include/audio_converter.hpp index d046f835..81532969 100644 --- a/src/audio/include/sink_mixer.hpp +++ b/src/audio/include/audio_converter.hpp @@ -18,19 +18,21 @@ namespace audio { /* - * Handles the final downmix + resample + quantisation stage of audio, - * generation sending the result directly to an IAudioOutput. + * Handle to a persistent task that converts samples between formats (sample + * rate, channels, bits per sample), in order to put samples in the preferred + * format of the current output device. The resulting samples are forwarded + * to the output device's sink stream. */ -class SinkMixer { +class SampleConverter { public: - SinkMixer(); - ~SinkMixer(); + SampleConverter(); + ~SampleConverter(); auto SetOutput(std::shared_ptr<IAudioOutput>) -> void; - auto MixAndSend(cpp::span<sample::Sample>, - const IAudioOutput::Format& format, - bool is_eos) -> void; + auto ConvertSamples(cpp::span<sample::Sample>, + const IAudioOutput::Format& format, + bool is_eos) -> void; private: auto Main() -> void; diff --git a/src/audio/include/audio_task.hpp b/src/audio/include/audio_decoder.hpp index 08c5769c..1759f6e4 100644 --- a/src/audio/include/audio_task.hpp +++ b/src/audio/include/audio_decoder.hpp @@ -9,15 +9,18 @@ #include <cstdint> #include <memory> +#include "audio_converter.hpp" #include "audio_sink.hpp" #include "audio_source.hpp" #include "codec.hpp" -#include "sink_mixer.hpp" #include "track.hpp" #include "types.hpp" namespace audio { +/* + * Sample-based timer for the current elapsed playback time. + */ class Timer { public: Timer(const codecs::ICodec::OutputFormat& format); @@ -32,25 +35,30 @@ class Timer { uint32_t total_duration_seconds_; }; -class AudioTask { +/* + * Handle to a persistent task that takes bytes from the given source, decodes + * them into sample::Sample (normalised to 16 bit signed PCM), and then + * forwards the resulting stream to the given converter. + */ +class Decoder { public: static auto Start(std::shared_ptr<IAudioSource> source, - std::shared_ptr<SinkMixer> mixer) -> AudioTask*; + std::shared_ptr<SampleConverter> converter) -> Decoder*; auto Main() -> void; - AudioTask(const AudioTask&) = delete; - AudioTask& operator=(const AudioTask&) = delete; + Decoder(const Decoder&) = delete; + Decoder& operator=(const Decoder&) = delete; private: - AudioTask(std::shared_ptr<IAudioSource> source, - std::shared_ptr<SinkMixer> mixer); + Decoder(std::shared_ptr<IAudioSource> source, + std::shared_ptr<SampleConverter> converter); auto BeginDecoding(std::shared_ptr<codecs::IStream>) -> bool; auto ContinueDecoding() -> bool; std::shared_ptr<IAudioSource> source_; - std::shared_ptr<SinkMixer> mixer_; + std::shared_ptr<SampleConverter> converter_; std::shared_ptr<codecs::IStream> stream_; std::unique_ptr<codecs::ICodec> codec_; diff --git a/src/audio/include/audio_fsm.hpp b/src/audio/include/audio_fsm.hpp index 6c785426..430bc298 100644 --- a/src/audio/include/audio_fsm.hpp +++ b/src/audio/include/audio_fsm.hpp @@ -13,8 +13,8 @@ #include "audio_sink.hpp" #include "tinyfsm.hpp" +#include "audio_decoder.hpp" #include "audio_events.hpp" -#include "audio_task.hpp" #include "bt_audio_output.hpp" #include "database.hpp" #include "display.hpp" @@ -68,9 +68,9 @@ class AudioState : public tinyfsm::Fsm<AudioState> { static std::shared_ptr<drivers::I2SDac> sDac; static std::weak_ptr<database::Database> sDatabase; - static std::unique_ptr<AudioTask> sTask; static std::shared_ptr<FatfsAudioInput> sFileSource; - static std::shared_ptr<SinkMixer> sMixer; + static std::unique_ptr<Decoder> sDecoder; + static std::shared_ptr<SampleConverter> sSampleConverter; static std::shared_ptr<IAudioOutput> sOutput; static TrackQueue* sTrackQueue; |
