From f3c5eec0251ec98f90d324c88d3519de2e6ee5e0 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Wed, 16 Aug 2023 15:11:30 +1000 Subject: Rename the main audio tasks to be more sensible --- src/audio/include/audio_converter.hpp | 65 +++++++++++++++++++++++++++++++ src/audio/include/audio_decoder.hpp | 73 +++++++++++++++++++++++++++++++++++ src/audio/include/audio_fsm.hpp | 6 +-- src/audio/include/audio_task.hpp | 65 ------------------------------- src/audio/include/sink_mixer.hpp | 63 ------------------------------ 5 files changed, 141 insertions(+), 131 deletions(-) create mode 100644 src/audio/include/audio_converter.hpp create mode 100644 src/audio/include/audio_decoder.hpp delete mode 100644 src/audio/include/audio_task.hpp delete mode 100644 src/audio/include/sink_mixer.hpp (limited to 'src/audio/include') diff --git a/src/audio/include/audio_converter.hpp b/src/audio/include/audio_converter.hpp new file mode 100644 index 00000000..81532969 --- /dev/null +++ b/src/audio/include/audio_converter.hpp @@ -0,0 +1,65 @@ +/* + * Copyright 2023 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include +#include + +#include "audio_sink.hpp" +#include "audio_source.hpp" +#include "codec.hpp" +#include "resample.hpp" +#include "sample.hpp" + +namespace audio { + +/* + * 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 SampleConverter { + public: + SampleConverter(); + ~SampleConverter(); + + auto SetOutput(std::shared_ptr) -> void; + + auto ConvertSamples(cpp::span, + const IAudioOutput::Format& format, + bool is_eos) -> void; + + private: + auto Main() -> void; + + auto SetTargetFormat(const IAudioOutput::Format& format) -> void; + auto HandleSamples(cpp::span, bool) -> size_t; + + struct Args { + IAudioOutput::Format format; + size_t samples_available; + bool is_end_of_stream; + }; + QueueHandle_t commands_; + + std::unique_ptr resampler_; + + StreamBufferHandle_t source_; + cpp::span input_buffer_; + cpp::span input_buffer_as_bytes_; + + cpp::span resampled_buffer_; + + std::shared_ptr sink_; + IAudioOutput::Format source_format_; + IAudioOutput::Format target_format_; + size_t leftover_bytes_; + size_t leftover_offset_; +}; + +} // namespace audio diff --git a/src/audio/include/audio_decoder.hpp b/src/audio/include/audio_decoder.hpp new file mode 100644 index 00000000..1759f6e4 --- /dev/null +++ b/src/audio/include/audio_decoder.hpp @@ -0,0 +1,73 @@ +/* + * Copyright 2023 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include +#include + +#include "audio_converter.hpp" +#include "audio_sink.hpp" +#include "audio_source.hpp" +#include "codec.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); + + auto AddSamples(std::size_t) -> void; + + private: + uint32_t current_seconds_; + uint32_t current_sample_in_second_; + uint32_t samples_per_second_; + + uint32_t total_duration_seconds_; +}; + +/* + * 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 source, + std::shared_ptr converter) -> Decoder*; + + auto Main() -> void; + + Decoder(const Decoder&) = delete; + Decoder& operator=(const Decoder&) = delete; + + private: + Decoder(std::shared_ptr source, + std::shared_ptr converter); + + auto BeginDecoding(std::shared_ptr) -> bool; + auto ContinueDecoding() -> bool; + + std::shared_ptr source_; + std::shared_ptr converter_; + + std::shared_ptr stream_; + std::unique_ptr codec_; + std::unique_ptr timer_; + + std::optional current_format_; + std::optional current_sink_format_; + + cpp::span codec_buffer_; +}; + +} // namespace audio 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 { static std::shared_ptr sDac; static std::weak_ptr sDatabase; - static std::unique_ptr sTask; static std::shared_ptr sFileSource; - static std::shared_ptr sMixer; + static std::unique_ptr sDecoder; + static std::shared_ptr sSampleConverter; static std::shared_ptr sOutput; static TrackQueue* sTrackQueue; diff --git a/src/audio/include/audio_task.hpp b/src/audio/include/audio_task.hpp deleted file mode 100644 index 08c5769c..00000000 --- a/src/audio/include/audio_task.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include - -#include "audio_sink.hpp" -#include "audio_source.hpp" -#include "codec.hpp" -#include "sink_mixer.hpp" -#include "track.hpp" -#include "types.hpp" - -namespace audio { - -class Timer { - public: - Timer(const codecs::ICodec::OutputFormat& format); - - auto AddSamples(std::size_t) -> void; - - private: - uint32_t current_seconds_; - uint32_t current_sample_in_second_; - uint32_t samples_per_second_; - - uint32_t total_duration_seconds_; -}; - -class AudioTask { - public: - static auto Start(std::shared_ptr source, - std::shared_ptr mixer) -> AudioTask*; - - auto Main() -> void; - - AudioTask(const AudioTask&) = delete; - AudioTask& operator=(const AudioTask&) = delete; - - private: - AudioTask(std::shared_ptr source, - std::shared_ptr mixer); - - auto BeginDecoding(std::shared_ptr) -> bool; - auto ContinueDecoding() -> bool; - - std::shared_ptr source_; - std::shared_ptr mixer_; - - std::shared_ptr stream_; - std::unique_ptr codec_; - std::unique_ptr timer_; - - std::optional current_format_; - std::optional current_sink_format_; - - cpp::span codec_buffer_; -}; - -} // namespace audio diff --git a/src/audio/include/sink_mixer.hpp b/src/audio/include/sink_mixer.hpp deleted file mode 100644 index d046f835..00000000 --- a/src/audio/include/sink_mixer.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include - -#include "audio_sink.hpp" -#include "audio_source.hpp" -#include "codec.hpp" -#include "resample.hpp" -#include "sample.hpp" - -namespace audio { - -/* - * Handles the final downmix + resample + quantisation stage of audio, - * generation sending the result directly to an IAudioOutput. - */ -class SinkMixer { - public: - SinkMixer(); - ~SinkMixer(); - - auto SetOutput(std::shared_ptr) -> void; - - auto MixAndSend(cpp::span, - const IAudioOutput::Format& format, - bool is_eos) -> void; - - private: - auto Main() -> void; - - auto SetTargetFormat(const IAudioOutput::Format& format) -> void; - auto HandleSamples(cpp::span, bool) -> size_t; - - struct Args { - IAudioOutput::Format format; - size_t samples_available; - bool is_end_of_stream; - }; - QueueHandle_t commands_; - - std::unique_ptr resampler_; - - StreamBufferHandle_t source_; - cpp::span input_buffer_; - cpp::span input_buffer_as_bytes_; - - cpp::span resampled_buffer_; - - std::shared_ptr sink_; - IAudioOutput::Format source_format_; - IAudioOutput::Format target_format_; - size_t leftover_bytes_; - size_t leftover_offset_; -}; - -} // namespace audio -- cgit v1.2.3