diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-04-19 16:45:50 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-04-19 16:45:50 +1000 |
| commit | 4c77950e702a329f3136456a932efbea36e03d42 (patch) | |
| tree | 5df7e8717b751846655c16b50c352712b642658b /src/audio | |
| parent | 561f9d2a07ee6ee1c2f18dc375125f87ea7b0d55 (diff) | |
| download | tangara-fw-4c77950e702a329f3136456a932efbea36e03d42.tar.gz | |
Pipeline working and outputting correctly, but noisy
Diffstat (limited to 'src/audio')
| -rw-r--r-- | src/audio/audio_decoder.cpp | 5 | ||||
| -rw-r--r-- | src/audio/audio_task.cpp | 12 | ||||
| -rw-r--r-- | src/audio/i2s_audio_output.cpp | 8 | ||||
| -rw-r--r-- | src/audio/include/audio_sink.hpp | 24 | ||||
| -rw-r--r-- | src/audio/stream_info.cpp | 70 |
5 files changed, 106 insertions, 13 deletions
diff --git a/src/audio/audio_decoder.cpp b/src/audio/audio_decoder.cpp index af9abb94..4b9826a9 100644 --- a/src/audio/audio_decoder.cpp +++ b/src/audio/audio_decoder.cpp @@ -128,7 +128,10 @@ auto AudioDecoder::Process(const std::vector<InputStream>& inputs, } } - input->consume(current_codec_->GetInputPosition() - 1); + std::size_t pos = current_codec_->GetInputPosition(); + if (pos > 0) { + input->consume(pos - 1); + } } } // namespace audio diff --git a/src/audio/audio_task.cpp b/src/audio/audio_task.cpp index 3a2a5941..1670f9f6 100644 --- a/src/audio/audio_task.cpp +++ b/src/audio/audio_task.cpp @@ -45,7 +45,7 @@ auto StartPipeline(Pipeline* pipeline, IAudioSink* sink) -> void { ESP_LOGI(kTag, "starting audio pipeline task"); xTaskCreatePinnedToCore(&AudioTaskMain, "pipeline", kStackSize, args, - kTaskPriorityAudio, NULL, kAudioCore); + kTaskPriorityAudioPipeline, NULL, kAudioCore); } auto StartDrain(IAudioSink* sink) -> void { @@ -57,8 +57,8 @@ auto StartDrain(IAudioSink* sink) -> void { }; ESP_LOGI(kTag, "starting audio drain task"); - xTaskCreatePinnedToCore(&AudioDrainMain, "drain", kDrainStackSize, drain_args, - kTaskPriorityAudio, NULL, kAudioCore); + xTaskCreate(&AudioDrainMain, "drain", kDrainStackSize, drain_args, + kTaskPriorityAudioDrain, NULL); } void AudioTaskMain(void* args) { @@ -134,7 +134,7 @@ void AudioTaskMain(void* args) { // The format of the stream within the sink stream has changed. We // need to reconfigure the sink, but shouldn't do so until we've fully // drained the current buffer. - if (xStreamBufferIsEmpty(sink->buffer())) { + if (xStreamBufferIsEmpty(*sink->buffer())) { ESP_LOGI(kTag, "reconfiguring dac"); output_format = sink_stream.info().format; sink->Configure(*output_format); @@ -149,7 +149,7 @@ void AudioTaskMain(void* args) { // throttle this task's CPU time. Maybe also hold off on the pipeline // if the buffer is already close to full? std::size_t sent = xStreamBufferSend( - sink->buffer(), sink_stream.data().data(), + *sink->buffer(), sink_stream.data().data(), sink_stream.data().size_bytes(), pdMS_TO_TICKS(10)); sink_stream.consume(sent); } @@ -172,7 +172,7 @@ void AudioDrainMain(void* args) { // TODO(jacqueline): implement PAUSE without busy-waiting. while (*command != QUIT) { - std::size_t len = xStreamBufferReceive(sink->buffer(), sDrainBuf, + std::size_t len = xStreamBufferReceive(*sink->buffer(), sDrainBuf, sizeof(sDrainBuf), portMAX_DELAY); if (len > 0) { sink->Send({sDrainBuf, len}); diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp index 2d336152..7e9e9353 100644 --- a/src/audio/i2s_audio_output.cpp +++ b/src/audio/i2s_audio_output.cpp @@ -38,9 +38,13 @@ auto I2SAudioOutput::create(drivers::GpioExpander* expander) I2SAudioOutput::I2SAudioOutput(drivers::GpioExpander* expander, std::unique_ptr<drivers::AudioDac> dac) - : expander_(expander), dac_(std::move(dac)), current_config_() {} + : expander_(expander), dac_(std::move(dac)), current_config_() { + //dac_->SetSource(buffer()); + } -I2SAudioOutput::~I2SAudioOutput() {} +I2SAudioOutput::~I2SAudioOutput() { + dac_->SetSource(nullptr); +} auto I2SAudioOutput::Configure(const StreamInfo::Format& format) -> bool { if (!std::holds_alternative<StreamInfo::Pcm>(format)) { diff --git a/src/audio/include/audio_sink.hpp b/src/audio/include/audio_sink.hpp index 03a4690d..a11a9c92 100644 --- a/src/audio/include/audio_sink.hpp +++ b/src/audio/include/audio_sink.hpp @@ -1,6 +1,9 @@ #pragma once +#include <stdint.h> #include "audio_element.hpp" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" #include "stream_info.hpp" namespace audio { @@ -8,17 +11,30 @@ class IAudioSink { private: // TODO: tune. at least about 12KiB seems right for mp3 static const std::size_t kDrainBufferSize = 24 * 1024; - StreamBufferHandle_t buffer_; + uint8_t *buffer_; + StaticStreamBuffer_t *metadata_; + StreamBufferHandle_t *handle_; public: - IAudioSink() : buffer_(xStreamBufferCreate(kDrainBufferSize, 1)) {} - virtual ~IAudioSink() { vStreamBufferDelete(buffer_); } + IAudioSink() : + buffer_(reinterpret_cast<uint8_t*>(heap_caps_malloc(kDrainBufferSize, MALLOC_CAP_DMA))), + metadata_(reinterpret_cast<StaticStreamBuffer_t*>(heap_caps_malloc(sizeof(StaticStreamBuffer_t), MALLOC_CAP_DMA))), + handle_(reinterpret_cast<StreamBufferHandle_t*>(heap_caps_malloc(sizeof(StreamBufferHandle_t), MALLOC_CAP_DMA))) { + *handle_ = xStreamBufferCreateStatic(kDrainBufferSize, 1, buffer_, metadata_); + } + + virtual ~IAudioSink() { + vStreamBufferDelete(*handle_); + free(buffer_); + free(handle_); + free(metadata_); + } virtual auto Configure(const StreamInfo::Format& format) -> bool = 0; virtual auto Send(const cpp::span<std::byte>& data) -> void = 0; virtual auto Log() -> void {} - auto buffer() const -> StreamBufferHandle_t { return buffer_; } + auto buffer() -> StreamBufferHandle_t* { return handle_; } }; } // namespace audio diff --git a/src/audio/stream_info.cpp b/src/audio/stream_info.cpp new file mode 100644 index 00000000..7d833d25 --- /dev/null +++ b/src/audio/stream_info.cpp @@ -0,0 +1,70 @@ +#include "stream_info.hpp" + +#include <cstdint> +#include <optional> +#include <string> +#include <string_view> +#include <type_traits> +#include <utility> +#include <variant> + +#include "result.hpp" +#include "span.hpp" +#include "types.hpp" + +namespace audio { + +void InputStream::consume(std::size_t bytes) const { + assert(raw_->info->bytes_in_stream >= bytes); + auto new_data = raw_->data.subspan(bytes); + std::move(new_data.begin(), new_data.end(), raw_->data.begin()); + raw_->info->bytes_in_stream = new_data.size_bytes(); +} + +void InputStream::mark_incomplete() const { + raw_->is_incomplete = true; +} + +const StreamInfo& InputStream::info() const { + return *raw_->info; +} + +cpp::span<const std::byte> 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; +} + +bool OutputStream::prepare(const StreamInfo::Format& new_format) { + if (std::holds_alternative<std::monostate>(raw_->info->format)) { + raw_->info->format = new_format; + raw_->info->bytes_in_stream = 0; + return true; + } + if (new_format == raw_->info->format) { + return true; + } + if (raw_->is_incomplete) { + raw_->info->format = new_format; + raw_->info->bytes_in_stream = 0; + return true; + } + return false; +} + +const StreamInfo& OutputStream::info() const { + return *raw_->info; +} + +cpp::span<std::byte> OutputStream::data() const { + return raw_->data.subspan(raw_->info->bytes_in_stream); +} + +bool OutputStream::is_incomplete() const { + return raw_->is_incomplete; +} + +} // namespace audio |
