arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
CodecFLACFoxen.h
1#pragma once
2
3#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
4#include "AudioTools/CoreAudio/Buffers.h"
5#include "foxen-flac.h"
6
7namespace audio_tools {
8
9#define FOXEN_IN_BUFFER_SIZE 1024 * 2
10#define FOXEN_OUT_BUFFER_SIZE 1024 * 4
11
20 public:
21 FLACDecoderFoxen() = default;
22
24 FLACDecoderFoxen(int maxBlockSize, int maxChannels,
25 bool convertTo16Bits = true) {
26 is_convert_to_16 = convertTo16Bits;
27 max_block_size = maxBlockSize;
28 max_channels = maxChannels;
29 };
30
32 ~FLACDecoderFoxen() { end(); }
33
34 bool begin() {
35 TRACEI();
36 is_active = false;
37 if (flac == nullptr) {
38 size_t foxen_size = fx_flac_size(max_block_size, max_channels);
39 if (foxen_size > 0) {
40 foxen_data.resize(foxen_size);
41 }
42 if (foxen_data.data() != nullptr) {
43 flac = fx_flac_init(foxen_data.data(), max_block_size, max_channels);
44 }
45 }
46 if (flac != nullptr) {
47 is_active = true;
48 } else {
49 LOGE("not enough memory");
50 if (is_stop_on_error) stop();
51 }
52 if (buffer.size() == 0) {
53 buffer.resize(in_buffer_size);
54 out.resize(FOXEN_OUT_BUFFER_SIZE);
55 }
56
57 return is_active;
58 }
59
60 void end() {
61 TRACEI();
62 if (flac != nullptr) {
63 flush();
64 foxen_data.resize(0);
65 flac = nullptr;
66 }
67 buffer.resize(0);
68 out.resize(0);
69 is_active = false;
70 }
71
72 size_t write(const uint8_t *data, size_t len) override {
73 LOGD("write: %d", len);
74 // no processing if not active
75 if (!is_active) return 0;
76
77 size_t result = buffer.writeArray(data, len);
78 LOGD("buffer availabe: %d", buffer.available());
79
80 while (buffer.available() > 0) {
81 if (!decode()) break;
82 }
83
84 // if the buffer is full we could not decode anything
85 if (buffer.available() == buffer.size()) {
86 LOGE("Decoder did not consume any data");
87 if (is_stop_on_error) stop();
88 }
89
90 LOGD("write: %d -> %d", len, result);
91 return result;
92 }
93
94 void flush() { decode(); }
95
96 operator bool() override { return is_active; }
97
99 void setInBufferSize(int size){
100 in_buffer_size = size;
101 }
102
104 void setOutBufferSize(int size){
105 out_buffer_size = size;
106 }
107
109 void setMaxBlockSize(int size){
110 max_block_size = size;
111 }
112
114 void setMaxChannels(int ch){
115 max_channels = ch;
116 }
117
119 void set32Bit(bool flag) {
120 is_convert_to_16 = !flag;
121 }
122
123 protected:
124 fx_flac_t *flac = nullptr;
125 SingleBuffer<uint8_t> buffer{0};
126 Vector<int32_t> out;
127 Vector<uint8_t> foxen_data{0};
128 bool is_active = false;
129 bool is_convert_to_16 = true;
130 bool is_stop_on_error = true;
131 int bits_eff = 0;
132 int max_block_size = 5 * 1024;
133 int max_channels = 2;
134 int in_buffer_size = FOXEN_IN_BUFFER_SIZE;
135 int out_buffer_size = FOXEN_OUT_BUFFER_SIZE;
136
137 bool decode() {
138 TRACED();
139 if (flac == nullptr) return false;
140 uint32_t out_len = out.size();
141 uint32_t buf_len = buffer.available();
142 uint32_t buf_len_result = buf_len;
143 int rc = fx_flac_process(flac, buffer.data(), &buf_len_result, out.data(),
144 &out_len);
145 // assert(out_len <= FOXEN_OUT_BUFFER_SIZE);
146
147 switch (rc) {
148 case FLAC_END_OF_METADATA: {
149 processMetadata();
150 } break;
151
152 case FLAC_ERR: {
153 LOGE("FLAC decoder in error state!");
154 if (is_stop_on_error) stop();
155 } break;
156
157 default: {
158 if (out_len > 0) {
159 LOGD("Providing data: %d samples", out_len);
160 if (is_convert_to_16) {
161 write16BitData(out_len);
162 } else {
163 write32BitData(out_len);
164 }
165 }
166 } break;
167 }
168 LOGD("processed: %d bytes of %d -> %d samples", buf_len_result, buf_len,
169 out_len);
170 // removed processed bytes from buffer
171 buffer.clearArray(buf_len_result);
172 return buf_len_result > 0 || out_len > 0;
173 }
174
175 void write32BitData(int out_len) {
176 TRACED();
177 // write the result to the output destination
178 writeBlocking(p_print, (uint8_t *)out.data(), out_len * sizeof(int32_t));
179 }
180
181 void write16BitData(int out_len) {
182 TRACED();
183 // in place convert to 16 bits
184 int16_t *out16 = (int16_t *)out.data();
185 for (int j = 0; j < out_len; j++) {
186 out16[j] = out.data()[j] >> 16; // 65538;
187 }
188 // write the result to the output destination
189 LOGI("writeBlocking: %d", out_len * sizeof(int16_t));
190 writeBlocking(p_print, (uint8_t *)out.data(), out_len * sizeof(int16_t));
191 }
192
193 void processMetadata() {
194 bits_eff = fx_flac_get_streaminfo(flac, FLAC_KEY_SAMPLE_SIZE);
195 int info_blocksize = fx_flac_get_streaminfo(flac, FLAC_KEY_MAX_BLOCK_SIZE);
196
197 LOGI("bits: %d", bits_eff);
198 LOGI("blocksize: %d", info_blocksize);
199 // assert(bits_eff == 32);
200 info.sample_rate = fx_flac_get_streaminfo(flac, FLAC_KEY_SAMPLE_RATE);
201 info.channels = fx_flac_get_streaminfo(flac, FLAC_KEY_N_CHANNELS);
202 info.bits_per_sample = is_convert_to_16 ? 16 : bits_eff;
203 info.logInfo();
204 if (info.channels > max_channels) {
205 LOGE("max channels too low: %d -> %d", max_channels, info.channels);
206 if (is_stop_on_error) stop();
207 }
208 if (info_blocksize > max_block_size) {
209 LOGE("max channels too low: %d -> %d", max_block_size, info_blocksize);
210 if (is_stop_on_error) stop();
211 }
212 notifyAudioChange(info);
213 }
214};
215
216} // namespace audio_tools
Decoding of encoded audio into PCM data.
Definition AudioCodecsBase.h:18
virtual int writeArray(const T data[], int len)
Fills the buffer data.
Definition Buffers.h:59
Foxen FLAC Decoder.
Definition CodecFLACFoxen.h:19
void set32Bit(bool flag)
Select between 16 and 32 bit output: the default is 16 bits.
Definition CodecFLACFoxen.h:119
void setMaxChannels(int ch)
Defines the maximum number of channels: drives the buffer allocation.
Definition CodecFLACFoxen.h:114
void setOutBufferSize(int size)
Defines the number of 32 bit samples for providing the result (default is 4k)
Definition CodecFLACFoxen.h:104
~FLACDecoderFoxen()
Destructor - calls end();.
Definition CodecFLACFoxen.h:32
void setMaxBlockSize(int size)
Defines the maximum FLAC blocksize: drives the buffer allocation.
Definition CodecFLACFoxen.h:109
void setInBufferSize(int size)
Defines the input buffer size (default is 2k)
Definition CodecFLACFoxen.h:99
FLACDecoderFoxen(int maxBlockSize, int maxChannels, bool convertTo16Bits=true)
Default Constructor.
Definition CodecFLACFoxen.h:24
A simple Buffer implementation which just uses a (dynamically sized) array.
Definition Buffers.h:175
int available() override
provides the number of entries that are available to read
Definition Buffers.h:227
T * data()
Provides address of actual data.
Definition Buffers.h:261
int clearArray(int len) override
consumes len bytes and moves current data to the beginning
Definition Buffers.h:237
void stop()
Public generic methods.
Definition AudioRuntime.h:14
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:59