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  }
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
A simple Arduino API for the libhelix AAC decoder. The data us provided with the help of write() call...
Definition: AACDecoderHelix.h:19
_AACFrameInfo audioInfo()
Provides the last available _AACFrameInfo_t.
Definition: AACDecoderHelix.h:48
size_t maxPCMSize() override
Definition: AACDecoderHelix.h:66
virtual void end() override
Releases the reserved memory.
Definition: AACDecoderHelix.h:51
int decode() override
decods the data and removes the decoded frame from the buffer
Definition: AACDecoderHelix.h:106
void setAudioInfo(int channels, int samplerate)
Used by M3A format.
Definition: AACDecoderHelix.h:71
virtual bool allocateDecoder() override
Allocate the decoder.
Definition: AACDecoderHelix.h:88
size_t maxFrameSize() override
Definition: AACDecoderHelix.h:62
int findSynchWord(int offset=0) override
finds the sync word in the buffer
Definition: AACDecoderHelix.h:97
Common Simple Arduino API.
Definition: CommonHelix.h:33
void flush()
Decode all open packets.
Definition: CommonHelix.h:104
virtual void end()
Releases the reserved memory.
Definition: CommonHelix.h:63
virtual void setMinFrameBufferSize(int size)
Defines the minimum frame buffer size which is required before starting the decoding.
Definition: CommonHelix.h:251