From 5fb5e16be8a6ca1ec337819fffc55bd75e1a0ab5 Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Sat, 21 Dec 2024 14:15:40 -0800 Subject: [PATCH] Add real block write for AudioRequestBuffer (#2712) Optimize AudioRequestBuffer writing when large blocks are available (i.e. I2S writes of full MP3 or AAC frames in BackgroundAudio). Update I2S to use the new call. Reduces 1152 calls to arb::write() to a single call/return and optimized memcpy in that case. --- .../src/AudioBufferManager.cpp | 32 +++++++++++++++++++ .../src/AudioBufferManager.h | 1 + libraries/I2S/src/I2S.cpp | 15 +-------- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/libraries/AudioBufferManager/src/AudioBufferManager.cpp b/libraries/AudioBufferManager/src/AudioBufferManager.cpp index d082aa49..a2a93b3a 100644 --- a/libraries/AudioBufferManager/src/AudioBufferManager.cpp +++ b/libraries/AudioBufferManager/src/AudioBufferManager.cpp @@ -188,6 +188,38 @@ bool AudioBufferManager::write(uint32_t v, bool sync) { return true; } +size_t AudioBufferManager::write(const uint32_t *v, size_t words, bool sync) { + size_t written = 0; + + if (!_running || !_isOutput) { + return 0; + } + while (words) { + AudioBuffer ** volatile p = (AudioBuffer ** volatile)&_empty; + if (!*p) { + if (!sync) { + return written; + } else { + while (!*p) { + /* noop busy wait */ + } + } + + } + size_t availToWriteThisBuff = _wordsPerBuffer - _userOff; + size_t toWrite = std::min(availToWriteThisBuff, words); + memcpy(&((*p)->buff[_userOff]), v, toWrite * sizeof(uint32_t)); + written += toWrite; + _userOff += toWrite; + words -= toWrite; + if (_userOff == _wordsPerBuffer) { + _addToList(&_filled, _takeFromList(p)); + _userOff = 0; + } + } + return written; +} + bool AudioBufferManager::read(uint32_t *v, bool sync) { if (!_running || _isOutput) { return false; diff --git a/libraries/AudioBufferManager/src/AudioBufferManager.h b/libraries/AudioBufferManager/src/AudioBufferManager.h index a98c4270..3326cac5 100644 --- a/libraries/AudioBufferManager/src/AudioBufferManager.h +++ b/libraries/AudioBufferManager/src/AudioBufferManager.h @@ -34,6 +34,7 @@ public: bool begin(int dreq, volatile void *pioFIFOAddr); bool write(uint32_t v, bool sync = true); + size_t write(const uint32_t *v, size_t words, bool sync = true); bool read(uint32_t *v, bool sync = true); void flush(); diff --git a/libraries/I2S/src/I2S.cpp b/libraries/I2S/src/I2S.cpp index b3e71659..ca7374af 100644 --- a/libraries/I2S/src/I2S.cpp +++ b/libraries/I2S/src/I2S.cpp @@ -500,20 +500,7 @@ size_t I2S::write(const uint8_t *buffer, size_t size) { if (size & 0x3 || !_running || !_isOutput) { return 0; } - - size_t writtenSize = 0; - uint32_t *p = (uint32_t *)buffer; - while (size) { - if (!_arb->write(*p, false)) { - // Blocked, stop write here - return writtenSize; - } else { - p++; - size -= 4; - writtenSize += 4; - } - } - return writtenSize; + return _arb->write((const uint32_t *)buffer, size / sizeof(uint32_t), false); } int I2S::availableForWrite() {