24#include "WrappedAudioOutputBase.h"
50 _outputRate = outputRate;
51 _outputBufferWords = outputBufferWords;
52 _outputBuffer =
new uint32_t[outputBufferWords];
54 _wordsPerBuffer = 2048;
56 _inputRate = outputRate;
62 delete[] _outputBuffer;
64 auto x = _filled->next;
65 _deleteAudioBuffer(_filled);
69 auto x = _empty->next;
70 _deleteAudioBuffer(_empty);
84 virtual bool setBuffers(
size_t buffers,
size_t bufferWords, int32_t silenceSample = 0)
override {
85 _bufferCount = buffers;
86 _wordsPerBuffer = bufferWords;
87 _silenceSample = silenceSample;
115 if ((
int)_inputRate != freq) {
121 _resample16p16 = _inputRate << 16;
122 _resample16p16 /= _outputRate;
154 for (
size_t i = 0; i < _bufferCount; i++) {
155 auto ab =
new AudioBuffer;
156 ab->buff =
new uint32_t[_wordsPerBuffer];
157 bzero(ab->buff, _wordsPerBuffer * 4);
159 _addToList(&_empty, ab);
179 virtual bool end()
override {
190 auto ret = _underflow;
202 virtual void onTransmit(
void (*cb)(
void *),
void *cbData)
override {
225 virtual size_t write(
const uint8_t *buffer,
size_t size)
override {
231 size_t words = size /
sizeof(uint32_t);
233 AudioBuffer **
volatile p = (AudioBuffer * *
volatile)&_empty;
237 size_t availToWriteThisBuff = _wordsPerBuffer - _userOff;
238 size_t toWrite = std::min(availToWriteThisBuff, words);
239 memcpy(&((*p)->buff[_userOff]), buffer, toWrite *
sizeof(uint32_t));
240 buffer += toWrite *
sizeof(uint32_t);
244 if (_userOff == _wordsPerBuffer) {
245 _addToList(&_filled, _takeFromList(p));
249 return written *
sizeof(uint32_t);
262 AudioBuffer *p = _empty;
263 int avail = _wordsPerBuffer - _userOff;
268 avail += _wordsPerBuffer;
275 void _addToList(AudioBuffer **list, AudioBuffer *element) {
278 while ((*list) && ((*list)->next !=
nullptr)) {
279 list = &(*list)->next;
282 (*list)->next = element;
286 element->next =
nullptr;
290 AudioBuffer *_takeFromList(AudioBuffer **list) {
300 void _deleteAudioBuffer(AudioBuffer *ab) {
305 uint32_t *getResampledBuffer() {
307 if (!_filled && _cb) {
312 for (
size_t i = 0; i < _outputBufferWords; i++) {
313 _outputBuffer[i] = _silenceSample;
316 return _outputBuffer;
319 uint32_t *p = _outputBuffer;
320 if (_outputRate == _inputRate) {
321 for (
size_t i = 0; i < _outputBufferWords; i++) {
322 if (_readOff == _wordsPerBuffer) {
323 _addToList(&_empty, _takeFromList(&_filled));
332 *(p++) = _filled ? _filled->buff[_readOff++] : _silenceSample;
336 for (
size_t i = 0; i < _outputBufferWords; i++) {
337 while (_readOff >= _wordsPerBuffer << 16) {
338 _addToList(&_empty, _takeFromList(&_filled));
339 _readOff -= _wordsPerBuffer << 16;
347 *(p++) = _filled ? _filled->buff[_readOff >> 16] : _silenceSample;
349 _readOff += _resample16p16;
353 return _outputBuffer;
357 typedef struct AudioBuffer {
358 struct AudioBuffer *next;
361 AudioBuffer *_filled =
nullptr;
362 AudioBuffer *_empty =
nullptr;
365 size_t _wordsPerBuffer;
366 int32_t _silenceSample;
368 uint32_t _outputRate;
372 uint32_t _resample16p16;
374 size_t _outputBufferWords;
375 uint32_t *_outputBuffer;
397template<
size_t _outWords = 512>
409 _outRate = outputRate;
446 _out->setBuffers(4, _outWords);
447 _out->onTransmit(&_cb, (
void *)
this);
448 _out->setBitsPerSample(16);
449 _out->setStereo(
true);
450 _out->setFrequency(_outRate);
454 uint32_t zeros[32] __attribute__((aligned(4))) = {};
455 while (_out->availableForWrite() > 32) {
456 _out->write((uint8_t *)zeros,
sizeof(zeros));
468 static void _cb(
void *ptr) {
475 void generateOneFrame() {
477 int16_t *leg[_input.size()];
478 for (
size_t i = 0; i < _input.size(); i++) {
479 leg[i] = (int16_t *)_input[i]->getResampledBuffer();
483 for (
size_t i = 0; i < _outWords * 2; i++) {
485 for (
size_t j = 0; j < _input.size(); j++) {
490 }
else if (sum < -32767) {
493 _outBuff[i] = (int16_t)sum;
501 while (_out->availableForWrite() >= (
int)_outWords) {
503 _out->write((uint8_t *)_outBuff, _outWords * 4);
508 AudioOutputBase *_out;
510 int16_t _outBuff[_outWords * 2];
511 std::vector<BackgroundAudioMixerInput *> _input;
Real-time, IRQ driven mixer with configurable number of inputs.
Definition BackgroundAudioMixer.h:398
BackgroundAudioMixerInput * add()
Create a new input leg on the mixer, usable as an AudioOutputBase. Only legal before begin
Definition BackgroundAudioMixer.h:421
BackgroundAudioMixer(AudioOutputBase &d, int outputRate)
Construct a mixer with output device and constant sample rate.
Definition BackgroundAudioMixer.h:406
bool begin()
Start the mixer and attached physical interface.
Definition BackgroundAudioMixer.h:440