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.
This commit is contained in:
Earle F. Philhower, III 2024-12-21 14:15:40 -08:00 committed by GitHub
parent 45c0b3a1b4
commit 5fb5e16be8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 14 deletions

View file

@ -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;

View file

@ -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();

View file

@ -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() {