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(pcm_io_context_t
*io
, void *buffer
, uint32_t size
)
28 rc
= io
->vtbl
->read(io
->cookie
, buffer
, size
- count
);
31 } while (rc
> 0 && count
< size
);
32 return count
> 0 ? count
: rc
;
35 int pcm_skip(pcm_io_context_t
*io
, int64_t count
)
39 pcm_io_vtbl_t
*vp
= io
->vtbl
;
41 if (count
== 0 || pcm_seek(io
, count
, SEEK_CUR
) >= 0)
44 if ((rc
= vp
->read(io
->cookie
, buff
, count
> 8192 ? 8192 : count
)) > 0)
46 } while (rc
> 0 && count
> 0);
48 return count
== 0 ? 0 : -1;
51 int pcm_read16le(pcm_io_context_t
*io
, uint16_t *value
)
53 if (pcm_read(io
, value
, 2) == 2) {
54 *value
= m4af_ltoh16(*value
);
60 int pcm_read16be(pcm_io_context_t
*io
, uint16_t *value
)
62 if (pcm_read(io
, value
, 2) == 2) {
63 *value
= m4af_btoh16(*value
);
69 int pcm_read32le(pcm_io_context_t
*io
, uint32_t *value
)
71 if (pcm_read(io
, value
, 4) == 4) {
72 *value
= m4af_ltoh32(*value
);
78 int pcm_read32be(pcm_io_context_t
*io
, uint32_t *value
)
80 if (pcm_read(io
, value
, 4) == 4) {
81 *value
= m4af_btoh32(*value
);
87 int pcm_read64le(pcm_io_context_t
*io
, uint64_t *value
)
89 if (pcm_read(io
, value
, 8) == 8) {
90 *value
= m4af_ltoh64(*value
);
96 int pcm_read64be(pcm_io_context_t
*io
, uint64_t *value
)
98 if (pcm_read(io
, value
, 8) == 8) {
99 *value
= m4af_btoh64(*value
);
105 int pcm_scanl(pcm_io_context_t
*io
, const char *fmt
, ...)
111 while ((c
= *fmt
++)) {
114 TRY_IO(pcm_read16le(io
, va_arg(ap
, uint16_t*)));
118 TRY_IO(pcm_read32le(io
, va_arg(ap
, uint32_t*)));
122 TRY_IO(pcm_read64le(io
, va_arg(ap
, uint64_t*)));
132 int pcm_scanb(pcm_io_context_t
*io
, const char *fmt
, ...)
138 while ((c
= *fmt
++)) {
141 TRY_IO(pcm_read16be(io
, va_arg(ap
, uint16_t*)));
145 TRY_IO(pcm_read32be(io
, va_arg(ap
, uint32_t*)));
149 TRY_IO(pcm_read64be(io
, va_arg(ap
, uint64_t*)));
160 int channel_compare(const void *a
, const void *b
)
162 return (*(const uint8_t **)a
)[0] - (*(const uint8_t **)b
)[0];
165 void apple_translate_channel_labels(uint8_t *channels
, unsigned n
)
168 char *has_side
= strpbrk((char*)channels
, "\x0A\x0B");
170 for (i
= 0; i
< n
; ++i
) {
171 switch (channels
[i
]) {
172 case kAudioChannelLabel_LeftSurround
:
173 case kAudioChannelLabel_RightSurround
:
174 if (!has_side
) channels
[i
] += 5; // map to SL/SR
176 case kAudioChannelLabel_RearSurroundLeft
:
177 case kAudioChannelLabel_RearSurroundRight
:
178 if (!has_side
) channels
[i
] -= 28; // map to BL/BR
180 case kAudioChannelLabel_Mono
:
181 channels
[i
] = kAudioChannelLabel_Center
;
187 int apple_chan_chunk(pcm_io_context_t
*io
, uint32_t chunk_size
,
188 pcm_sample_description_t
*fmt
, uint8_t *mapping
)
191 * Although FDK encoder supports upto 5.1ch, we handle upto
194 uint32_t i
, mChannelLayoutTag
, mChannelBitmap
, mNumberChannelDescriptions
;
196 const uint32_t nchannels
= fmt
->channels_per_frame
;
197 uint8_t channels
[9] = { 0 };
198 uint8_t *index
[8] = { 0 };
199 const char *layout
= 0;
201 ENSURE(chunk_size
>= 12);
202 TRY_IO(pcm_scanb(io
, "LLL", &mChannelLayoutTag
, &mChannelBitmap
,
203 &mNumberChannelDescriptions
) != 3);
205 switch (mChannelLayoutTag
) {
206 case kAudioChannelLayoutTag_UseChannelBitmap
:
207 ENSURE(bitcount(mask
) == nchannels
);
208 TRY_IO(pcm_skip(io
, chunk_size
- 12));
209 fmt
->channel_mask
= mChannelBitmap
;
210 for (i
= 0; i
< nchannels
; ++i
)
213 case kAudioChannelLayoutTag_UseChannelDescriptions
:
214 ENSURE(mNumberChannelDescriptions
== nchannels
);
215 ENSURE(chunk_size
>= 12 + nchannels
* 20);
216 for (i
= 0; i
< mNumberChannelDescriptions
; ++i
) {
217 uint32_t mChannelLabel
;
218 TRY_IO(pcm_read32be(io
, &mChannelLabel
));
219 ENSURE(mChannelLabel
&& mChannelLabel
<= 0xff);
220 channels
[i
] = mChannelLabel
;
221 TRY_IO(pcm_skip(io
, 16));
223 TRY_IO(pcm_skip(io
, chunk_size
- 12 - nchannels
* 20));
224 apple_translate_channel_labels(channels
, nchannels
);
225 for (i
= 0; i
< nchannels
; ++i
)
226 if (channels
[i
] > kAudioChannelLabel_TopBackLeft
)
230 ENSURE((mChannelLayoutTag
& 0xffff) == nchannels
);
231 TRY_IO(pcm_skip(io
, chunk_size
- 12));
233 switch (mChannelLayoutTag
) {
235 case kAudioChannelLayoutTag_Mono
:
236 layout
= "\x03"; break;
238 case kAudioChannelLayoutTag_AC3_1_0_1
:
239 layout
= "\x03\x04"; break;
241 case kAudioChannelLayoutTag_Stereo
:
242 case kAudioChannelLayoutTag_MatrixStereo
:
243 case kAudioChannelLayoutTag_Binaural
:
244 layout
= "\x01\x02"; break;
246 case kAudioChannelLayoutTag_DVD_4
:
247 layout
= "\x01\x02\x04"; break;
249 case kAudioChannelLayoutTag_MPEG_3_0_A
:
250 layout
= "\x01\x02\x03"; break;
251 case kAudioChannelLayoutTag_AC3_3_0
:
252 layout
= "\x01\x03\x02"; break;
253 case kAudioChannelLayoutTag_MPEG_3_0_B
:
254 layout
= "\x03\x01\x02"; break;
255 case kAudioChannelLayoutTag_ITU_2_1
:
256 layout
= "\x01\x02\x09"; break;
258 case kAudioChannelLayoutTag_DVD_10
:
259 layout
= "\x01\x02\x03\x04"; break;
260 case kAudioChannelLayoutTag_AC3_3_0_1
:
261 layout
= "\x01\x03\x02\x04"; break;
262 case kAudioChannelLayoutTag_DVD_5
:
263 layout
= "\x01\x02\x04\x09"; break;
264 case kAudioChannelLayoutTag_AC3_2_1_1
:
265 layout
= "\x01\x02\x09\x04"; break;
267 case kAudioChannelLayoutTag_Quadraphonic
:
268 case kAudioChannelLayoutTag_ITU_2_2
:
269 layout
= "\x01\x02\x0A\x0B"; break;
270 case kAudioChannelLayoutTag_MPEG_4_0_A
:
271 layout
= "\x01\x02\x03\x09"; break;
272 case kAudioChannelLayoutTag_MPEG_4_0_B
:
273 layout
= "\x03\x01\x02\x09"; break;
274 case kAudioChannelLayoutTag_AC3_3_1
:
275 layout
= "\x01\x03\x02\x09"; break;
277 case kAudioChannelLayoutTag_DVD_6
:
278 layout
= "\x01\x02\x04\x0A\x0B"; break;
279 case kAudioChannelLayoutTag_DVD_18
:
280 layout
= "\x01\x02\x0A\x0B\x04"; break;
281 case kAudioChannelLayoutTag_DVD_11
:
282 layout
= "\x01\x02\x03\x04\x09"; break;
283 case kAudioChannelLayoutTag_AC3_3_1_1
:
284 layout
= "\x01\x03\x02\x09\x04"; break;
286 case kAudioChannelLayoutTag_MPEG_5_0_A
:
287 layout
= "\x01\x02\x03\x0A\x0B"; break;
288 case kAudioChannelLayoutTag_Pentagonal
:
289 case kAudioChannelLayoutTag_MPEG_5_0_B
:
290 layout
= "\x01\x02\x0A\x0B\x03"; break;
291 case kAudioChannelLayoutTag_MPEG_5_0_C
:
292 layout
= "\x01\x03\x02\x0A\x0B"; break;
293 case kAudioChannelLayoutTag_MPEG_5_0_D
:
294 layout
= "\x03\x01\x02\x0A\x0B"; break;
296 case kAudioChannelLayoutTag_MPEG_5_1_A
:
297 layout
= "\x01\x02\x03\x04\x0A\x0B"; break;
298 case kAudioChannelLayoutTag_MPEG_5_1_B
:
299 layout
= "\x01\x02\x0A\x0B\x03\x04"; break;
300 case kAudioChannelLayoutTag_MPEG_5_1_C
:
301 layout
= "\x01\x03\x02\x0A\x0B\x04"; break;
302 case kAudioChannelLayoutTag_MPEG_5_1_D
:
303 layout
= "\x03\x01\x02\x0A\x0B\x04"; break;
305 case kAudioChannelLayoutTag_Hexagonal
:
306 case kAudioChannelLayoutTag_AudioUnit_6_0
:
307 layout
= "\x01\x02\x0A\x0B\x03\x09"; break;
308 case kAudioChannelLayoutTag_AAC_6_0
:
309 layout
= "\x03\x01\x02\x0A\x0B\x09"; break;
311 case kAudioChannelLayoutTag_MPEG_6_1_A
:
312 layout
= "\x01\x02\x03\x04\x0A\x0B\x09"; break;
313 case kAudioChannelLayoutTag_AAC_6_1
:
314 layout
= "\x03\x01\x02\x0A\x0B\x09\x04"; break;
316 case kAudioChannelLayoutTag_AudioUnit_7_0
:
317 layout
= "\x01\x02\x0A\x0B\x03\x05\x06"; break;
318 case kAudioChannelLayoutTag_AudioUnit_7_0_Front
:
319 layout
= "\x01\x02\x0A\x0B\x03\x07\x08"; break;
320 case kAudioChannelLayoutTag_AAC_7_0
:
321 layout
= "\x03\x01\x02\x0A\x0B\x05\x06"; break;
323 case kAudioChannelLayoutTag_MPEG_7_1_A
:
324 layout
= "\x01\x02\x03\x04\x0A\x0B\x07\x08"; break;
325 case kAudioChannelLayoutTag_MPEG_7_1_B
:
326 layout
= "\x03\x07\x08\x01\x02\x05\x06\x04"; break;
327 case kAudioChannelLayoutTag_MPEG_7_1_C
:
328 layout
= "\x01\x02\x03\x04\x0A\x0B\x05\x06"; break;
329 case kAudioChannelLayoutTag_Emagic_Default_7_1
:
330 layout
= "\x01\x02\x0A\x0B\x03\x04\x07\x08"; break;
332 case kAudioChannelLayoutTag_Octagonal
:
333 layout
= "\x01\x02\x05\x06\x03\x09\x0A\x0B"; break;
334 case kAudioChannelLayoutTag_AAC_Octagonal
:
335 layout
= "\x03\x01\x02\x0A\x0B\x05\x06\x09"; break;
339 strcpy((char*)channels
, layout
);
342 for (i
= 0; i
< nchannels
; ++i
)
343 mask
|= 1 << (channels
[i
] - 1);
344 fmt
->channel_mask
= mask
;
345 ENSURE(bitcount(mask
) == nchannels
);
347 for (i
= 0; i
< nchannels
; ++i
)
348 index
[i
] = channels
+ i
;
349 qsort(index
, nchannels
, sizeof(char*), channel_compare
);
350 for (i
= 0; i
< nchannels
; ++i
)
351 mapping
[i
] = index
[i
] - channels
;