arduino-audio-tools
Loading...
Searching...
No Matches
CodecATRAC.h
Go to the documentation of this file.
1#pragma once
2
3#include <string.h>
4
5#include <algorithm>
6
7#include "ATRACDecoder.h" // https://github.com/pschatzmann/codec-atrac
9
10namespace audio_tools {
11
40 public:
41 DecoderATRAC(ATRACType type = ATRAC3) { this->type = type; }
43
44 const char *mime() override { return "audio/atrac"; }
45
47 void setType(ATRACType type) {
48 if (is_open) {
49 LOGE("setType() must be called before begin()");
50 return;
51 }
52 this->type = type;
53 }
54
55 ATRACType getType() { return type; }
56
58 void setBlockSize(int blockSize) override { block_align = blockSize; }
59
61 void setExtraData(const uint8_t *data, size_t len) override {
62 setCodecConfig(data, len);
63 }
64
69 switch (type) {
70 case ATRAC3:
72 case ATRAC3PLUS:
74 case ATRAC9:
76 default:
78 }
79 }
80
82 bool setCodecConfig(const uint8_t *data, size_t len) override {
83 extradata.resize(len);
84 if (len > 0) memcpy(extradata.data(), data, len);
85 return true;
86 }
87
90 bool begin() override {
93 }
94
96 bool begin(ATRACType type, int sampleRate, int channels, int blockAlign,
97 const uint8_t *extra = nullptr, size_t extraSize = 0) {
98 TRACED();
99 end();
100 this->type = type;
101 ATRACConfig cfg;
102 cfg.sampleRate = sampleRate;
103 cfg.channels = channels;
104 cfg.blockAlign = blockAlign;
105 cfg.extradata = extra;
106 cfg.extradataSize = extraSize;
107 p_decoder = new ATRACDecoder(type);
108 if (p_decoder == nullptr || !p_decoder->begin(cfg)) {
109 LOGE("ATRAC decoder could not be opened (type: %d)", (int)type);
110 end();
111 return false;
112 }
113
114 // ATRAC9 provides the block align via the extradata
115 frame_size = blockAlign;
116 if (frame_size <= 0 && type == ATRAC9) {
117 frame_size = atrac9FrameSize(extra, extraSize);
118 }
119 if (frame_size <= 0) {
120 LOGE("ATRAC block size is not defined");
121 end();
122 return false;
123 }
125 frame_pos = 0;
126
127 int ch = p_decoder->channels();
130
131 AudioInfo tmp(p_decoder->sampleRate(), ch, 16);
132 setAudioInfo(tmp);
133 LOGI("ATRAC %s: %d Hz, %d channels, %d bytes/frame", p_decoder->codecName(),
134 (int)tmp.sample_rate, (int)tmp.channels, frame_size);
135 is_open = true;
136 return true;
137 }
138
139 void end() override {
140 if (p_decoder != nullptr) {
141 delete p_decoder;
142 p_decoder = nullptr;
143 }
144 is_open = false;
145 frame_pos = 0;
146 }
147
149 void flush() {
150 frame_pos = 0;
151 if (p_decoder != nullptr) p_decoder->flush();
152 }
153
155 size_t write(const uint8_t *data, size_t len) override {
156 if (!is_open) return 0;
157 size_t pos = 0;
158 while (pos < len) {
159 size_t n = std::min(len - pos, (size_t)frame_size - frame_pos);
160 memcpy(frame.data() + frame_pos, data + pos, n);
161 frame_pos += n;
162 pos += n;
163 if (frame_pos == (size_t)frame_size) {
164 decodeFrame();
165 frame_pos = 0;
166 }
167 }
168 return len;
169 }
170
171 operator bool() override { return is_open; }
172
174 int frameSize() { return frame_size; }
175
176 protected:
178 static const int MAX_SAMPLES_PER_FRAME = 2048;
179 ATRACDecoder *p_decoder = nullptr;
180 ATRACType type = ATRAC3;
184 size_t frame_pos = 0;
185 int frame_size = 0;
186 int block_align = 0;
187 bool is_open = false;
188
189 void decodeFrame() {
190 int samples =
191 p_decoder->decode(frame.data(), frame.size(), pcm.data(), pcm.size());
192 if (samples <= 0) {
193 // the first frame(s) of some streams do not produce any output
194 LOGD("ATRAC decode: no output (error: %d)", p_decoder->lastError());
195 return;
196 }
197 if (p_print == nullptr) return;
198 size_t open = samples * p_decoder->channels() * sizeof(int16_t);
199 uint8_t *ptr = (uint8_t *)pcm.data();
200 while (open > 0) {
201 size_t written = p_print->write(ptr, open);
202 if (written == 0) {
203 LOGE("write error: %d bytes lost", (int)open);
204 break;
205 }
206 ptr += written;
207 open -= written;
208 }
209 }
210
213 static int atrac9FrameSize(const uint8_t *extra, size_t size) {
214 if (extra == nullptr || size != 12) return 0;
215 const uint8_t *e = extra + 4;
216 int frame_size = ((e[2] << 3) | (e[3] >> 5)) + 1;
217 int superframe = (e[3] >> 3) & 0x3;
218 return frame_size << superframe;
219 }
220};
221
222} // namespace audio_tools
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
virtual size_t write(const uint8_t *data, size_t len)
Definition Arduino.h:120
Extended AudioDecoder interface to support block size configuration.
Definition AudioCodecsBase.h:133
AudioInfo info
Definition AudioCodecsBase.h:80
void setAudioInfo(AudioInfo from) override
for most decoders this is not needed
Definition AudioCodecsBase.h:32
Print * p_print
Definition AudioCodecsBase.h:79
ATRAC decoder (ATRAC1, ATRAC3, ATRAC3+ and ATRAC9) which converts the raw ATRAC frames into 16 bit PC...
Definition CodecATRAC.h:39
bool is_open
Definition CodecATRAC.h:187
int frameSize()
Size of one ATRAC frame in bytes.
Definition CodecATRAC.h:174
Vector< int16_t > pcm
Definition CodecATRAC.h:183
bool setCodecConfig(const uint8_t *data, size_t len) override
Defines the codec specific header (e.g. the WAV fmt extension)
Definition CodecATRAC.h:82
AudioFormat wavFormat() override
Definition CodecATRAC.h:68
ATRACDecoder * p_decoder
Definition CodecATRAC.h:179
void setBlockSize(int blockSize) override
Defines the size of one ATRAC frame (block align) in bytes.
Definition CodecATRAC.h:58
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
DecoderATRAC(ATRACType type=ATRAC3)
Definition CodecATRAC.h:41
static int atrac9FrameSize(const uint8_t *extra, size_t size)
Definition CodecATRAC.h:213
Vector< uint8_t > extradata
Definition CodecATRAC.h:181
void setExtraData(const uint8_t *data, size_t len) override
Defines the codec specific header (e.g. the WAV fmt extension)
Definition CodecATRAC.h:61
void decodeFrame()
Definition CodecATRAC.h:189
~DecoderATRAC()
Definition CodecATRAC.h:42
bool begin(ATRACType type, int sampleRate, int channels, int blockAlign, const uint8_t *extra=nullptr, size_t extraSize=0)
Starts the decoder with the parameters found in the header of the stream.
Definition CodecATRAC.h:96
void setType(ATRACType type)
Defines the ATRAC variant (must be called before begin())
Definition CodecATRAC.h:47
const char * mime() override
Provides the mime type of the data that is expected by this decoder.
Definition CodecATRAC.h:44
int block_align
Definition CodecATRAC.h:186
ATRACType getType()
Definition CodecATRAC.h:55
ATRACType type
Definition CodecATRAC.h:180
bool begin() override
Definition CodecATRAC.h:90
static const int MAX_SAMPLES_PER_FRAME
ATRAC3+ has the largest frames: 2048 samples per channel.
Definition CodecATRAC.h:178
int frame_size
Definition CodecATRAC.h:185
Vector< uint8_t > frame
Definition CodecATRAC.h:182
void flush()
Drops partial data and resets the decoder state, e.g. after a seek.
Definition CodecATRAC.h:149
size_t frame_pos
Definition CodecATRAC.h:184
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
bool resize(size_t newSize, T value)
Definition Vector.h:266
T * data()
Definition Vector.h:321
int size()
Definition Vector.h:178
AudioFormat
Audio format codes used by Microsoft e.g. in avi or wav files.
Definition AudioFormat.h:21
@ 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
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:56
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:58
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:60