Arduino LibHelix

AACDecoderHelix.h
1 #pragma once
2
3 #include "CommonHelix.h"
4 #include "libhelix-aac/aacdec.h"
5
6 namespace libhelix {
7
8 typedef void (*AACInfoCallback)(_AACFrameInfo &info, void *ref);
9 typedef void (*AACDataCallback)(_AACFrameInfo &info, short *pcm_buffer,
10 size_t len, void *ref);
11
19 class AACDecoderHelix : public CommonHelix {
20 public:
21 AACDecoderHelix() {
22 setMinFrameBufferSize(AAC_MIN_FRAME_SIZE);
23 }
24
25 #if defined(ARDUINO) || defined(HELIX_PRINT)
26 AACDecoderHelix(Print &output) {
27 setMinFrameBufferSize(AAC_MIN_FRAME_SIZE);
28 this->out = &output;
29 }
30 #endif
31
32 AACDecoderHelix(AACDataCallback dataCallback) {
33 setMinFrameBufferSize(AAC_MIN_FRAME_SIZE);
34 this->pcmCallback = dataCallback;
35 }
36
37 virtual ~AACDecoderHelix() { end(); }
38
39 void setInfoCallback(AACInfoCallback cb, void *caller = nullptr) {
40 this->infoCallback = cb;
41 if (caller!=nullptr)
42 p_caller_ref = caller;
43 }
44
45 void setDataCallback(AACDataCallback cb) { this->pcmCallback = cb; }
46
48 _AACFrameInfo audioInfo() { return aacFrameInfo; }
49
51 virtual void end() override {
52 LOGD_HELIX( "end");
53 if (decoder != nullptr) {
54 flush();
55 AACFreeDecoder(decoder);
56 decoder = nullptr;
57 }
58 CommonHelix::end();
59 memset(&aacFrameInfo, 0, sizeof(_AACFrameInfo));
60 }
61
62 size_t maxFrameSize() override {
63 return max_frame_size == 0 ? AAC_MAX_FRAME_SIZE : max_frame_size;
64 }
65
66 size_t maxPCMSize() override {
67 return max_pcm_size == 0 ? AAC_MAX_OUTPUT_SIZE : max_pcm_size;
68 }
69
71 void setAudioInfo(int channels, int samplerate) {
72 memset(&aacFrameInfo, 0, sizeof(AACFrameInfo));
73 aacFrameInfo.nChans = channels;
74 // aacFrameInfo.bitsPerSample = bits; not used
75 aacFrameInfo.sampRateCore = samplerate;
76 aacFrameInfo.profile = AAC_PROFILE_LC;
77 AACSetRawBlockParams(decoder, 0, &aacFrameInfo);
78 }
79
80 protected:
81 HAACDecoder decoder = nullptr;
82 AACDataCallback pcmCallback = nullptr;
83 AACInfoCallback infoCallback = nullptr;
84 _AACFrameInfo aacFrameInfo;
85 void *p_caller_data = nullptr;
86
88 virtual bool allocateDecoder() override {
89 if (decoder == nullptr) {
90 decoder = AACInitDecoder();
91 }
92 memset(&aacFrameInfo, 0, sizeof(_AACFrameInfo));
93 return decoder != nullptr;
94 }
95
97 int findSynchWord(int offset = 0) override {
98 if (offset > frame_buffer.available()) return -1;
99 int result = AACFindSyncWord(frame_buffer.data() + offset,
100 frame_buffer.available() - offset);
101 if (result < 0) return result;
102 return offset == 0 ? result : result - offset;
103 }
104
106 int decode() override {
107 LOGD_HELIX( "decode");
108 int processed = 0;
109 int available = frame_buffer.available();
110 int bytes_left = frame_buffer.available();
111 uint8_t *data = frame_buffer.data();
112 int rc = AACDecode(decoder, &data, &bytes_left, (short *)pcm_buffer.data());
113 if (rc == 0) {
114 processed = data - frame_buffer.data();
115 // return the decoded result
116 _AACFrameInfo info;
117 AACGetLastFrameInfo(decoder, &info);
118 provideResult(info);
119 }
120 return processed;
121 }
122
123 // return the result PCM data
124 void provideResult(_AACFrameInfo &info) {
125 // increase PCM size if this fails
126 int sampleSize = info.bitsPerSample / 8;
127 assert(info.outputSamps * sampleSize <= maxPCMSize());
128
129 LOGD_HELIX( "==> provideResult: %d samples", info.outputSamps);
130 if (info.outputSamps > 0) {
131 // provide result
132 if (pcmCallback != nullptr) {
133 // output via callback
134 pcmCallback(info, (short *)pcm_buffer.data(), info.outputSamps,
135 p_caller_data);
136 } else {
137 // output to stream
138 if (info.sampRateOut != aacFrameInfo.sampRateOut &&
139 infoCallback != nullptr) {
140 infoCallback(info, p_caller_ref);
141 }
142 #if defined(ARDUINO) || defined(HELIX_PRINT)
143 if (out != nullptr){
144 size_t to_write = info.outputSamps * sampleSize;
145 size_t written = out->write((uint8_t *)pcm_buffer.data(), to_write);
146 assert(written == to_write);
147 }
148 #endif
149 }
150 aacFrameInfo = info;
151 }
152 }
153 };
154 } // namespace libhelix
libhelix::AACDecoderHelix
A simple Arduino API for the libhelix AAC decoder. The data us provided with the help of write() call...
Definition: AACDecoderHelix.h:19
libhelix::AACDecoderHelix::audioInfo
_AACFrameInfo audioInfo()
Provides the last available _AACFrameInfo_t.
Definition: AACDecoderHelix.h:48
libhelix::AACDecoderHelix::maxPCMSize
size_t maxPCMSize() override
Definition: AACDecoderHelix.h:66
libhelix::AACDecoderHelix::end
virtual void end() override
Releases the reserved memory.
Definition: AACDecoderHelix.h:51
libhelix::AACDecoderHelix::decode
int decode() override
decods the data and removes the decoded frame from the buffer
Definition: AACDecoderHelix.h:106
libhelix::AACDecoderHelix::setAudioInfo
void setAudioInfo(int channels, int samplerate)
Used by M3A format.
Definition: AACDecoderHelix.h:71
libhelix::AACDecoderHelix::allocateDecoder
virtual bool allocateDecoder() override
Allocate the decoder.
Definition: AACDecoderHelix.h:88
libhelix::AACDecoderHelix::maxFrameSize
size_t maxFrameSize() override
Definition: AACDecoderHelix.h:62
libhelix::AACDecoderHelix::findSynchWord
int findSynchWord(int offset=0) override
finds the sync word in the buffer
Definition: AACDecoderHelix.h:97
libhelix::CommonHelix
Common Simple Arduino API.
Definition: CommonHelix.h:33
libhelix::CommonHelix::flush
void flush()
Decode all open packets.
Definition: CommonHelix.h:104
libhelix::CommonHelix::end
virtual void end()
Releases the reserved memory.
Definition: CommonHelix.h:63
libhelix::CommonHelix::setMinFrameBufferSize
virtual void setMinFrameBufferSize(int size)
Defines the minimum frame buffer size which is required before starting the decoding.
Definition: CommonHelix.h:251