diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-03-10 11:28:33 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-04-19 10:27:59 +1000 |
| commit | a9531c86a433c8b7ae1f77ff0266c27c39eca7f4 (patch) | |
| tree | 11835552aa2ecb400537781d8eb3851118c47e61 /src/audio/i2s_audio_output.cpp | |
| parent | 2a46eecdc6334c31cee2b40427d2536b48cbb6be (diff) | |
| download | tangara-fw-a9531c86a433c8b7ae1f77ff0266c27c39eca7f4.tar.gz | |
mostly single task pipeline
Diffstat (limited to 'src/audio/i2s_audio_output.cpp')
| -rw-r--r-- | src/audio/i2s_audio_output.cpp | 83 |
1 files changed, 28 insertions, 55 deletions
diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp index 110227cf..7766ebed 100644 --- a/src/audio/i2s_audio_output.cpp +++ b/src/audio/i2s_audio_output.cpp @@ -1,6 +1,7 @@ #include "i2s_audio_output.hpp" #include <algorithm> +#include <variant> #include "esp_err.h" #include "freertos/portmacro.h" @@ -10,14 +11,12 @@ #include "freertos/projdefs.h" #include "gpio_expander.hpp" #include "result.hpp" +#include "stream_info.hpp" -static const TickType_t kIdleTimeBeforeMute = pdMS_TO_TICKS(1000); static const char* kTag = "I2SOUT"; namespace audio { -static const std::size_t kDmaQueueLength = 8; - auto I2SAudioOutput::create(drivers::GpioExpander* expander) -> cpp::result<std::shared_ptr<I2SAudioOutput>, Error> { // First, we need to perform initial configuration of the DAC chip. @@ -38,40 +37,26 @@ auto I2SAudioOutput::create(drivers::GpioExpander* expander) I2SAudioOutput::I2SAudioOutput(drivers::GpioExpander* expander, std::unique_ptr<drivers::AudioDac> dac) - : expander_(expander), - dac_(std::move(dac)), - chunk_reader_(), - latest_chunk_() {} + : expander_(expander), dac_(std::move(dac)), current_config_() {} I2SAudioOutput::~I2SAudioOutput() {} -auto I2SAudioOutput::HasUnprocessedInput() -> bool { - return latest_chunk_.size() > 0; -} - -auto I2SAudioOutput::IsOverBuffered() -> bool { - return false; -} - -auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> void { - // TODO(jacqueline): probs do something with the channel hey - - if (!info.bits_per_sample || !info.sample_rate) { - ESP_LOGE(kTag, "audio stream missing bits or sample rate"); - return; +auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> bool { + if (!std::holds_alternative<StreamInfo::Pcm>(info.data)) { + return false; } - if (!info.chunk_size) { - ESP_LOGE(kTag, "audio stream missing chunk size"); - return; + StreamInfo::Pcm pcm = std::get<StreamInfo::Pcm>(info.data); + + if (current_config_ && pcm == *current_config_) { + return true; } - chunk_reader_.emplace(*info.chunk_size); - ESP_LOGI(kTag, "incoming audio stream: %u bpp @ %u Hz", *info.bits_per_sample, - *info.sample_rate); + ESP_LOGI(kTag, "incoming audio stream: %u bpp @ %u Hz", pcm.bits_per_sample, + pcm.sample_rate); drivers::AudioDac::BitsPerSample bps; - switch (*info.bits_per_sample) { + switch (pcm.bits_per_sample) { case 16: bps = drivers::AudioDac::BPS_16; break; @@ -83,11 +68,11 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> void { break; default: ESP_LOGE(kTag, "dropping stream with unknown bps"); - return; + return false; } drivers::AudioDac::SampleRate sample_rate; - switch (*info.sample_rate) { + switch (pcm.sample_rate) { case 44100: sample_rate = drivers::AudioDac::SAMPLE_RATE_44_1; break; @@ -96,37 +81,25 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) -> void { break; default: ESP_LOGE(kTag, "dropping stream with unknown rate"); - return; + return false; } - dac_->Reconfigure(bps, sample_rate); -} - -auto I2SAudioOutput::ProcessChunk(const cpp::span<std::byte>& chunk) -> void { - latest_chunk_ = chunk_reader_->HandleNewData(chunk); -} + // TODO(jacqueline): probs do something with the channel hey -auto I2SAudioOutput::ProcessEndOfStream() -> void { - dac_->Stop(); - SendOrBufferEvent(std::unique_ptr<StreamEvent>( - StreamEvent::CreateEndOfStream(input_events_))); -} + dac_->Reconfigure(bps, sample_rate); + current_config_ = pcm; -auto I2SAudioOutput::ProcessLogStatus() -> void { - dac_->LogStatus(); + return true; } -auto I2SAudioOutput::Process() -> void { - // Note: avoid logging here! We need to get bytes from the chunk buffer into - // the I2S DMA buffer as fast as possible, to avoid running out of samples. - std::size_t bytes_written = dac_->WriteData(latest_chunk_); - if (bytes_written == latest_chunk_.size_bytes()) { - latest_chunk_ = cpp::span<std::byte>(); - chunk_reader_->HandleBytesLeftOver(0); - } else { - latest_chunk_ = latest_chunk_.subspan(bytes_written); - } - return; +auto I2SAudioOutput::Process(std::vector<Stream>* inputs, MutableStream* output) + -> void { + std::for_each(inputs->begin(), inputs->end(), [&](Stream& s) { + if (ProcessStreamInfo(s.info)) { + std::size_t bytes_written = dac_->WriteData(s.data); + s.data = s.data.subspan(bytes_written); + } + }); } auto I2SAudioOutput::SetVolume(uint8_t volume) -> void { |
