24#include "WrappedAudioOutputBase.h"
25#include "BackgroundAudioGain.h"
26#include "BackgroundAudioBuffers.h"
27#include "libhelix-aac/aacdec.h"
34template<
class DataBuffer>
77 _gain = (int32_t)(scale * (1 << 16));
90 if (_playing || !_out) {
94#ifdef ARDUINO_ARCH_RP2040
95 _workIRQ = user_irq_claim_unused(
true);
97 irq_set_exclusive_handler(_workIRQ, _irqStub);
98 irq_set_priority(_workIRQ, 0xc0);
99 irq_set_enabled(_workIRQ,
true);
102 _hAACDecoder = AACInitDecoderPre(_private,
sizeof(_private));
108 _out->setBuffers(5, framelen);
109 _out->onTransmit(&_cb, (
void *)
this);
110 _out->setBitsPerSample(16);
111 _out->setStereo(
true);
112 _out->setFrequency(44100);
116 uint16_t zeros[32] __attribute__((aligned(4))) = {};
117 while (_out->availableForWrite() > 32) {
118 _out->write((uint8_t *)zeros,
sizeof(zeros));
130#ifdef ARDUINO_ARCH_RP2040
131 irq_set_enabled(_workIRQ,
false);
132 user_irq_unclaim(_workIRQ);
164 size_t write(
const void *data,
size_t len) {
165 return _ib.write((
const uint8_t *)data, len);
180 return _ib.availableForWrite();
189 return _ib.available() - _accumShift;
284#ifdef ARDUINO_ARCH_RP2040
285 static void _irqStub() {
289 static void _cb(
void *ptr) {
294 static void _cb(
void *ptr) {
299 void generateOneFrame() {
305 int nextFrame = AACFindSyncWord((uint8_t *)_ib.buffer() + _accumShift, _ib.available() - _accumShift);
306 if (nextFrame == -1) {
308 _ib.shiftUp(_ib.available());
310 bzero(_outSample,
sizeof(_outSample));
314 _accumShift += nextFrame;
315 const unsigned char *inBuff = _ib.buffer() + _accumShift;
316 int bytesLeft = _ib.available() - _accumShift;
317 int ret = AACDecode(_hAACDecoder, (
unsigned char **)&inBuff, &bytesLeft, (int16_t *)_outSample);
322 bzero(_outSample,
sizeof(_outSample));
325 AACGetLastFrameInfo(_hAACDecoder, &fi);
326 _sampleRate = fi.sampRateOut;
327 _outSamples = fi.outputSamps / 2;
328 _accumShift = inBuff - _ib.buffer();
330 if (fi.nChans == 1) {
331 for (
int i = 0; i < _outSamples; i++) {
332 _outSample[i][1] = _outSample[1][0];
339 if (_accumShift > _ib.size() / 2) {
340 _ib.shiftUp(_accumShift);
345 ApplyGain((int16_t *)_outSample, _outSamples * 2, _gain);
348#ifdef ARDUINO_ARCH_RP2040
352 while (_out->availableForWrite() >= (
int)(framelen * 2 *
sizeof(int16_t))) {
354 bzero((uint8_t *)_outSample, _outSamples * 2 *
sizeof(int16_t));
358 _out->setFrequency(_sampleRate);
361 assert(_out->write((uint8_t *)_outSample, _outSamples * 2 *
sizeof(int16_t)) == _outSamples * 2 *
sizeof(int16_t));
363#ifdef ARDUINO_ARCH_RP2040
368#ifdef ARDUINO_ARCH_RP2040
369 static uint8_t _workIRQ;
374 AudioOutputBase *_out =
nullptr;
375 HAACDecoder _hAACDecoder;
376 uint8_t _private[ 96 + 28752 + 50788 + 16];
377 bool _playing =
false;
378 bool _paused =
false;
379 static const size_t framelen = 2048;
380 int16_t _outSample[framelen][2] __attribute__((aligned(4)));
381 int _outSamples = 1024;
382 int _sampleRate = 44000;
384 int32_t _gain = 1 << 16;
385 uint32_t _accumShift = 0;
388 uint32_t _frames = 0;
389 uint32_t _shifts = 0;
390 uint32_t _underflows = 0;
391 uint32_t _errors = 0;
395#ifdef ARDUINO_ARCH_RP2040
using ROMBackgroundAudioAAC =
BackgroundAudioAACClass<ROMDataBuffer>;
Interrupt-driven AAC decoder. Generates a full frame of samples each cycle and uses the RawBuffer to ...
Definition BackgroundAudioAAC.h:35
uint32_t underflows()
Get the number of times the AAC decoder has underflowed waiting on raw data since begin
Definition BackgroundAudioAAC.h:224
void pause()
Pause the decoder. Won't process raw input data and will transmit silence.
Definition BackgroundAudioAAC.h:263
bool begin()
Starts the background AAC decoder/player. Will initialize the output device and start sending silence...
Definition BackgroundAudioAAC.h:89
void unpause()
Unpause previously paused playback. Will start processing input data again.
Definition BackgroundAudioAAC.h:279
bool setDevice(AudioOutputBase *d)
Set an output device before begin
Definition BackgroundAudioAAC.h:63
size_t write(const void *data, size_t len)
Writes a block of raw data to the decoder's buffer.
Definition BackgroundAudioAAC.h:164
uint32_t dumps()
Get the number of full buffer dumps (catastrophic data error) since begin
Definition BackgroundAudioAAC.h:242
void flush()
Flushes any existing raw data, resets the processor to start a new AAC.
Definition BackgroundAudioAAC.h:253
uint32_t frames()
Get number of "frames" (1024 or 2048 stereo samples) processed by decoder.
Definition BackgroundAudioAAC.h:206
uint32_t errors()
Get the number of decoder errors since begin
Definition BackgroundAudioAAC.h:233
BackgroundAudioAACClass(AudioOutputBase &d)
Construct an AAC decoder with a given AudioOutputBase.
Definition BackgroundAudioAAC.h:48
bool playing()
Determines if the AAC decoder has been started.
Definition BackgroundAudioAAC.h:142
void end()
Stops the AAC decoder process and the calls the output device's end to shut it down,...
Definition BackgroundAudioAAC.h:128
size_t available()
Gets number of bytes already in the raw buffer.
Definition BackgroundAudioAAC.h:188
bool paused()
Determine if the playback is paused.
Definition BackgroundAudioAAC.h:272
bool done()
Determine if no more AAC file is present in the buffer.
Definition BackgroundAudioAAC.h:197
uint32_t shifts()
Get the number of input data shifts processed by decoder since begin
Definition BackgroundAudioAAC.h:215
size_t availableForWrite()
Gets number of bytes available to write to raw buffer.
Definition BackgroundAudioAAC.h:179
void setGain(float scale)
Set the gain multiplier (volume) for the stream. Takes effect immediately.
Definition BackgroundAudioAAC.h:76