arduino-audio-tools
Loading...
Searching...
No Matches
ContainerATRAC.h
Go to the documentation of this file.
1
14#pragma once
15
16#include <string.h>
17
20
21namespace audio_tools {
22
31 public:
33
35 void setOutput(Print &out_stream) override {
36 AudioDecoder::setOutput(out_stream);
37 dec.setOutput(out_stream);
38 }
39
41 bool begin() override {
42 dec.end();
43 hdr.clear();
44 state = 0;
45 skip_count = 0;
46 payload_left = 0;
47 is_streaming = false;
48 is_done = false;
49 is_failed = false;
50 is_active = true;
51 return true;
52 }
53
54 void end() override {
55 dec.end();
56 is_active = false;
57 }
58
59 operator bool() override { return is_active && !is_failed; }
60
62 DecoderATRAC &decoder() { return dec; }
63
65 size_t write(const uint8_t *data, size_t len) override {
66 if (!is_active || is_failed) return 0;
67 const uint8_t *p = data;
68 size_t n = len;
69 while (n > 0 && !is_failed && !is_done) {
70 if (skip_count > 0) {
71 size_t s = skip_count < n ? skip_count : n;
72 p += s;
73 n -= s;
74 skip_count -= s;
75 } else if (is_streaming) {
76 writePayload(p, n);
77 } else {
78 int state_before = state;
79 size_t n_before = n;
80 parse(p, n);
81 if (!is_failed && state == state_before && n == n_before &&
82 !is_streaming) {
83 LOGE("ATRAC header parser is not progressing");
84 is_failed = true;
85 }
86 }
87 }
88 return is_failed ? 0 : len;
89 }
90
91 protected:
94 size_t skip_count = 0;
97 int state = 0;
98 bool payload_known = false;
99 bool is_streaming = false;
100 bool is_done = false;
101 bool is_failed = false;
102 bool is_active = false;
103
105 virtual void parse(const uint8_t *&p, size_t &n) = 0;
106
108 bool collect(const uint8_t *&p, size_t &n, size_t need) {
109 while ((size_t)hdr.size() < need && n > 0) {
110 uint8_t value = *p;
111 hdr.push_back(value);
112 p++;
113 n--;
114 }
115 return (size_t)hdr.size() >= need;
116 }
117
118 void fail(const char *msg) {
119 LOGE("%s", msg);
120 is_failed = true;
121 }
122
124 bool startDecoder(ATRACType type, int sample_rate, int channels,
125 int block_align, const uint8_t *extra = nullptr,
126 size_t extra_size = 0, bool known = false,
127 uint32_t length = 0) {
128 if (!dec.begin(type, sample_rate, channels, block_align, extra,
129 extra_size)) {
130 fail("ATRAC decoder could not be started");
131 return false;
132 }
134 payload_known = known;
135 payload_left = length;
136 is_streaming = true;
137 if (known && length == 0) is_done = true;
138 return true;
139 }
140
141 void writePayload(const uint8_t *&p, size_t &n) {
142 size_t chunk = n;
143 if (payload_known && chunk > payload_left) chunk = payload_left;
144 if (chunk > 0) dec.write(p, chunk);
145 p += chunk;
146 n -= chunk;
147 if (payload_known) {
148 payload_left -= chunk;
149 // ignore everything which follows the audio data (e.g. other chunks)
150 if (payload_left == 0) is_done = true;
151 }
152 }
153
154 static uint16_t be16(const uint8_t *p) { return (p[0] << 8) | p[1]; }
155 static uint32_t be24(const uint8_t *p) {
156 return (p[0] << 16) | (p[1] << 8) | p[2];
157 }
158};
159
170 public:
171 const char *mime() override { return "audio/oma"; }
172
173 protected:
174 enum State { Start = 0, Ea3 };
175 static const size_t ID3_HEADER_SIZE = 10;
176 static const size_t EA3_HEADER_SIZE = 96;
178
179 void parse(const uint8_t *&p, size_t &n) override {
180 switch (state) {
181 case Start:
182 if (!collect(p, n, ID3_HEADER_SIZE)) return;
183 if (memcmp(hdr.data(), "ea3", 3) == 0 ||
184 memcmp(hdr.data(), "ID3", 3) == 0) {
185 size_t tag_size = syncSafe(hdr.data() + 6);
186 // footer
187 if (hdr.data()[5] & 0x10) tag_size += 10;
188 skip_count = tag_size;
189 hdr.clear();
190 } else if (memcmp(hdr.data(), "EA3", 3) != 0) {
191 fail("Not an OMA stream");
192 return;
193 }
194 // an EA3 header without the tag is completed in the next state
195 state = Ea3;
196 break;
197
198 case Ea3:
199 if (!collect(p, n, EA3_HEADER_SIZE)) return;
200 parseEa3();
201 break;
202 }
203 }
204
205 static size_t syncSafe(const uint8_t *p) {
206 return ((p[0] & 0x7F) << 21) | ((p[1] & 0x7F) << 14) |
207 ((p[2] & 0x7F) << 7) | (p[3] & 0x7F);
208 }
209
210 void parseEa3() {
211 const uint8_t *h = hdr.data();
212 if (memcmp(h, "EA3", 3) != 0 || h[4] != 0 || h[5] != EA3_HEADER_SIZE) {
213 fail("OMA: EA3 header not found");
214 return;
215 }
216 // 0xFFFF and 0xFF80: not encrypted
217 uint16_t encryption_id = be16(h + 6);
218 if (encryption_id != 0xFFFF && encryption_id != 0xFF80) {
219 fail("OMA: encrypted files are not supported");
220 return;
221 }
222 uint8_t codec_id = h[32];
223 uint32_t params = be24(h + 33);
224 static const int rates[] = {32000, 44100, 48000, 88200, 96000};
225 unsigned rate_idx = (params >> 13) & 7;
226 if (rate_idx >= sizeof(rates) / sizeof(rates[0])) {
227 fail("OMA: invalid sample rate");
228 return;
229 }
230 int sample_rate = rates[rate_idx];
231 int frame_size = (params & 0x3FF) * 8;
232
233 if (codec_id == CodecATRAC3) {
234 // joint stereo flag: fake the extradata of the WAV format
235 uint16_t js = (params >> 17) & 1;
236 uint8_t extra[14] = {1, 0, 0, 0x10, 0, 0, (uint8_t)js, 0,
237 (uint8_t)js, 0, 1, 0, 0, 0};
238 hdr.clear();
239 startDecoder(ATRAC3, sample_rate, 2, frame_size, extra, sizeof(extra));
240 } else if (codec_id == CodecATRAC3Plus) {
241 static const int channel_ids[] = {0, 1, 2, 3, 4, 6, 7, 8};
242 int channels = channel_ids[(params >> 10) & 7];
243 if (channels == 0) {
244 fail("OMA: invalid channel configuration");
245 return;
246 }
247 hdr.clear();
248 startDecoder(ATRAC3PLUS, sample_rate, channels, frame_size + 8);
249 } else {
250 fail("OMA: unsupported codec (only ATRAC3 and ATRAC3+)");
251 }
252 }
253};
254
264 public:
265 const char *mime() override { return "audio/aea"; }
266
267 protected:
268 static const size_t HEADER_SIZE = 2048;
269 static const size_t CHANNELS_POS = 264;
270 static const int SOUND_UNIT_SIZE = 212;
271
272 void parse(const uint8_t *&p, size_t &n) override {
273 if (!collect(p, n, CHANNELS_POS + 1)) return;
274 static const uint8_t magic[4] = {0x00, 0x08, 0x00, 0x00};
275 if (memcmp(hdr.data(), magic, 4) != 0) {
276 fail("Not an AEA stream");
277 return;
278 }
279 int channels = hdr.data()[CHANNELS_POS];
280 hdr.clear();
281 if (channels != 1 && channels != 2) {
282 fail("AEA: invalid number of channels");
283 return;
284 }
285 startDecoder(ATRAC1, 44100, channels, SOUND_UNIT_SIZE * channels);
286 // the rest of the header is not needed
288 }
289};
290
291} // namespace audio_tools
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Definition Arduino.h:56
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:32
virtual void setOutput(AudioStream &out_stream)
Defines where the decoded result is written to.
Definition AudioCodecsBase.h:40
AudioInfo audioInfo() override
provides the actual input AudioInfo
Definition AudioCodecsBase.h:29
Decodes ATRAC1 audio of a Sony MiniDisc .aea file: a 2048 byte header (magic, title,...
Definition ContainerATRAC.h:263
static const size_t HEADER_SIZE
Definition ContainerATRAC.h:268
static const int SOUND_UNIT_SIZE
Definition ContainerATRAC.h:270
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition ContainerATRAC.h:265
void parse(const uint8_t *&p, size_t &n) override
Processes the header data: must consume data, change the state or fail.
Definition ContainerATRAC.h:272
static const size_t CHANNELS_POS
Definition ContainerATRAC.h:269
Common functionality of the ATRAC container decoders: a streaming header parser which does not need t...
Definition ContainerATRAC.h:30
void setOutput(Print &out_stream) override
Defines where the decoded PCM data is written to.
Definition ContainerATRAC.h:35
bool payload_known
Definition ContainerATRAC.h:98
size_t skip_count
Definition ContainerATRAC.h:94
bool is_done
Definition ContainerATRAC.h:100
bool is_active
Definition ContainerATRAC.h:102
void writePayload(const uint8_t *&p, size_t &n)
Definition ContainerATRAC.h:141
void end() override
Definition ContainerATRAC.h:54
bool collect(const uint8_t *&p, size_t &n, size_t need)
Copies the data into hdr until it contains need bytes.
Definition ContainerATRAC.h:108
static uint32_t be24(const uint8_t *p)
Definition ContainerATRAC.h:155
size_t write(const uint8_t *data, size_t len) override
Processes the container data: returns 0 if the stream is not supported.
Definition ContainerATRAC.h:65
int state
Definition ContainerATRAC.h:97
bool is_failed
Definition ContainerATRAC.h:101
DecoderATRAC dec
Definition ContainerATRAC.h:92
Vector< uint8_t > hdr
Definition ContainerATRAC.h:93
bool is_streaming
Definition ContainerATRAC.h:99
void fail(const char *msg)
Definition ContainerATRAC.h:118
bool startDecoder(ATRACType type, int sample_rate, int channels, int block_align, const uint8_t *extra=nullptr, size_t extra_size=0, bool known=false, uint32_t length=0)
Configures the decoder: the audio data starts after the header.
Definition ContainerATRAC.h:124
bool begin() override
Prepares the decoder for a new stream.
Definition ContainerATRAC.h:41
virtual void parse(const uint8_t *&p, size_t &n)=0
Processes the header data: must consume data, change the state or fail.
static uint16_t be16(const uint8_t *p)
Definition ContainerATRAC.h:154
DecoderATRAC & decoder()
Provides access to the ATRAC decoder.
Definition ContainerATRAC.h:62
uint32_t payload_left
remaining audio bytes (only relevant if payload_known)
Definition ContainerATRAC.h:96
Decodes ATRAC3 and ATRAC3+ audio in a Sony OpenMG audio container (.oma, .aa3, .at3): the file starts...
Definition ContainerATRAC.h:169
State
Definition ContainerATRAC.h:174
@ Start
Definition ContainerATRAC.h:174
@ Ea3
Definition ContainerATRAC.h:174
void parseEa3()
Definition ContainerATRAC.h:210
CodecId
Definition ContainerATRAC.h:177
@ CodecATRAC3
Definition ContainerATRAC.h:177
@ CodecATRAC3Plus
Definition ContainerATRAC.h:177
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition ContainerATRAC.h:171
void parse(const uint8_t *&p, size_t &n) override
Processes the header data: must consume data, change the state or fail.
Definition ContainerATRAC.h:179
static const size_t ID3_HEADER_SIZE
Definition ContainerATRAC.h:175
static size_t syncSafe(const uint8_t *p)
Definition ContainerATRAC.h:205
static const size_t EA3_HEADER_SIZE
Definition ContainerATRAC.h:176
Parent class for all container formats.
Definition AudioCodecsBase.h:90
ATRAC decoder (ATRAC1, ATRAC3, ATRAC3+ and ATRAC9) which converts the raw ATRAC frames into 16 bit PC...
Definition CodecATRAC.h:39
void end() override
Definition CodecATRAC.h:139
size_t write(const uint8_t *data, size_t len) override
Decodes the data: any amount of data can be provided.
Definition CodecATRAC.h:155
bool begin() override
Definition CodecATRAC.h:90
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
void push_back(T &&value)
Definition Vector.h:182
void clear()
Definition Vector.h:176
T * data()
Definition Vector.h:321
int size()
Definition Vector.h:178
@ ATRAC3
Sony ATRAC3 (the tag is called SONY_SCX in some lists)
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition LMSEchoCancellationStream.h:6