24#include "WrappedAudioOutputBase.h"
25#include "BackgroundAudioGain.h"
26#include "BackgroundAudioBuffers.h"
27#include "libmad/config.h"
28#include "libmad/mad.h"
35template<
class DataBuffer>
78 _gain = (int32_t)(scale * (1 << 16));
89 mad_stream_init(&_stream);
90 mad_frame_init(&_frame);
91 mad_synth_init(&_synth);
92 mad_stream_options(&_stream, 0);
95 _out->setBuffers(5, framelen);
96 _out->onTransmit(&_cb, (
void *)
this);
97 _out->setBitsPerSample(16);
98 _out->setStereo(
true);
99 _out->setFrequency(44100);
103 uint16_t zeros[32] __attribute__((aligned(4))) = {};
104 while (_out->availableForWrite() > 32) {
105 _out->write((uint8_t *)zeros,
sizeof(zeros));
150 size_t write(
const void *data,
size_t len) {
151 return _ib.write((
const uint8_t *)data, len);
166 return _ib.availableForWrite();
175 return _ib.available() - _accumShift;
184 return available() <= MAD_BUFFER_GUARD * 2;
271 static void _cb(
void *ptr) {
275 void generateOneFrame() {
282 if (_stream.buffer) {
283 if (_stream.next_frame && _stream.next_frame != _stream.this_frame) {
284 _accumShift += _stream.next_frame - _stream.this_frame;
287 _accumShift += maxFrameSize;
293 int pend = _ib.available() - 1 - _accumShift;
294 const uint8_t *b = _ib.buffer() + _accumShift;
296 for (ptr = 0; ptr < pend; ptr++) {
297 if ((b[ptr] == 0xff) && ((b[ptr + 1] & 0xe0) == 0xe0)) {
306 _ib.shiftUp(_ib.available());
311 if (_accumShift > _ib.size() / 2) {
312 _ib.shiftUp(_accumShift);
318 if (_ib.available() - _accumShift < MAD_BUFFER_GUARD) {
319 _ib.write0(MAD_BUFFER_GUARD);
324 mad_stream_buffer(&_stream, _ib.buffer() + _accumShift, _ib.available() - _accumShift);
327 if (mad_frame_decode(&_frame, &_stream)) {
328 mad_frame_mute(&_frame);
331 mad_synth_frame(&_synth, &_frame);
335 if (_synth.pcm.channels == 1) {
336 for (
size_t i = 0; i < framelen; i++) {
337 _synth.pcm.samplesX[i][1] = _synth.pcm.samplesX[i][0];
341 ApplyGain((int16_t*)_synth.pcm.samplesX, framelen * 2, _gain);
345 while (_out->availableForWrite() >= (
int)framelen) {
347 bzero(_synth.pcm.samplesX, _synth.pcm.length * 4);
350 if (_synth.pcm.samplerate) {
351 _out->setFrequency(_synth.pcm.samplerate);
354 _out->write((uint8_t *)_synth.pcm.samplesX, _synth.pcm.length * 4);
359 AudioOutputBase *_out;
360 bool _playing =
false;
361 bool _paused =
false;
362 static const size_t framelen = 1152;
363 static const size_t maxFrameSize = 2881;
365 struct mad_stream _stream;
366 struct mad_frame _frame;
367 struct mad_synth _synth;
368 int32_t _gain = 1 << 16;
369 uint32_t _accumShift = 0;
372 uint32_t _frames = 0;
373 uint32_t _shifts = 0;
374 uint32_t _underflows = 0;
375 uint32_t _errors = 0;
Interrupt-driven MP3 decoder. Generates a full frame of samples each cycle and uses the RawBuffer to ...
Definition BackgroundAudioMP3.h:36
size_t availableForWrite()
Gets number of bytes available to write to raw buffer.
Definition BackgroundAudioMP3.h:165
uint32_t underflows()
Get the number of times the MP3 decoder has underflowed waiting on raw data since begin
Definition BackgroundAudioMP3.h:210
uint32_t dumps()
Get the number of full buffer dumps (catastrophic data error) since begin
Definition BackgroundAudioMP3.h:228
void end()
Stops the MP3 decoder process and the calls the output device's end to shut it down,...
Definition BackgroundAudioMP3.h:116
BackgroundAudioMP3Class(AudioOutputBase &d)
Construct an MP3 output device using the specified physical audio output.
Definition BackgroundAudioMP3.h:49
void flush()
Flushes any existing raw data, resets the processor to start a new MP3.
Definition BackgroundAudioMP3.h:263
uint32_t shifts()
Get the number of input data shifts processed by decoder since begin
Definition BackgroundAudioMP3.h:201
void setGain(float scale)
Set the gain multiplier (volume) for the stream. Takes effect immediately.
Definition BackgroundAudioMP3.h:77
bool done()
Determine if no more MP3 file is present in the buffer.
Definition BackgroundAudioMP3.h:183
void unpause()
Unpause previously paused playback. Will start processing input data again.
Definition BackgroundAudioMP3.h:252
bool setDevice(AudioOutputBase *d)
Set an output device before begin
Definition BackgroundAudioMP3.h:64
bool begin()
Starts the background MP3 decoder/player. Will initialize the output device and start sending silence...
Definition BackgroundAudioMP3.h:87
size_t available()
Gets number of bytes already in the raw buffer.
Definition BackgroundAudioMP3.h:174
uint32_t errors()
Get the number of decoder errors since begin
Definition BackgroundAudioMP3.h:219
size_t write(const void *data, size_t len)
Writes a block of raw data to the decoder's buffer.
Definition BackgroundAudioMP3.h:150
void pause()
Pause the decoder. Won't process raw input data and will transmit silence.
Definition BackgroundAudioMP3.h:235
bool playing()
Determines if the MP3 decoder has been started.
Definition BackgroundAudioMP3.h:128
uint32_t frames()
Get number of "frames" (1152 stereo samples) processed by decoder.
Definition BackgroundAudioMP3.h:192
bool paused()
Determine if the playback is paused.
Definition BackgroundAudioMP3.h:244