diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index a7dda8fd..de6c9b64 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -3,9 +3,8 @@ # SPDX-License-Identifier: GPL-3.0-only idf_component_register( - SRCS "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp" - "stream_message.cpp" "i2s_audio_output.cpp" "stream_buffer.cpp" "track_queue.cpp" - "stream_event.cpp" "stream_info.cpp" "audio_fsm.cpp" "sink_mixer.cpp" "resample.cpp" + SRCS "audio_task.cpp" "fatfs_audio_input.cpp" "i2s_audio_output.cpp" + "track_queue.cpp" "audio_fsm.cpp" "sink_mixer.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/audio_decoder.cpp b/src/audio/audio_decoder.cpp deleted file mode 100644 index b8054574..00000000 --- a/src/audio/audio_decoder.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "audio_decoder.hpp" - -#include - -#include -#include -#include -#include -#include - -#include "codec.hpp" -#include "freertos/FreeRTOS.h" - -#include "esp_heap_caps.h" -#include "esp_log.h" -#include "freertos/message_buffer.h" -#include "freertos/portmacro.h" - -#include "audio_element.hpp" -#include "chunk.hpp" -#include "fatfs_audio_input.hpp" -#include "stream_info.hpp" - -namespace audio { - -static const char* kTag = "DEC"; - -AudioDecoder::AudioDecoder() - : IAudioElement(), - current_codec_(), - current_input_format_(), - current_output_format_(), - has_prepared_output_(false), - has_samples_to_send_(false), - has_input_remaining_(false) {} - -AudioDecoder::~AudioDecoder() {} - -auto AudioDecoder::ProcessStreamInfo(const StreamInfo& info) -> bool { - has_prepared_output_ = false; - current_codec_.reset(); - current_input_format_.reset(); - current_output_format_.reset(); - - if (!std::holds_alternative(info.format)) { - return false; - } - - const auto& new_format = std::get(info.format); - current_input_format_ = new_format; - - ESP_LOGI(kTag, "creating new decoder"); - auto result = codecs::CreateCodecForType(new_format.type); - if (result.has_value()) { - current_codec_.reset(result.value()); - } else { - ESP_LOGE(kTag, "no codec for this file"); - return false; - } - - return true; -} - -auto AudioDecoder::NeedsToProcess() const -> bool { - return has_samples_to_send_ || has_input_remaining_; -} - -auto AudioDecoder::Process(const std::vector& inputs, - OutputStream* output) -> void { - auto input = inputs.begin(); - const StreamInfo& info = input->info(); - - // Is this a completely new stream? - if (!current_input_format_) { - if (!ProcessStreamInfo(info)) { - // We couldn't handle the new stream. Signal to the producer that we don't - // have anything to do. - input->mark_consumer_finished(); - return; - } - } - - // Have we determined what kind of samples this stream decodes to? - if (!current_output_format_) { - auto res = current_codec_->BeginStream(input->data()); - input->consume(res.first); - - if (res.second.has_error()) { - auto err = res.second.error(); - if (err == codecs::ICodec::Error::kOutOfInput) { - // We didn't manage to clear whatever front matter is before this - // stream's header. We need to call BeginStream again with more data. - return; - } - // Somthing about the stream's header was malformed. Skip it. - ESP_LOGE(kTag, "error beginning stream"); - input->mark_consumer_finished(); - return; - } - - // The stream started successfully. Record what format the samples are in. - codecs::ICodec::OutputFormat format = res.second.value(); - current_output_format_ = StreamInfo::Pcm{ - .channels = format.num_channels, - .bits_per_sample = format.bits_per_sample, - .sample_rate = format.sample_rate_hz, - }; - - if (format.duration_seconds) { - duration_seconds_from_decoder_ = format.duration_seconds; - } else if (format.bits_per_second && - current_input_format_->duration_bytes) { - duration_seconds_from_decoder_ = - (current_input_format_->duration_bytes.value() - res.first) * 8 / - format.bits_per_second.value() / format.num_channels; - } - - if (info.seek_to_seconds) { - seek_to_sample_ = *info.seek_to_seconds * format.sample_rate_hz; - } else { - seek_to_sample_.reset(); - } - } - - if (seek_to_sample_) { - ESP_LOGI(kTag, "seeking forwards..."); - auto res = current_codec_->SeekStream(input->data(), *seek_to_sample_); - input->consume(res.first); - - if (res.second.has_error()) { - auto err = res.second.error(); - if (err == codecs::ICodec::Error::kOutOfInput) { - return; - } else { - // TODO(jacqueline): Handle errors. - } - } - - seek_to_sample_.reset(); - } - - has_input_remaining_ = true; - while (true) { - // Make sure the output buffer is ready to receive samples in our format - // before starting to process data. - // TODO(jacqueline): Pass through seek info here? - if (!has_prepared_output_ && !output->prepare(*current_output_format_)) { - return; - } - if (duration_seconds_from_decoder_) { - output->set_duration(*duration_seconds_from_decoder_); - } - has_prepared_output_ = true; - - // Parse frames and produce samples. - auto res = current_codec_->ContinueStream(input->data(), output->data()); - input->consume(res.first); - - // Handle any errors during processing. - if (res.second.has_error()) { - // The codec ran out of input during processing. This is expected to - // happen throughout the stream. - if (res.second.error() == codecs::ICodec::Error::kOutOfInput) { - has_input_remaining_ = false; - has_samples_to_send_ = false; - if (input->is_producer_finished()) { - // We're out of data, and so is the producer. Nothing left to be done - // with the input stream. - input->mark_consumer_finished(); - - // Upstream isn't going to give us any more data. Tell downstream - // that they shouldn't expact any more samples from this stream. - output->mark_producer_finished(); - break; - } - } else { - // TODO(jacqueline): Handle errors. - ESP_LOGE(kTag, "codec returned fatal error"); - } - // Note that a codec that returns an error is not allowed to write - // samples. So it's safe to skip the latter part of the loop. - return; - } else { - // Some samples were written! Ensure the downstream element knows about - // them. - codecs::ICodec::OutputInfo out_info = res.second.value(); - output->add(out_info.bytes_written); - has_samples_to_send_ = !out_info.is_finished_writing; - - if (has_samples_to_send_) { - // The codec wasn't able to finish writing all of its samples into the - // output buffer. We need to return so that we can get a new buffer. - return; - } - } - } - - current_codec_.reset(); - current_input_format_.reset(); -} - -} // namespace audio diff --git a/src/audio/audio_fsm.cpp b/src/audio/audio_fsm.cpp index 9558d778..87fbbda2 100644 --- a/src/audio/audio_fsm.cpp +++ b/src/audio/audio_fsm.cpp @@ -5,23 +5,24 @@ */ #include "audio_fsm.hpp" + #include #include #include -#include "audio_decoder.hpp" + +#include "esp_log.h" +#include "freertos/portmacro.h" +#include "freertos/projdefs.h" + #include "audio_events.hpp" #include "audio_task.hpp" #include "bluetooth.hpp" #include "bt_audio_output.hpp" -#include "esp_log.h" #include "event_queue.hpp" #include "fatfs_audio_input.hpp" -#include "freertos/portmacro.h" -#include "freertos/projdefs.h" #include "future_fetcher.hpp" #include "i2s_audio_output.hpp" #include "i2s_dac.hpp" -#include "pipeline.hpp" #include "system_events.hpp" #include "track.hpp" #include "track_queue.hpp" diff --git a/src/audio/audio_task.cpp b/src/audio/audio_task.cpp index d1432007..1ebd4e46 100644 --- a/src/audio/audio_task.cpp +++ b/src/audio/audio_task.cpp @@ -6,8 +6,8 @@ #include "audio_task.hpp" -#include -#include +#include +#include #include #include @@ -28,13 +28,10 @@ #include "freertos/ringbuf.h" #include "span.hpp" -#include "audio_decoder.hpp" -#include "audio_element.hpp" #include "audio_events.hpp" #include "audio_fsm.hpp" #include "audio_sink.hpp" #include "audio_source.hpp" -#include "chunk.hpp" #include "codec.hpp" #include "event_queue.hpp" #include "fatfs_audio_input.hpp" diff --git a/src/audio/bt_audio_output.cpp b/src/audio/bt_audio_output.cpp index 71e40d02..641bea21 100644 --- a/src/audio/bt_audio_output.cpp +++ b/src/audio/bt_audio_output.cpp @@ -5,8 +5,6 @@ */ #include "bt_audio_output.hpp" -#include -#include #include #include @@ -17,14 +15,12 @@ #include "esp_err.h" #include "esp_heap_caps.h" #include "freertos/portmacro.h" - -#include "audio_element.hpp" #include "freertos/projdefs.h" + #include "gpios.hpp" #include "i2c.hpp" #include "i2s_dac.hpp" #include "result.hpp" -#include "stream_info.hpp" #include "wm8523.hpp" static const char* kTag = "BTOUT"; diff --git a/src/audio/chunk.cpp b/src/audio/chunk.cpp deleted file mode 100644 index 11503b2b..00000000 --- a/src/audio/chunk.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "chunk.hpp" - -#include -#include -#include -#include -#include - -#include "cbor.h" -#include "esp_log.h" - -#include "stream_buffer.hpp" -#include "stream_message.hpp" - -namespace audio { - -static const std::size_t kWorkingBufferMultiple = 2; - -ChunkReader::ChunkReader(std::size_t chunk_size) - : raw_working_buffer_(static_cast( - heap_caps_malloc(chunk_size * kWorkingBufferMultiple, - MALLOC_CAP_SPIRAM))), - working_buffer_(raw_working_buffer_, - chunk_size * kWorkingBufferMultiple) {} - -ChunkReader::~ChunkReader() { - free(raw_working_buffer_); -} - -auto ChunkReader::HandleNewData(cpp::span data) - -> cpp::span { - assert(leftover_bytes_ + data.size() <= working_buffer_.size()); - // Copy the new data onto the front for anything that was left over from the - // last portion. Note: this could be optimised for the '0 leftover bytes' - // case, which technically shouldn't need a copy. - std::copy(data.begin(), data.end(), - working_buffer_.begin() + leftover_bytes_); - last_data_in_working_buffer_ = - working_buffer_.first(leftover_bytes_ + data.size()); - leftover_bytes_ = 0; - return last_data_in_working_buffer_; -} - -auto ChunkReader::HandleBytesUsed(std::size_t bytes_used) -> void { - HandleBytesLeftOver(last_data_in_working_buffer_.size() - bytes_used); -} -auto ChunkReader::HandleBytesLeftOver(std::size_t bytes_left) -> void { - leftover_bytes_ = bytes_left; - - // Ensure that we don't have more than a chunk of leftever bytes. This is - // bad, because we probably won't have enough data to store the next chunk. - assert(leftover_bytes_ <= working_buffer_.size() / kWorkingBufferMultiple); - - if (leftover_bytes_ > 0) { - auto data_to_keep = last_data_in_working_buffer_.last(leftover_bytes_); - std::copy(data_to_keep.begin(), data_to_keep.end(), - working_buffer_.begin()); - } -} - -auto ChunkReader::GetLeftovers() -> cpp::span { - return working_buffer_.first(leftover_bytes_); -} - -} // namespace audio diff --git a/src/audio/fatfs_audio_input.cpp b/src/audio/fatfs_audio_input.cpp index cae552db..44653624 100644 --- a/src/audio/fatfs_audio_input.cpp +++ b/src/audio/fatfs_audio_input.cpp @@ -6,8 +6,6 @@ #include "fatfs_audio_input.hpp" -#include - #include #include #include @@ -19,22 +17,21 @@ #include #include -#include "codec.hpp" #include "esp_heap_caps.h" #include "esp_log.h" -#include "fatfs_source.hpp" #include "ff.h" +#include "freertos/portmacro.h" +#include "freertos/projdefs.h" +#include "idf_additions.h" +#include "span.hpp" #include "audio_events.hpp" #include "audio_fsm.hpp" #include "audio_source.hpp" +#include "codec.hpp" #include "event_queue.hpp" -#include "freertos/portmacro.h" -#include "freertos/projdefs.h" +#include "fatfs_source.hpp" #include "future_fetcher.hpp" -#include "idf_additions.h" -#include "span.hpp" -#include "stream_info.hpp" #include "tag_parser.hpp" #include "tasks.hpp" #include "types.hpp" diff --git a/src/audio/fatfs_source.cpp b/src/audio/fatfs_source.cpp index 58986648..7fe4adf9 100644 --- a/src/audio/fatfs_source.cpp +++ b/src/audio/fatfs_source.cpp @@ -5,7 +5,6 @@ */ #include "fatfs_source.hpp" -#include #include #include diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp index 8b7d130f..8c779e15 100644 --- a/src/audio/i2s_audio_output.cpp +++ b/src/audio/i2s_audio_output.cpp @@ -5,8 +5,6 @@ */ #include "i2s_audio_output.hpp" -#include -#include #include #include @@ -14,18 +12,16 @@ #include #include -#include "audio_sink.hpp" #include "esp_err.h" #include "esp_heap_caps.h" #include "freertos/portmacro.h" - -#include "audio_element.hpp" #include "freertos/projdefs.h" + +#include "audio_sink.hpp" #include "gpios.hpp" #include "i2c.hpp" #include "i2s_dac.hpp" #include "result.hpp" -#include "stream_info.hpp" #include "wm8523.hpp" static const char* kTag = "I2SOUT"; diff --git a/src/audio/include/audio_backend.hpp b/src/audio/include/audio_backend.hpp deleted file mode 100644 index 86d90d25..00000000 --- a/src/audio/include/audio_backend.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -namespace drivers { - -class IAudioBackend { - public: - virtual ~IAudioBackend() {} - - enum SampleRate {}; - enum BitDepth {}; - - virtual auto Configure(SampleRate sample_rate, BitDepth bit_depth) - -> bool = 0; - virtual auto WritePcmData(uint8_t* data, size_t length) -> bool = 0; - - virtual auto SetVolume(uint8_t percent) -> void = 0; -}; - -} // namespace drivers diff --git a/src/audio/include/audio_decoder.hpp b/src/audio/include/audio_decoder.hpp deleted file mode 100644 index e8da415e..00000000 --- a/src/audio/include/audio_decoder.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include - -#include "chunk.hpp" -#include "ff.h" -#include "span.hpp" - -#include "audio_element.hpp" -#include "codec.hpp" -#include "stream_info.hpp" - -namespace audio { - -/* - * An audio element that accepts various kinds of encoded audio streams as - * input, and converts them to uncompressed PCM output. - */ -class AudioDecoder { - public: - AudioDecoder(); - ~AudioDecoder(); - - auto Process(const InputStream& input, OutputStream* output) -> void; - - AudioDecoder(const AudioDecoder&) = delete; - AudioDecoder& operator=(const AudioDecoder&) = delete; - - private: - std::unique_ptr current_codec_; - std::optional current_input_format_; - std::optional current_output_format_; - std::optional duration_seconds_from_decoder_; - std::optional seek_to_sample_; - bool has_prepared_output_; - bool has_samples_to_send_; - bool has_input_remaining_; - - auto ProcessStreamInfo(const StreamInfo& info) -> bool; -}; - -} // namespace audio diff --git a/src/audio/include/audio_element.hpp b/src/audio/include/audio_element.hpp deleted file mode 100644 index 7e3d9d7d..00000000 --- a/src/audio/include/audio_element.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" - -#include "chunk.hpp" -#include "freertos/message_buffer.h" -#include "freertos/portmacro.h" -#include "result.hpp" -#include "span.hpp" - -#include "stream_buffer.hpp" -#include "stream_event.hpp" -#include "stream_info.hpp" -#include "types.hpp" - -namespace audio { - -static const size_t kEventQueueSize = 8; - -/* - * One indepedentent part of an audio pipeline. Each element has an input and - * output message stream, and is responsible for taking data from the input - * stream, applying some kind of transformation to it, then sending the result - * out via the output stream. All communication with an element should be done - * over these streams, as an element's methods are only safe to call from the - * task that owns it. - * - * Each element implementation will have its input stream automatically parsed - * by its owning task, and its various Process* methods will be invoked - * accordingly. Element implementations are responsible for managing their own - * writes to their output streams. - */ -class IAudioElement { - public: - IAudioElement() {} - virtual ~IAudioElement() {} - - virtual auto NeedsToProcess() const -> bool = 0; - - virtual auto Process(const std::vector& inputs, - OutputStream* output) -> void = 0; -}; - -} // namespace audio diff --git a/src/audio/include/audio_events.hpp b/src/audio/include/audio_events.hpp index 9c945f33..28e29863 100644 --- a/src/audio/include/audio_events.hpp +++ b/src/audio/include/audio_events.hpp @@ -6,7 +6,6 @@ #pragma once -#include #include #include diff --git a/src/audio/include/audio_fsm.hpp b/src/audio/include/audio_fsm.hpp index 5d44fcda..cb307e68 100644 --- a/src/audio/include/audio_fsm.hpp +++ b/src/audio/include/audio_fsm.hpp @@ -10,6 +10,8 @@ #include #include +#include "tinyfsm.hpp" + #include "audio_events.hpp" #include "audio_task.hpp" #include "bt_audio_output.hpp" @@ -20,11 +22,9 @@ #include "i2s_audio_output.hpp" #include "i2s_dac.hpp" #include "storage.hpp" +#include "system_events.hpp" #include "tag_parser.hpp" -#include "tinyfsm.hpp" #include "track.hpp" - -#include "system_events.hpp" #include "track_queue.hpp" namespace audio { diff --git a/src/audio/include/audio_output.hpp b/src/audio/include/audio_output.hpp deleted file mode 100644 index 074f21d4..00000000 --- a/src/audio/include/audio_output.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include - -#include "audio_common.h" -#include "audio_element.h" -#include "audio_element.hpp" - -namespace audio { - -class AudioOutput : IAudioElement { - public: - AudioOutput(); - ~AudioOutput(); - - auto GetAudioElement() -> audio_element_handle_t { return element_; } - - auto SetInputBuffer(StreamBufferHandle_t buffer) -> void; - - virtual auto Configure(audio_element_info_t& info) -> void = 0; - virtual auto SetSoftMute(bool enabled) -> void = 0; - - private: - audio_element_handle_t element_; - uint8_t volume_; -}; - -} // namespace audio diff --git a/src/audio/include/audio_sink.hpp b/src/audio/include/audio_sink.hpp index b5d6ef57..cce14242 100644 --- a/src/audio/include/audio_sink.hpp +++ b/src/audio/include/audio_sink.hpp @@ -8,11 +8,10 @@ #include #include -#include "audio_element.hpp" + #include "esp_heap_caps.h" #include "freertos/FreeRTOS.h" #include "idf_additions.h" -#include "stream_info.hpp" namespace audio { diff --git a/src/audio/include/audio_source.hpp b/src/audio/include/audio_source.hpp index 6c54a882..a0d690a6 100644 --- a/src/audio/include/audio_source.hpp +++ b/src/audio/include/audio_source.hpp @@ -6,19 +6,7 @@ #pragma once -#include - -#include -#include - -#include "freertos/FreeRTOS.h" -#include "freertos/portmacro.h" -#include "freertos/semphr.h" - #include "codec.hpp" -#include "stream_info.hpp" -#include "track.hpp" -#include "types.hpp" namespace audio { diff --git a/src/audio/include/audio_task.hpp b/src/audio/include/audio_task.hpp index cd79b708..d2c25add 100644 --- a/src/audio/include/audio_task.hpp +++ b/src/audio/include/audio_task.hpp @@ -6,12 +6,9 @@ #pragma once -#include - #include #include -#include "audio_decoder.hpp" #include "audio_sink.hpp" #include "audio_source.hpp" #include "codec.hpp" diff --git a/src/audio/include/bt_audio_output.hpp b/src/audio/include/bt_audio_output.hpp index e11a5d44..d762bab6 100644 --- a/src/audio/include/bt_audio_output.hpp +++ b/src/audio/include/bt_audio_output.hpp @@ -6,20 +6,16 @@ #pragma once -#include #include #include #include -#include "audio_element.hpp" -#include "audio_sink.hpp" -#include "bluetooth.hpp" -#include "chunk.hpp" #include "result.hpp" +#include "audio_sink.hpp" +#include "bluetooth.hpp" #include "gpios.hpp" #include "i2s_dac.hpp" -#include "stream_info.hpp" namespace audio { diff --git a/src/audio/include/chunk.hpp b/src/audio/include/chunk.hpp deleted file mode 100644 index f5ba6654..00000000 --- a/src/audio/include/chunk.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include "freertos/FreeRTOS.h" - -#include "cbor.h" -#include "freertos/message_buffer.h" -#include "freertos/portmacro.h" -#include "freertos/queue.h" -#include "result.hpp" -#include "span.hpp" -#include "stream_buffer.hpp" - -namespace audio { - -/** - * Utility for handling an input stream of chunk data, which simplifies needing - * access to blocks of data spanning two chunks. - */ -class ChunkReader { - public: - explicit ChunkReader(std::size_t chunk_size); - ~ChunkReader(); - - auto HandleBytesLeftOver(std::size_t bytes_left) -> void; - auto HandleBytesUsed(std::size_t bytes_used) -> void; - - /* - * Reads chunks of data from the given input stream, and invokes the given - * callback to process each of them in turn. - * - * The callback will be invoked with a byte buffer and its size. The callback - * should process as much data as it can from this buffer, and then return the - * number of bytes it was able to read. Any leftover bytes will be added as a - * prefix to the next chunk. - * - * If this function encounters a message in the stream that is not a chunk, it - * will place the message at the start of the working_buffer and then return. - */ - auto HandleNewData(cpp::span data) -> cpp::span; - - auto GetLeftovers() -> cpp::span; - - ChunkReader(const ChunkReader&) = delete; - ChunkReader& operator=(const ChunkReader&) = delete; - - private: - std::byte* raw_working_buffer_; - cpp::span working_buffer_; - cpp::span last_data_in_working_buffer_; - std::size_t leftover_bytes_ = 0; -}; - -} // namespace audio diff --git a/src/audio/include/fatfs_audio_input.hpp b/src/audio/include/fatfs_audio_input.hpp index df40696a..da44d2ec 100644 --- a/src/audio/include/fatfs_audio_input.hpp +++ b/src/audio/include/fatfs_audio_input.hpp @@ -12,13 +12,12 @@ #include #include -#include "codec.hpp" #include "ff.h" +#include "freertos/portmacro.h" #include "audio_source.hpp" -#include "freertos/portmacro.h" +#include "codec.hpp" #include "future_fetcher.hpp" -#include "stream_info.hpp" #include "tag_parser.hpp" #include "types.hpp" diff --git a/src/audio/fatfs_source.hpp b/src/audio/include/fatfs_source.hpp similarity index 100% rename from src/audio/fatfs_source.hpp rename to src/audio/include/fatfs_source.hpp diff --git a/src/audio/include/fir.h b/src/audio/include/fir.h deleted file mode 100644 index e50c3eff..00000000 --- a/src/audio/include/fir.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * FIR filter coefficients from resample-1.x smallfilter.h - * see Digital Audio Resampling Home Page located at - * http://ccrma.stanford.edu/~jos/resample/ - */ -32767, 32766, 32764, 32760, 32755, 32749, 32741, 32731, 32721, 32708, -32695, 32679, 32663, 32645, 32625, 32604, 32582, 32558, 32533, 32506, -32478, 32448, 32417, 32385, 32351, 32316, 32279, 32241, 32202, 32161, -32119, 32075, 32030, 31984, 31936, 31887, 31836, 31784, 31731, 31676, -31620, 31563, 31504, 31444, 31383, 31320, 31256, 31191, 31124, 31056, -30987, 30916, 30845, 30771, 30697, 30621, 30544, 30466, 30387, 30306, -30224, 30141, 30057, 29971, 29884, 29796, 29707, 29617, 29525, 29433, -29339, 29244, 29148, 29050, 28952, 28852, 28752, 28650, 28547, 28443, -28338, 28232, 28125, 28017, 27908, 27797, 27686, 27574, 27461, 27346, -27231, 27115, 26998, 26879, 26760, 26640, 26519, 26398, 26275, 26151, -26027, 25901, 25775, 25648, 25520, 25391, 25262, 25131, 25000, 24868, -24735, 24602, 24467, 24332, 24197, 24060, 23923, 23785, 23647, 23507, -23368, 23227, 23086, 22944, 22802, 22659, 22515, 22371, 22226, 22081, -21935, 21789, 21642, 21494, 21346, 21198, 21049, 20900, 20750, 20600, -20449, 20298, 20146, 19995, 19842, 19690, 19537, 19383, 19230, 19076, -18922, 18767, 18612, 18457, 18302, 18146, 17990, 17834, 17678, 17521, -17365, 17208, 17051, 16894, 16737, 16579, 16422, 16264, 16106, 15949, -15791, 15633, 15475, 15317, 15159, 15001, 14843, 14685, 14527, 14369, -14212, 14054, 13896, 13739, 13581, 13424, 13266, 13109, 12952, 12795, -12639, 12482, 12326, 12170, 12014, 11858, 11703, 11548, 11393, 11238, -11084, 10929, 10776, 10622, 10469, 10316, 10164, 10011, 9860, 9708, -9557, 9407, 9256, 9106, 8957, 8808, 8659, 8511, 8364, 8216, 8070, -7924, 7778, 7633, 7488, 7344, 7200, 7057, 6914, 6773, 6631, 6490, -6350, 6210, 6071, 5933, 5795, 5658, 5521, 5385, 5250, 5115, 4981, -4848, 4716, 4584, 4452, 4322, 4192, 4063, 3935, 3807, 3680, 3554, -3429, 3304, 3180, 3057, 2935, 2813, 2692, 2572, 2453, 2335, 2217, -2101, 1985, 1870, 1755, 1642, 1529, 1418, 1307, 1197, 1088, 979, 872, -765, 660, 555, 451, 348, 246, 145, 44, -54, -153, -250, -347, -443, --537, -631, -724, -816, -908, -998, -1087, -1175, -1263, -1349, -1435, --1519, -1603, -1685, -1767, -1848, -1928, -2006, -2084, -2161, -2237, --2312, -2386, -2459, -2531, -2603, -2673, -2742, -2810, -2878, -2944, --3009, -3074, -3137, -3200, -3261, -3322, -3381, -3440, -3498, -3554, --3610, -3665, -3719, -3772, -3824, -3875, -3925, -3974, -4022, -4069, --4116, -4161, -4205, -4249, -4291, -4333, -4374, -4413, -4452, -4490, --4527, -4563, -4599, -4633, -4666, -4699, -4730, -4761, -4791, -4820, --4848, -4875, -4901, -4926, -4951, -4974, -4997, -5019, -5040, -5060, --5080, -5098, -5116, -5133, -5149, -5164, -5178, -5192, -5205, -5217, --5228, -5238, -5248, -5257, -5265, -5272, -5278, -5284, -5289, -5293, --5297, -5299, -5301, -5303, -5303, -5303, -5302, -5300, -5298, -5295, --5291, -5287, -5282, -5276, -5270, -5263, -5255, -5246, -5237, -5228, --5217, -5206, -5195, -5183, -5170, -5157, -5143, -5128, -5113, -5097, --5081, -5064, -5047, -5029, -5010, -4991, -4972, -4952, -4931, -4910, --4889, -4867, -4844, -4821, -4797, -4774, -4749, -4724, -4699, -4673, --4647, -4620, -4593, -4566, -4538, -4510, -4481, -4452, -4422, -4393, --4363, -4332, -4301, -4270, -4238, -4206, -4174, -4142, -4109, -4076, --4042, -4009, -3975, -3940, -3906, -3871, -3836, -3801, -3765, -3729, --3693, -3657, -3620, -3584, -3547, -3510, -3472, -3435, -3397, -3360, --3322, -3283, -3245, -3207, -3168, -3129, -3091, -3052, -3013, -2973, --2934, -2895, -2855, -2816, -2776, -2736, -2697, -2657, -2617, -2577, --2537, -2497, -2457, -2417, -2377, -2337, -2297, -2256, -2216, -2176, --2136, -2096, -2056, -2016, -1976, -1936, -1896, -1856, -1817, -1777, --1737, -1698, -1658, -1619, -1579, -1540, -1501, -1462, -1423, -1384, --1345, -1306, -1268, -1230, -1191, -1153, -1115, -1077, -1040, -1002, --965, -927, -890, -854, -817, -780, -744, -708, -672, -636, -600, --565, -530, -494, -460, -425, -391, -356, -322, -289, -255, -222, --189, -156, -123, -91, -59, -27, 4, 35, 66, 97, 127, 158, 188, 218, -247, 277, 306, 334, 363, 391, 419, 447, 474, 501, 528, 554, 581, 606, -632, 657, 683, 707, 732, 756, 780, 803, 827, 850, 872, 895, 917, 939, -960, 981, 1002, 1023, 1043, 1063, 1082, 1102, 1121, 1139, 1158, 1176, -1194, 1211, 1228, 1245, 1262, 1278, 1294, 1309, 1325, 1340, 1354, -1369, 1383, 1397, 1410, 1423, 1436, 1448, 1461, 1473, 1484, 1496, -1507, 1517, 1528, 1538, 1548, 1557, 1566, 1575, 1584, 1592, 1600, -1608, 1616, 1623, 1630, 1636, 1643, 1649, 1654, 1660, 1665, 1670, -1675, 1679, 1683, 1687, 1690, 1694, 1697, 1700, 1702, 1704, 1706, -1708, 1709, 1711, 1712, 1712, 1713, 1713, 1713, 1713, 1712, 1711, -1710, 1709, 1708, 1706, 1704, 1702, 1700, 1697, 1694, 1691, 1688, -1685, 1681, 1677, 1673, 1669, 1664, 1660, 1655, 1650, 1644, 1639, -1633, 1627, 1621, 1615, 1609, 1602, 1596, 1589, 1582, 1575, 1567, -1560, 1552, 1544, 1536, 1528, 1520, 1511, 1503, 1494, 1485, 1476, -1467, 1458, 1448, 1439, 1429, 1419, 1409, 1399, 1389, 1379, 1368, -1358, 1347, 1337, 1326, 1315, 1304, 1293, 1282, 1271, 1260, 1248, -1237, 1225, 1213, 1202, 1190, 1178, 1166, 1154, 1142, 1130, 1118, -1106, 1094, 1081, 1069, 1057, 1044, 1032, 1019, 1007, 994, 981, 969, -956, 943, 931, 918, 905, 892, 879, 867, 854, 841, 828, 815, 802, 790, -777, 764, 751, 738, 725, 713, 700, 687, 674, 662, 649, 636, 623, 611, -598, 585, 573, 560, 548, 535, 523, 510, 498, 486, 473, 461, 449, 437, -425, 413, 401, 389, 377, 365, 353, 341, 330, 318, 307, 295, 284, 272, -261, 250, 239, 228, 217, 206, 195, 184, 173, 163, 152, 141, 131, 121, -110, 100, 90, 80, 70, 60, 51, 41, 31, 22, 12, 3, -5, -14, -23, -32, --41, -50, -59, -67, -76, -84, -93, -101, -109, -117, -125, -133, -140, --148, -156, -163, -170, -178, -185, -192, -199, -206, -212, -219, --226, -232, -239, -245, -251, -257, -263, -269, -275, -280, -286, --291, -297, -302, -307, -312, -317, -322, -327, -332, -336, -341, --345, -349, -354, -358, -362, -366, -369, -373, -377, -380, -384, --387, -390, -394, -397, -400, -402, -405, -408, -411, -413, -416, --418, -420, -422, -424, -426, -428, -430, -432, -433, -435, -436, --438, -439, -440, -442, -443, -444, -445, -445, -446, -447, -447, --448, -448, -449, -449, -449, -449, -449, -449, -449, -449, -449, --449, -449, -448, -448, -447, -447, -446, -445, -444, -443, -443, --442, -441, -440, -438, -437, -436, -435, -433, -432, -430, -429, --427, -426, -424, -422, -420, -419, -417, -415, -413, -411, -409, --407, -405, -403, -400, -398, -396, -393, -391, -389, -386, -384, --381, -379, -376, -374, -371, -368, -366, -363, -360, -357, -355, --352, -349, -346, -343, -340, -337, -334, -331, -328, -325, -322, --319, -316, -313, -310, -307, -304, -301, -298, -294, -291, -288, --285, -282, -278, -275, -272, -269, -265, -262, -259, -256, -252, --249, -246, -243, -239, -236, -233, -230, -226, -223, -220, -217, --213, -210, -207, -204, -200, -197, -194, -191, -187, -184, -181, --178, -175, -172, -168, -165, -162, -159, -156, -153, -150, -147, --143, -140, -137, -134, -131, -128, -125, -122, -120, -117, -114, --111, -108, -105, -102, -99, -97, -94, -91, -88, -86, -83, -80, -78, --75, -72, -70, -67, -65, -62, -59, -57, -55, -52, -50, -47, -45, -43, --40, -38, -36, -33, -31, -29, -27, -25, -22, -20, -18, -16, -14, -12, --10, -8, -6, -4, -2, 0, 0, 2, 4, 6, 8, 9, 11, 13, 14, 16, 17, 19, 21, -22, 24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 40, 41, 42, 43, -44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, -59, 60, 61, 62, 62, 63, 63, 64, 64, 65, 66, 66, 66, 67, 67, 68, 68, -69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, -72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, -72, 71, 71, 71, 71, 71, 70, 70, 70, 70, 69, 69, 69, 69, 68, 68, 68, -67, 67, 67, 66, 66, 66, 65, 65, 64, 64, 64, 63, 63, 62, 62, 62, 61, -61, 60, 60, 59, 59, 58, 58, 58, 57, 57, 56, 56, 55, 55, 54, 54, 53, -53, 52, 52, 51, 51, 50, 50, 49, 48, 48, 47, 47, 46, 46, 45, 45, 44, -44, 43, 43, 42, 42, 41, 41, 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, -35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, -26, 26, 25, 25, 24, 24, 23, 23, 23, 22, 22, 21, 21, 20, 20, 20, 19, -19, 18, 18, 17, 17, 17, 16, 16, 15, 15, 15, 14, 14, 14, 13, 13, 12, -12, 12, 11, 11, 11, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 7, 7, 7, 7, 6, 6, -6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, -1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, --2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, --2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, --2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, --2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, --1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, diff --git a/src/audio/include/i2s_audio_output.hpp b/src/audio/include/i2s_audio_output.hpp index 717e6519..13cb183f 100644 --- a/src/audio/include/i2s_audio_output.hpp +++ b/src/audio/include/i2s_audio_output.hpp @@ -6,19 +6,14 @@ #pragma once -#include #include #include #include -#include "audio_element.hpp" #include "audio_sink.hpp" -#include "chunk.hpp" -#include "result.hpp" - #include "gpios.hpp" #include "i2s_dac.hpp" -#include "stream_info.hpp" +#include "result.hpp" namespace audio { diff --git a/src/audio/include/pipeline.hpp b/src/audio/include/pipeline.hpp deleted file mode 100644 index bb773006..00000000 --- a/src/audio/include/pipeline.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include - -#include "freertos/portmacro.h" - -#include "audio_element.hpp" -#include "stream_info.hpp" - -namespace audio { - -static const std::size_t kPipelineBufferSize = 64 * 1024; - -class Pipeline { - public: - explicit Pipeline(IAudioElement* output); - ~Pipeline(); - auto AddInput(IAudioElement* input) -> Pipeline*; - - auto OutputElement() const -> IAudioElement*; - - auto NumInputs() const -> std::size_t; - - auto InStreams(std::vector*) -> void; - - auto OutStream() -> RawStream; - - auto GetIterationOrder() -> std::vector; - - // Not copyable or movable. - Pipeline(const Pipeline&) = delete; - Pipeline& operator=(const Pipeline&) = delete; - - private: - IAudioElement* root_; - std::vector> subtrees_; - - std::array output_buffer_; - StreamInfo output_info_; -}; - -} // namespace audio diff --git a/src/audio/include/resample.hpp b/src/audio/include/resample.hpp index 7b114f59..a9464cb1 100644 --- a/src/audio/include/resample.hpp +++ b/src/audio/include/resample.hpp @@ -1,6 +1,12 @@ +/* + * Copyright 2023 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + #pragma once -#include +#include #include #include "span.hpp" diff --git a/src/audio/include/sink_mixer.hpp b/src/audio/include/sink_mixer.hpp index 4a7627e8..37143439 100644 --- a/src/audio/include/sink_mixer.hpp +++ b/src/audio/include/sink_mixer.hpp @@ -6,19 +6,15 @@ #pragma once -#include #include #include #include "resample.hpp" #include "sample.hpp" -#include "audio_decoder.hpp" #include "audio_sink.hpp" #include "audio_source.hpp" #include "codec.hpp" -#include "pipeline.hpp" -#include "stream_info.hpp" namespace audio { @@ -38,7 +34,7 @@ class SinkMixer { private: auto Main() -> void; - auto SetTargetFormat(const StreamInfo::Pcm& format) -> void; + auto SetTargetFormat(const IAudioSink::Format& format) -> void; auto HandleSamples(cpp::span, bool) -> size_t; struct Args { diff --git a/src/audio/include/stream_buffer.hpp b/src/audio/include/stream_buffer.hpp deleted file mode 100644 index 06fe8af5..00000000 --- a/src/audio/include/stream_buffer.hpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include - -#include "freertos/FreeRTOS.h" - -#include "freertos/message_buffer.h" -#include "span.hpp" - -namespace audio { - -/* - * A collection of the buffers required for two IAudioElement implementations to - * stream data between each other. - * - * Currently, we use a FreeRTOS MessageBuffer to hold the byte stream, and also - * maintain two chunk-sized buffers for the elements to stage their read and - * write operations (as MessageBuffer copies the given data into its memory - * space). A future optimisation here could be to instead post himem memory - * addresses to the message buffer, and then maintain address spaces into which - * we map these messages, rather than 'real' allocated buffers as we do now. - */ -class StreamBuffer { - public: - explicit StreamBuffer(std::size_t chunk_size, std::size_t buffer_size); - ~StreamBuffer(); - - /* Returns the handle for the underlying message buffer. */ - auto Handle() -> MessageBufferHandle_t* { return &handle_; } - - /* - * Returns a chunk-sized staging buffer that should be used *only* by the - * reader (sink) element. - */ - auto ReadBuffer() -> cpp::span { return input_chunk_; } - - /* - * Returns a chunk-sized staging buffer that should be used *only* by the - * writer (source) element. - */ - auto WriteBuffer() -> cpp::span { return output_chunk_; } - - StreamBuffer(const StreamBuffer&) = delete; - StreamBuffer& operator=(const StreamBuffer&) = delete; - - private: - std::byte* raw_memory_; - StaticMessageBuffer_t metadata_; - MessageBufferHandle_t handle_; - - std::byte* raw_input_chunk_; - cpp::span input_chunk_; - - std::byte* raw_output_chunk_; - cpp::span output_chunk_; -}; - -} // namespace audio diff --git a/src/audio/include/stream_event.hpp b/src/audio/include/stream_event.hpp deleted file mode 100644 index d98d9baa..00000000 --- a/src/audio/include/stream_event.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include - -#include "arena.hpp" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" - -#include "span.hpp" -#include "stream_info.hpp" - -namespace audio { - -struct StreamEvent { - static auto CreateStreamInfo(QueueHandle_t source, const StreamInfo& payload) - -> StreamEvent*; - static auto CreateArenaChunk(QueueHandle_t source, memory::ArenaPtr ptr) - -> StreamEvent*; - static auto CreateChunkNotification(QueueHandle_t source) -> StreamEvent*; - static auto CreateEndOfStream(QueueHandle_t source) -> StreamEvent*; - static auto CreateLogStatus() -> StreamEvent*; - - StreamEvent(); - ~StreamEvent(); - StreamEvent(StreamEvent&&); - - QueueHandle_t source; - - enum { - UNINITIALISED, - STREAM_INFO, - ARENA_CHUNK, - CHUNK_NOTIFICATION, - END_OF_STREAM, - LOG_STATUS, - } tag; - - union { - StreamInfo* stream_info; - - memory::ArenaPtr arena_chunk; - - // FIXME: It would be nice to also support a pointer to himem data here, to - // save a little ordinary heap space. - }; - - StreamEvent(const StreamEvent&) = delete; - StreamEvent& operator=(const StreamEvent&) = delete; -}; - -} // namespace audio diff --git a/src/audio/include/stream_info.hpp b/src/audio/include/stream_info.hpp deleted file mode 100644 index 01dd282a..00000000 --- a/src/audio/include/stream_info.hpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_heap_caps.h" -#include "freertos/FreeRTOS.h" -#include "freertos/ringbuf.h" -#include "freertos/stream_buffer.h" - -#include "result.hpp" -#include "span.hpp" -#include "types.hpp" - -namespace audio { - -class StreamInfo { - public: - StreamInfo() : bytes_in_stream_(0), total_length_bytes_(), format_() {} - - // The number of bytes that are available for consumption within this - // stream's buffer. - auto bytes_in_stream() -> std::size_t& { return bytes_in_stream_; } - auto bytes_in_stream() const -> std::size_t { return bytes_in_stream_; } - - auto total_length_bytes() -> std::optional& { - return total_length_bytes_; - } - auto total_length_bytes() const -> std::optional { - return total_length_bytes_; - } - - auto total_length_seconds() -> std::optional& { - return total_length_seconds_; - } - auto total_length_seconds() const -> std::optional { - return total_length_seconds_; - } - - struct Encoded { - // The codec that this stream is associated with. - codecs::StreamType type; - - bool operator==(const Encoded&) const = default; - }; - - /* - * Two-channel, interleaved, 32-bit floating point pcm samples. - */ - struct FloatingPointPcm { - // Number of channels in this stream. - uint8_t channels; - // The sample rate. - uint32_t sample_rate; - - bool operator==(const FloatingPointPcm&) const = default; - }; - - struct Pcm { - // Number of channels in this stream. - uint8_t channels; - // Number of bits per sample. - uint8_t bits_per_sample; - // The sample rate. - uint32_t sample_rate; - - auto bytes_per_sample() const -> uint8_t { - return bits_per_sample == 16 ? 2 : 4; - } - - bool operator==(const Pcm&) const = default; - }; - - typedef std::variant Format; - auto format() const -> const Format& { return format_; } - auto set_format(Format f) -> void { format_ = f; } - - template - auto format_as() const -> std::optional { - if (std::holds_alternative(format_)) { - return std::get(format_); - } - return {}; - } - - bool operator==(const StreamInfo&) const = default; - - private: - std::size_t bytes_in_stream_; - std::optional total_length_bytes_; - std::optional total_length_seconds_; - Format format_{}; -}; - -class InputStream; -class OutputStream; - -class RawStream { - public: - explicit RawStream(std::size_t size); - RawStream(std::size_t size, uint32_t); - ~RawStream(); - - auto info() -> StreamInfo& { return info_; } - auto data() -> cpp::span; - template - auto data_as() -> cpp::span { - auto orig = data(); - return {reinterpret_cast(orig.data()), orig.size_bytes() / sizeof(T)}; - } - auto empty() const -> bool { return info_.bytes_in_stream() == 0; } - - private: - StreamInfo info_; - std::size_t buffer_size_; - std::byte* buffer_; -}; - -class InputStream { - public: - explicit InputStream(RawStream* s) : raw_(s) {} - - void consume(std::size_t bytes) const; - - const StreamInfo& info() const; - - cpp::span data() const; - template - auto data_as() const -> cpp::span { - auto orig = data(); - return {reinterpret_cast(orig.data()), - orig.size_bytes() / sizeof(T)}; - } - - private: - RawStream* raw_; -}; - -class OutputStream { - public: - explicit OutputStream(RawStream* s) : raw_(s) {} - - void add(std::size_t bytes) const; - - void prepare(const StreamInfo::Format& new_format, - std::optional length); - - const StreamInfo& info() const; - - cpp::span data() const; - template - auto data_as() const -> cpp::span { - auto orig = data(); - return {reinterpret_cast(orig.data()), orig.size_bytes() / sizeof(T)}; - } - - private: - RawStream* raw_; -}; - -} // namespace audio diff --git a/src/audio/include/stream_message.hpp b/src/audio/include/stream_message.hpp deleted file mode 100644 index cf9ba39c..00000000 --- a/src/audio/include/stream_message.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#pragma once - -#include -#include -#include - -#include "cbor.h" -#include "result.hpp" -#include "span.hpp" - -namespace audio { - -extern const int kEncoderFlags; -extern const int kDecoderFlags; - -enum MessageType { - TYPE_UNKNOWN, - TYPE_CHUNK_HEADER, - TYPE_STREAM_INFO, -}; - -template -auto WriteMessage(MessageType type, Writer&& writer, cpp::span data) - -> cpp::result { - CborEncoder root; - CborEncoder container; - uint8_t* cast_data = reinterpret_cast(data.data()); - - cbor_encoder_init(&root, cast_data, data.size(), kEncoderFlags); - cbor_encoder_create_array(&root, &container, 2); - cbor_encode_uint(&container, type); - - std::optional inner_err = std::invoke(writer, container); - if (inner_err) { - return cpp::fail(inner_err.value()); - } - - cbor_encoder_close_container(&root, &container); - return cbor_encoder_get_buffer_size(&root, cast_data); -} - -template -auto ReadMessage(Reader&& reader, cpp::span data) - -> cpp::result { - CborParser parser; - CborValue root; - CborValue container; - - cbor_parser_init(reinterpret_cast(data.data()), data.size(), - kDecoderFlags, &parser, &root); - cbor_value_enter_container(&root, &container); - // Skip the type header - cbor_value_advance_fixed(&container); - - return std::invoke(reader, container); -} - -auto WriteTypeOnlyMessage(MessageType type, cpp::span data) - -> cpp::result; -auto ReadMessageType(cpp::span msg) -> MessageType; -auto GetAdditionalData(cpp::span msg) -> cpp::span; - -} // namespace audio diff --git a/src/audio/pipeline.cpp b/src/audio/pipeline.cpp deleted file mode 100644 index f54f8d11..00000000 --- a/src/audio/pipeline.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "pipeline.hpp" -#include -#include -#include "stream_info.hpp" - -namespace audio { - -Pipeline::Pipeline(IAudioElement* output) : root_(output), subtrees_() { - assert(output != nullptr); -} - -Pipeline::~Pipeline() {} - -auto Pipeline::AddInput(IAudioElement* input) -> Pipeline* { - subtrees_.push_back(std::make_unique(input)); - return subtrees_.back().get(); -} - -auto Pipeline::OutputElement() const -> IAudioElement* { - return root_; -} - -auto Pipeline::NumInputs() const -> std::size_t { - return subtrees_.size(); -} - -auto Pipeline::InStreams(std::vector* out) -> void { - for (int i = 0; i < subtrees_.size(); i++) { - out->push_back(subtrees_[i]->OutStream()); - } -} - -auto Pipeline::OutStream() -> RawStream { - return {&output_info_, output_buffer_}; -} - -auto Pipeline::GetIterationOrder() -> std::vector { - std::vector to_search{this}; - std::vector found; - - while (!to_search.empty()) { - Pipeline* current = to_search.back(); - to_search.pop_back(); - found.push_back(current); - - for (const auto& i : current->subtrees_) { - to_search.push_back(i.get()); - } - } - - std::reverse(found.begin(), found.end()); - return found; -} - -} // namespace audio diff --git a/src/audio/resample.cpp b/src/audio/resample.cpp index bc2c7c51..a3a34ee7 100644 --- a/src/audio/resample.cpp +++ b/src/audio/resample.cpp @@ -4,27 +4,18 @@ * SPDX-License-Identifier: GPL-3.0-only */ #include "resample.hpp" -/* - * This file contains the implementation for a 32-bit floating point resampler. - * It is largely based on David Bryant's ART resampler, which is BSD-licensed, - * and available at https://github.com/dbry/audio-resampler/. - * - * This resampler uses windowed sinc interpolation filters, with an additional - * lowpass filter to reduce aliasing. - */ -#include -#include -#include #include #include +#include +#include +#include #include #include "esp_log.h" +#include "speex/speex_resampler.h" #include "sample.hpp" -#include "speex/speex_resampler.h" -#include "stream_info.hpp" namespace audio { diff --git a/src/audio/sink_mixer.cpp b/src/audio/sink_mixer.cpp index 79ff4fb7..c6cb886f 100644 --- a/src/audio/sink_mixer.cpp +++ b/src/audio/sink_mixer.cpp @@ -6,19 +6,18 @@ #include "sink_mixer.hpp" -#include #include #include +#include #include "esp_heap_caps.h" #include "esp_log.h" #include "freertos/portmacro.h" #include "freertos/projdefs.h" #include "idf_additions.h" + #include "resample.hpp" #include "sample.hpp" - -#include "stream_info.hpp" #include "tasks.hpp" static constexpr char kTag[] = "mixer"; diff --git a/src/audio/stream_buffer.cpp b/src/audio/stream_buffer.cpp deleted file mode 100644 index 569c9189..00000000 --- a/src/audio/stream_buffer.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "stream_buffer.hpp" -#include "assert.h" -#include "esp_log.h" - -namespace audio { - -StreamBuffer::StreamBuffer(std::size_t chunk_size, std::size_t buffer_size) - : raw_memory_(static_cast( - heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM))), - handle_( - xMessageBufferCreateStatic(buffer_size, - reinterpret_cast(raw_memory_), - &metadata_)), - raw_input_chunk_(static_cast( - heap_caps_malloc(chunk_size * 1.5, MALLOC_CAP_SPIRAM))), - input_chunk_(raw_input_chunk_, chunk_size * 1.5), - raw_output_chunk_(static_cast( - heap_caps_malloc(chunk_size, MALLOC_CAP_SPIRAM))), - output_chunk_(raw_output_chunk_, chunk_size) { - assert(input_chunk_.size() <= buffer_size); - assert(output_chunk_.size() <= buffer_size); - ESP_LOGI("streambuf", "created buffer of chunk size %d, total size %d", - chunk_size, buffer_size); -} - -StreamBuffer::~StreamBuffer() { - vMessageBufferDelete(handle_); - free(raw_memory_); - free(raw_input_chunk_); - free(raw_output_chunk_); -} - -} // namespace audio diff --git a/src/audio/stream_event.cpp b/src/audio/stream_event.cpp deleted file mode 100644 index d7533ea2..00000000 --- a/src/audio/stream_event.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "stream_event.hpp" -#include -#include -#include "arena.hpp" -#include "stream_info.hpp" - -namespace audio { - -auto StreamEvent::CreateStreamInfo(QueueHandle_t source, - const StreamInfo& payload) -> StreamEvent* { - auto event = new StreamEvent; - event->tag = StreamEvent::STREAM_INFO; - event->source = source; - event->stream_info = new StreamInfo(payload); - return event; -} - -auto StreamEvent::CreateArenaChunk(QueueHandle_t source, memory::ArenaPtr ptr) - -> StreamEvent* { - auto event = new StreamEvent; - event->tag = StreamEvent::ARENA_CHUNK; - event->source = source; - event->arena_chunk = ptr; - - return event; -} - -auto StreamEvent::CreateChunkNotification(QueueHandle_t source) - -> StreamEvent* { - auto event = new StreamEvent; - event->tag = StreamEvent::CHUNK_NOTIFICATION; - event->source = source; - return event; -} - -auto StreamEvent::CreateEndOfStream(QueueHandle_t source) -> StreamEvent* { - auto event = new StreamEvent; - event->tag = StreamEvent::END_OF_STREAM; - event->source = source; - return event; -} - -auto StreamEvent::CreateLogStatus() -> StreamEvent* { - auto event = new StreamEvent; - event->tag = StreamEvent::LOG_STATUS; - return event; -} - -StreamEvent::StreamEvent() : tag(StreamEvent::UNINITIALISED) {} - -StreamEvent::~StreamEvent() { - switch (tag) { - case UNINITIALISED: - break; - case STREAM_INFO: - delete stream_info; - break; - case ARENA_CHUNK: - arena_chunk.owner->Return(arena_chunk); - break; - case CHUNK_NOTIFICATION: - break; - case END_OF_STREAM: - break; - case LOG_STATUS: - break; - } -} - -StreamEvent::StreamEvent(StreamEvent&& other) { - tag = other.tag; - source = other.source; - switch (tag) { - case UNINITIALISED: - break; - case STREAM_INFO: - stream_info = other.stream_info; - other.stream_info = nullptr; - break; - case ARENA_CHUNK: - arena_chunk = other.arena_chunk; - other.arena_chunk = { - .owner = nullptr, .start = nullptr, .size = 0, .used_size = 0}; - break; - case CHUNK_NOTIFICATION: - break; - case END_OF_STREAM: - break; - case LOG_STATUS: - break; - } - other.tag = StreamEvent::UNINITIALISED; -} - -} // namespace audio diff --git a/src/audio/stream_info.cpp b/src/audio/stream_info.cpp deleted file mode 100644 index 73dbf91b..00000000 --- a/src/audio/stream_info.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "stream_info.hpp" -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "esp_heap_caps.h" -#include "result.hpp" -#include "span.hpp" -#include "types.hpp" - -namespace audio { - -RawStream::RawStream(std::size_t size) - : info_(), - buffer_size_(size), - buffer_(reinterpret_cast( - heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT))) { - assert(buffer_ != NULL); -} - -RawStream::RawStream(std::size_t size, uint32_t caps) - : info_(), - buffer_size_(size), - buffer_(reinterpret_cast(heap_caps_malloc(size, caps))) { - assert(buffer_ != NULL); -} - -RawStream::~RawStream() { - heap_caps_free(buffer_); -} - -auto RawStream::data() -> cpp::span { - return {buffer_, buffer_size_}; -} - -void InputStream::consume(std::size_t bytes) const { - assert(raw_->info().bytes_in_stream() >= bytes); - auto new_data = - raw_->data().subspan(bytes, raw_->info().bytes_in_stream() - bytes); - std::move(new_data.begin(), new_data.end(), raw_->data().begin()); - raw_->info().bytes_in_stream() = new_data.size_bytes(); -} - -const StreamInfo& InputStream::info() const { - return raw_->info(); -} - -cpp::span InputStream::data() const { - return raw_->data().first(raw_->info().bytes_in_stream()); -} - -void OutputStream::add(std::size_t bytes) const { - assert(raw_->info().bytes_in_stream() + bytes <= raw_->data().size_bytes()); - raw_->info().bytes_in_stream() += bytes; -} - -void OutputStream::prepare(const StreamInfo::Format& new_format, - std::optional length) { - raw_->info().set_format(new_format); - raw_->info().bytes_in_stream() = 0; - raw_->info().total_length_bytes() = length; -} - -const StreamInfo& OutputStream::info() const { - return raw_->info(); -} - -cpp::span OutputStream::data() const { - return raw_->data().subspan(raw_->info().bytes_in_stream()); -} - -} // namespace audio diff --git a/src/audio/stream_message.cpp b/src/audio/stream_message.cpp deleted file mode 100644 index a7b8901a..00000000 --- a/src/audio/stream_message.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2023 jacqueline - * - * SPDX-License-Identifier: GPL-3.0-only - */ - -#include "stream_message.hpp" - -#include - -#include "cbor.h" -#include "span.hpp" - -namespace audio { - -const int kEncoderFlags = 0; -const int kDecoderFlags = 0; - -auto WriteTypeOnlyMessage(MessageType type, cpp::span data) - -> cpp::result { - CborEncoder root; - CborEncoder container; - uint8_t* cast_data = reinterpret_cast(data.data()); - - cbor_encoder_init(&root, cast_data, data.size(), kEncoderFlags); - cbor_encode_uint(&container, type); - - return cbor_encoder_get_buffer_size(&root, cast_data); -} - -auto ReadMessageType(cpp::span msg) -> MessageType { - CborParser parser; - CborValue root; - CborValue container; - - cbor_parser_init(reinterpret_cast(msg.data()), msg.size(), - kDecoderFlags, &parser, &root); - - uint64_t header = 0; - if (cbor_value_is_container(&root)) { - cbor_value_enter_container(&root, &container); - cbor_value_get_uint64(&container, &header); - } else { - cbor_value_get_uint64(&root, &header); - } - - return static_cast(header); -} - -auto GetAdditionalData(cpp::span msg) -> cpp::span { - CborParser parser; - CborValue root; - uint8_t* cast_data = reinterpret_cast(msg.data()); - - cbor_parser_init(cast_data, msg.size(), kDecoderFlags, &parser, &root); - - while (!cbor_value_at_end(&root)) { - cbor_value_advance(&root); - } - - const uint8_t* remaining = cbor_value_get_next_byte(&root); - size_t header_size = remaining - cast_data; - - return cpp::span(msg.data() + header_size, - msg.size() - header_size); -} - -} // namespace audio