diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-02-14 14:30:53 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-02-14 14:30:53 +1100 |
| commit | a65d996583c72e0d77805bcbc36da580aacb2848 (patch) | |
| tree | ee64bb43ff2f44f495942e50e77176476b71f7b5 /src/audio/i2s_audio_output.cpp | |
| parent | fa1f1cd9aba914882b95e93cdf64ad01309aa633 (diff) | |
| download | tangara-fw-a65d996583c72e0d77805bcbc36da580aacb2848.tar.gz | |
Use the sync apis for I2S output
Diffstat (limited to 'src/audio/i2s_audio_output.cpp')
| -rw-r--r-- | src/audio/i2s_audio_output.cpp | 96 |
1 files changed, 13 insertions, 83 deletions
diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp index 3bed15b5..7ecadc03 100644 --- a/src/audio/i2s_audio_output.cpp +++ b/src/audio/i2s_audio_output.cpp @@ -43,22 +43,12 @@ I2SAudioOutput::I2SAudioOutput(drivers::GpioExpander* expander, volume_(255), is_soft_muted_(false), chunk_reader_(), - latest_chunk_(), - dma_size_(), - dma_queue_(nullptr) {} + latest_chunk_() {} -I2SAudioOutput::~I2SAudioOutput() { - if (dma_queue_ != nullptr) { - ClearDmaQueue(); - } - // TODO: power down the DAC. -} +I2SAudioOutput::~I2SAudioOutput() {} auto I2SAudioOutput::HasUnprocessedInput() -> bool { - if (dma_queue_ == nullptr || !dma_size_) { - return false; - } - return latest_chunk_.size() >= *dma_size_; + return latest_chunk_.size() > 0; } auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) @@ -108,77 +98,30 @@ auto I2SAudioOutput::ProcessStreamInfo(const StreamInfo& info) return cpp::fail(UNSUPPORTED_STREAM); } - QueueHandle_t new_dma_queue = - xQueueCreate(kDmaQueueLength, sizeof(std::byte*)); - - dma_size_ = dac_->Reconfigure(bps, sample_rate, new_dma_queue); - - if (dma_queue_ != nullptr) { - ClearDmaQueue(); - } - dma_queue_ = new_dma_queue; + dac_->Reconfigure(bps, sample_rate); return {}; } auto I2SAudioOutput::ProcessChunk(const cpp::span<std::byte>& chunk) -> cpp::result<std::size_t, AudioProcessingError> { - ESP_LOGI(kTag, "received new samples"); latest_chunk_ = chunk_reader_->HandleNewData(chunk); return 0; } auto I2SAudioOutput::ProcessEndOfStream() -> void { - if (chunk_reader_ && dma_size_) { - auto leftovers = chunk_reader_->GetLeftovers(); - if (leftovers.size() > 0 && leftovers.size() < *dma_size_) { - std::byte* dest = static_cast<std::byte*>(malloc(*dma_size_)); - cpp::span dest_span(dest, *dma_size_); - - std::copy(leftovers.begin(), leftovers.end(), dest_span.begin()); - std::fill(dest_span.begin() + leftovers.size(), dest_span.end(), static_cast<std::byte>(0)); - - xQueueSend(dma_queue_, &dest, portMAX_DELAY); - } - } - - SendOrBufferEvent( - std::unique_ptr<StreamEvent>( - StreamEvent::CreateEndOfStream(input_events_))); - - chunk_reader_.reset(); - dma_size_.reset(); + SendOrBufferEvent(std::unique_ptr<StreamEvent>( + StreamEvent::CreateEndOfStream(input_events_))); } auto I2SAudioOutput::Process() -> cpp::result<void, AudioProcessingError> { - std::size_t spaces_available = uxQueueSpacesAvailable(dma_queue_); - if (spaces_available == 0) { - // TODO: think about this more. can this just be the output event queue? - vTaskDelay(pdMS_TO_TICKS(100)); - return {}; - } - - // Fill the queue as much as possible, since we need to be able to stream - // FAST. - while (latest_chunk_.size() >= *dma_size_ && spaces_available > 0) { - // TODO: small memory arena for this? - std::byte* dest = static_cast<std::byte*>(malloc(*dma_size_)); - cpp::span dest_span(dest, *dma_size_); - cpp::span src_span = latest_chunk_.first(*dma_size_); - std::copy(src_span.begin(), src_span.end(), dest_span.begin()); - if (!xQueueSend(dma_queue_, &dest, 0)) { - // TODO: calculate how often we expect this to happen. - free(dest); - break; - } - latest_chunk_ = latest_chunk_.subspan(*dma_size_); - ESP_LOGI(kTag, "wrote dma buffer of size %u", *dma_size_); - } - if (latest_chunk_.size() < *dma_size_) { - // TODO: if this is the end of the stream, then we should be sending this - // with zero padding. hmm. i guess we need an explicit EOF event? - chunk_reader_->HandleBytesLeftOver(latest_chunk_.size()); - ESP_LOGI(kTag, "not enough samples for dma buffer"); + // Note: no logging here! + 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 {}; } @@ -202,17 +145,4 @@ auto I2SAudioOutput::SetSoftMute(bool enabled) -> void { } } -auto I2SAudioOutput::ClearDmaQueue() -> void { - // Ensure we don't leak any memory from events leftover in the queue. - while (uxQueueSpacesAvailable(dma_queue_) < kDmaQueueLength) { - std::byte* data = nullptr; - if (xQueueReceive(input_events_, &data, 0)) { - free(data); - } else { - break; - } - } - vQueueDelete(dma_queue_); -} - } // namespace audio |
