2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
18 #include "pcm_reader.h"
19 #include "m4af_endian.h"
22 int pcm_read_frames(pcm_reader_t
*r
, void *data
, unsigned nframes
)
27 unsigned bpf
= pcm_get_format(r
)->bytes_per_frame
;
30 n
= r
->vtbl
->read_frames(r
, bp
, nframes
- count
);
35 } while (n
> 0 && count
< nframes
);
39 int pcm_read(pcm_io_context_t
*io
, void *buffer
, uint32_t size
)
46 rc
= io
->vtbl
->read(io
->cookie
, bp
, size
- count
);
51 } while (rc
> 0 && count
< size
);
52 return count
> 0 ? count
: rc
;
55 int pcm_skip(pcm_io_context_t
*io
, int64_t count
)
59 pcm_io_vtbl_t
*vp
= io
->vtbl
;
61 if (count
== 0 || pcm_seek(io
, count
, SEEK_CUR
) >= 0)
64 if ((rc
= vp
->read(io
->cookie
, buff
, count
> 8192 ? 8192 : count
)) > 0)
66 } while (rc
> 0 && count
> 0);
68 return count
== 0 ? 0 : -1;
71 int pcm_read16le(pcm_io_context_t
*io
, uint16_t *value
)
73 if (pcm_read(io
, value
, 2) == 2) {
74 *value
= m4af_ltoh16(*value
);
80 int pcm_read16be(pcm_io_context_t
*io
, uint16_t *value
)
82 if (pcm_read(io
, value
, 2) == 2) {
83 *value
= m4af_btoh16(*value
);
89 int pcm_read32le(pcm_io_context_t
*io
, uint32_t *value
)
91 if (pcm_read(io
, value
, 4) == 4) {
92 *value
= m4af_ltoh32(*value
);
98 int pcm_read32be(pcm_io_context_t
*io
, uint32_t *value
)
100 if (pcm_read(io
, value
, 4) == 4) {
101 *value
= m4af_btoh32(*value
);
107 int pcm_read64le(pcm_io_context_t
*io
, uint64_t *value
)
109 if (pcm_read(io
, value
, 8) == 8) {
110 *value
= m4af_ltoh64(*value
);
116 int pcm_read64be(pcm_io_context_t
*io
, uint64_t *value
)
118 if (pcm_read(io
, value
, 8) == 8) {
119 *value
= m4af_btoh64(*value
);
125 int pcm_scanl(pcm_io_context_t
*io
, const char *fmt
, ...)
131 while ((c
= *fmt
++)) {
134 TRY_IO(pcm_read16le(io
, va_arg(ap
, uint16_t*)));
138 TRY_IO(pcm_read32le(io
, va_arg(ap
, uint32_t*)));
142 TRY_IO(pcm_read64le(io
, va_arg(ap
, uint64_t*)));
152 int pcm_scanb(pcm_io_context_t
*io
, const char *fmt
, ...)
158 while ((c
= *fmt
++)) {
161 TRY_IO(pcm_read16be(io
, va_arg(ap
, uint16_t*)));
165 TRY_IO(pcm_read32be(io
, va_arg(ap
, uint32_t*)));
169 TRY_IO(pcm_read64be(io
, va_arg(ap
, uint64_t*)));
180 int channel_compare(const void *a
, const void *b
)
182 return (*(const uint8_t **)a
)[0] - (*(const uint8_t **)b
)[0];
185 void apple_translate_channel_labels(uint8_t *channels
, unsigned n
)
188 char *has_side
= strpbrk((char*)channels
, "\x0A\x0B");
190 for (i
= 0; i
< n
; ++i
) {
191 switch (channels
[i
]) {
192 case kAudioChannelLabel_LeftSurround
:
193 case kAudioChannelLabel_RightSurround
:
194 if (!has_side
) channels
[i
] += 5; // map to SL/SR
196 case kAudioChannelLabel_RearSurroundLeft
:
197 case kAudioChannelLabel_RearSurroundRight
:
198 if (!has_side
) channels
[i
] -= 28; // map to BL/BR
200 case kAudioChannelLabel_Mono
:
201 channels
[i
] = kAudioChannelLabel_Center
;
207 int apple_chan_chunk(pcm_io_context_t
*io
, uint32_t chunk_size
,
208 pcm_sample_description_t
*fmt
, uint8_t *mapping
)
211 * Although FDK encoder supports upto 5.1ch, we handle upto
214 uint32_t i
, mChannelLayoutTag
, mChannelBitmap
, mNumberChannelDescriptions
;
216 const uint32_t nchannels
= fmt
->channels_per_frame
;
217 uint8_t channels
[9] = { 0 };
218 uint8_t *index
[8] = { 0 };
219 const char *layout
= 0;
221 ENSURE(chunk_size
>= 12);
222 TRY_IO(pcm_scanb(io
, "LLL", &mChannelLayoutTag
, &mChannelBitmap
,
223 &mNumberChannelDescriptions
) != 3);
225 switch (mChannelLayoutTag
) {
226 case kAudioChannelLayoutTag_UseChannelBitmap
:
227 ENSURE(bitcount(mChannelBitmap
) == nchannels
);
228 TRY_IO(pcm_skip(io
, chunk_size
- 12));
229 fmt
->channel_mask
= mChannelBitmap
;
230 for (i
= 0; i
< nchannels
; ++i
)
233 case kAudioChannelLayoutTag_UseChannelDescriptions
:
234 ENSURE(mNumberChannelDescriptions
== nchannels
);
235 ENSURE(chunk_size
>= 12 + nchannels
* 20);
236 for (i
= 0; i
< mNumberChannelDescriptions
; ++i
) {
237 uint32_t mChannelLabel
;
238 TRY_IO(pcm_read32be(io
, &mChannelLabel
));
239 ENSURE(mChannelLabel
&& mChannelLabel
<= 0xff);
240 channels
[i
] = mChannelLabel
;
241 TRY_IO(pcm_skip(io
, 16));
243 TRY_IO(pcm_skip(io
, chunk_size
- 12 - nchannels
* 20));
244 apple_translate_channel_labels(channels
, nchannels
);
245 for (i
= 0; i
< nchannels
; ++i
)
246 if (channels
[i
] > kAudioChannelLabel_TopBackLeft
)
250 ENSURE((mChannelLayoutTag
& 0xffff) == nchannels
);
251 TRY_IO(pcm_skip(io
, chunk_size
- 12));
253 switch (mChannelLayoutTag
) {
255 case kAudioChannelLayoutTag_Mono
:
256 layout
= "\x03"; break;
258 case kAudioChannelLayoutTag_AC3_1_0_1
:
259 layout
= "\x03\x04"; break;
261 case kAudioChannelLayoutTag_Stereo
:
262 case kAudioChannelLayoutTag_MatrixStereo
:
263 case kAudioChannelLayoutTag_Binaural
:
264 layout
= "\x01\x02"; break;
266 case kAudioChannelLayoutTag_DVD_4
:
267 layout
= "\x01\x02\x04"; break;
269 case kAudioChannelLayoutTag_MPEG_3_0_A
:
270 layout
= "\x01\x02\x03"; break;
271 case kAudioChannelLayoutTag_AC3_3_0
:
272 layout
= "\x01\x03\x02"; break;
273 case kAudioChannelLayoutTag_MPEG_3_0_B
:
274 layout
= "\x03\x01\x02"; break;
275 case kAudioChannelLayoutTag_ITU_2_1
:
276 layout
= "\x01\x02\x09"; break;
278 case kAudioChannelLayoutTag_DVD_10
:
279 layout
= "\x01\x02\x03\x04"; break;
280 case kAudioChannelLayoutTag_AC3_3_0_1
:
281 layout
= "\x01\x03\x02\x04"; break;
282 case kAudioChannelLayoutTag_DVD_5
:
283 layout
= "\x01\x02\x04\x09"; break;
284 case kAudioChannelLayoutTag_AC3_2_1_1
:
285 layout
= "\x01\x02\x09\x04"; break;
287 case kAudioChannelLayoutTag_Quadraphonic
:
288 case kAudioChannelLayoutTag_ITU_2_2
:
289 layout
= "\x01\x02\x0A\x0B"; break;
290 case kAudioChannelLayoutTag_MPEG_4_0_A
:
291 layout
= "\x01\x02\x03\x09"; break;
292 case kAudioChannelLayoutTag_MPEG_4_0_B
:
293 layout
= "\x03\x01\x02\x09"; break;
294 case kAudioChannelLayoutTag_AC3_3_1
:
295 layout
= "\x01\x03\x02\x09"; break;
297 case kAudioChannelLayoutTag_DVD_6
:
298 layout
= "\x01\x02\x04\x0A\x0B"; break;
299 case kAudioChannelLayoutTag_DVD_18
:
300 layout
= "\x01\x02\x0A\x0B\x04"; break;
301 case kAudioChannelLayoutTag_DVD_11
:
302 layout
= "\x01\x02\x03\x04\x09"; break;
303 case kAudioChannelLayoutTag_AC3_3_1_1
:
304 layout
= "\x01\x03\x02\x09\x04"; break;
306 case kAudioChannelLayoutTag_MPEG_5_0_A
:
307 layout
= "\x01\x02\x03\x0A\x0B"; break;
308 case kAudioChannelLayoutTag_Pentagonal
:
309 case kAudioChannelLayoutTag_MPEG_5_0_B
:
310 layout
= "\x01\x02\x0A\x0B\x03"; break;
311 case kAudioChannelLayoutTag_MPEG_5_0_C
:
312 layout
= "\x01\x03\x02\x0A\x0B"; break;
313 case kAudioChannelLayoutTag_MPEG_5_0_D
:
314 layout
= "\x03\x01\x02\x0A\x0B"; break;
316 case kAudioChannelLayoutTag_MPEG_5_1_A
:
317 layout
= "\x01\x02\x03\x04\x0A\x0B"; break;
318 case kAudioChannelLayoutTag_MPEG_5_1_B
:
319 layout
= "\x01\x02\x0A\x0B\x03\x04"; break;
320 case kAudioChannelLayoutTag_MPEG_5_1_C
:
321 layout
= "\x01\x03\x02\x0A\x0B\x04"; break;
322 case kAudioChannelLayoutTag_MPEG_5_1_D
:
323 layout
= "\x03\x01\x02\x0A\x0B\x04"; break;
325 case kAudioChannelLayoutTag_Hexagonal
:
326 case kAudioChannelLayoutTag_AudioUnit_6_0
:
327 layout
= "\x01\x02\x0A\x0B\x03\x09"; break;
328 case kAudioChannelLayoutTag_AAC_6_0
:
329 layout
= "\x03\x01\x02\x0A\x0B\x09"; break;
331 case kAudioChannelLayoutTag_MPEG_6_1_A
:
332 layout
= "\x01\x02\x03\x04\x0A\x0B\x09"; break;
333 case kAudioChannelLayoutTag_AAC_6_1
:
334 layout
= "\x03\x01\x02\x0A\x0B\x09\x04"; break;
336 case kAudioChannelLayoutTag_AudioUnit_7_0
:
337 layout
= "\x01\x02\x0A\x0B\x03\x05\x06"; break;
338 case kAudioChannelLayoutTag_AudioUnit_7_0_Front
:
339 layout
= "\x01\x02\x0A\x0B\x03\x07\x08"; break;
340 case kAudioChannelLayoutTag_AAC_7_0
:
341 layout
= "\x03\x01\x02\x0A\x0B\x05\x06"; break;
343 case kAudioChannelLayoutTag_MPEG_7_1_A
:
344 layout
= "\x01\x02\x03\x04\x0A\x0B\x07\x08"; break;
345 case kAudioChannelLayoutTag_MPEG_7_1_B
:
346 layout
= "\x03\x07\x08\x01\x02\x05\x06\x04"; break;
347 case kAudioChannelLayoutTag_MPEG_7_1_C
:
348 layout
= "\x01\x02\x03\x04\x0A\x0B\x05\x06"; break;
349 case kAudioChannelLayoutTag_Emagic_Default_7_1
:
350 layout
= "\x01\x02\x0A\x0B\x03\x04\x07\x08"; break;
352 case kAudioChannelLayoutTag_Octagonal
:
353 layout
= "\x01\x02\x05\x06\x03\x09\x0A\x0B"; break;
354 case kAudioChannelLayoutTag_AAC_Octagonal
:
355 layout
= "\x03\x01\x02\x0A\x0B\x05\x06\x09"; break;
359 strcpy((char*)channels
, layout
);
362 for (i
= 0; i
< nchannels
; ++i
)
363 mask
|= 1 << (channels
[i
] - 1);
364 fmt
->channel_mask
= mask
;
365 ENSURE(bitcount(mask
) == nchannels
);
367 for (i
= 0; i
< nchannels
; ++i
)
368 index
[i
] = channels
+ i
;
369 qsort(index
, nchannels
, sizeof(char*), channel_compare
);
370 for (i
= 0; i
< nchannels
; ++i
)
371 mapping
[i
] = index
[i
] - channels
;