@@ -29,7 +29,7 @@ class ALACBinaryConfig {
29
29
* https://github.com/pschatzmann/codec-alac. This implementaion is based on
30
30
* https://github.com/macosforge/alac
31
31
* @note Please note that this codec usually needs a container:
32
- * The write() method also expects a complete frame to be written!
32
+ * The write() method expects a complete frame to be written!
33
33
* The decoder also expects to get the config from the encoder, however we have
34
34
* some fallback functionality that uses the AudioInfo and the frame size
35
35
* defined in the constructor.
@@ -38,6 +38,7 @@ class ALACBinaryConfig {
38
38
*/
39
39
class DecoderALAC : public AudioDecoder {
40
40
public:
41
+ // / Default constructor: you can define your own optimized frame size
41
42
DecoderALAC (int frameSize = kALACDefaultFrameSize ) {
42
43
// this is used when setCodecConfig() is not called with encoder info
43
44
setFrameSize (frameSize);
@@ -46,7 +47,6 @@ class DecoderALAC : public AudioDecoder {
46
47
47
48
// define ALACSpecificConfig
48
49
bool setCodecConfig (ALACSpecificConfig config) {
49
- convert (config);
50
50
return setCodecConfig ((uint8_t *)&config, sizeof (config));
51
51
}
52
52
@@ -86,10 +86,15 @@ class DecoderALAC : public AudioDecoder {
86
86
dec.mConfig .bitDepth = from.bits_per_sample ;
87
87
}
88
88
89
-
90
89
// / we expect the write is called for a complete frame!
91
90
size_t write (const uint8_t * encodedFrame, size_t encodedLen) override {
92
91
LOGI (" DecoderALAC::write: %d" , (int )encodedLen);
92
+ // Safety check
93
+ if (!is_init) {
94
+ LOGE (" Decoder not initialized" );
95
+ return 0 ;
96
+ }
97
+
93
98
// Make sure we have the output buffer set up
94
99
if (result_buffer.size () != outputBufferSize ()) {
95
100
result_buffer.resize (outputBufferSize ());
@@ -118,11 +123,11 @@ class DecoderALAC : public AudioDecoder {
118
123
int open = outputSize;
119
124
int processed = 0 ;
120
125
while (open > 0 ) {
121
- int writeSize = MIN (1024 , outputSize );
126
+ int writeSize = MIN (1024 , open );
122
127
size_t written =
123
128
p_print->write (result_buffer.data () + processed, writeSize);
124
129
if (writeSize != written) {
125
- LOGE (" write error: %d -> %d" , outputSize, written);
130
+ LOGE (" write error: %d -> %d" , ( int ) outputSize, ( int ) written);
126
131
}
127
132
open -= written;
128
133
processed += written;
@@ -132,8 +137,11 @@ class DecoderALAC : public AudioDecoder {
132
137
133
138
operator bool () { return true ; }
134
139
140
+ // / Set the default frame size: this will be overwritten if you call
141
+ // / setCodecConfig()
135
142
void setFrameSize (int frames) { dec.mConfig .frameLength = frames; }
136
143
144
+ // / Provides the actual frame size
137
145
int frameSize () { return dec.mConfig .frameLength ; }
138
146
139
147
protected:
@@ -143,7 +151,7 @@ class DecoderALAC : public AudioDecoder {
143
151
struct BitBuffer bits;
144
152
145
153
void setDefaultConfig () {
146
- LOGW (" Setting up default ALAC config" )
154
+ // LOGW("Setting up default ALAC config")
147
155
AudioInfo info = audioInfo ();
148
156
ALACSpecificConfig tmp;
149
157
// Essential parameters for ALAC compression
@@ -174,6 +182,7 @@ class DecoderALAC : public AudioDecoder {
174
182
tmp.maxFrameBytes =
175
183
uncompressedFrameSize + (uncompressedFrameSize / 2 ) + 64 + 50 ;
176
184
185
+ convert (tmp);
177
186
setCodecConfig (tmp);
178
187
}
179
188
@@ -201,6 +210,7 @@ class DecoderALAC : public AudioDecoder {
201
210
*/
202
211
class EncoderALAC : public AudioEncoder {
203
212
public:
213
+ // / Default constructor: you can define your own optimized frame size
204
214
EncoderALAC (int frameSize = kALACDefaultFrameSize ) {
205
215
setFrameSize (frameSize);
206
216
}
@@ -219,10 +229,18 @@ class EncoderALAC : public AudioEncoder {
219
229
enc.SetFrameSize (frame_size);
220
230
int rc = enc.InitializeEncoder (out_format);
221
231
222
- uint32_t inputBufferSize =
223
- frame_size * info.channels * (info.bits_per_sample / 8 );
232
+ // Calculate exact buffer sizes based on frame settings
233
+ uint32_t bytesPerSample = info.bits_per_sample / 8 ;
234
+ uint32_t inputBufferSize = frame_size * info.channels * bytesPerSample;
235
+ // Calculate output buffer size
224
236
uint32_t outputBufferSize = inputBufferSize * 2 ; // Ensure enough space
225
237
238
+ LOGI (
239
+ " ALAC Encoder: frame_size=%d, inputBuf=%d, outputBuf=%d, channels=%d, "
240
+ " bits=%d" ,
241
+ frame_size, inputBufferSize, outputBufferSize, info.channels ,
242
+ info.bits_per_sample );
243
+
226
244
in_buffer.resize (inputBufferSize);
227
245
out_buffer.resize (outputBufferSize);
228
246
is_started = rc == 0 ;
@@ -242,13 +260,13 @@ class EncoderALAC : public AudioEncoder {
242
260
in_buffer.write (data[j]);
243
261
if (in_buffer.isFull ()) {
244
262
// provide max output buffer size
245
- int32_t ioNumBytes = out_buffer .size ();
263
+ int32_t ioNumBytes = in_buffer .size ();
246
264
int rc =
247
265
enc.Encode (input_format, out_format, (uint8_t *)in_buffer.data (),
248
266
out_buffer.data (), &ioNumBytes);
249
267
size_t written = p_print->write (out_buffer.data (), ioNumBytes);
250
268
if (ioNumBytes != written) {
251
- LOGE (" write error: %d -> %d" , ioNumBytes, written);
269
+ LOGE (" write error: %d -> %d" , ( int ) ioNumBytes, ( int ) written);
252
270
}
253
271
in_buffer.reset ();
254
272
}
@@ -270,10 +288,19 @@ class EncoderALAC : public AudioEncoder {
270
288
271
289
operator bool () { return is_started && p_print != nullptr ; }
272
290
291
+ // / Mime type: returns audio/alac
273
292
const char * mime () override { return " audio/alac" ; }
274
293
275
- void setFrameSize (int frames) { frame_size = frames; }
294
+ // / Defines the frame size for the decoder: default is 4096 frames
295
+ void setFrameSize (int frames) {
296
+ if (is_started) {
297
+ LOGE (" Can't change frame size on started encoder" )
298
+ return ;
299
+ }
300
+ frame_size = frames;
301
+ }
276
302
303
+ // / Determins the actually defined number of frames
277
304
int frameSize () { return frame_size; }
278
305
279
306
protected:
0 commit comments