2 * Copyright (C) 2013 nu774
3 * For conditions of distribution and use, see copyright notice in COPYING
17 #include "caf_reader.h"
20 typedef struct caf_reader_t
{
21 pcm_reader_vtbl_t
*vtbl
;
22 pcm_sample_description_t sample_format
;
27 aacenc_tag_callback_t tag_callback
;
32 static const pcm_sample_description_t
*caf_get_format(pcm_reader_t
*reader
)
34 return &((caf_reader_t
*)reader
)->sample_format
;
37 static int64_t caf_get_length(pcm_reader_t
*reader
)
39 return ((caf_reader_t
*)reader
)->length
;
42 static int64_t caf_get_position(pcm_reader_t
*reader
)
44 return ((caf_reader_t
*)reader
)->position
;
47 static void caf_teardown(pcm_reader_t
**reader
)
54 uint32_t caf_next_chunk(caf_reader_t
*reader
, int64_t *chunk_size
)
57 if (pcm_scanb(&reader
->io
, "LQ", &fcc
, chunk_size
) == 2)
63 int caf_desc(caf_reader_t
*reader
, int64_t chunk_size
)
66 uint32_t mFormatID
, mFormatFlags
, mBytesPerPacket
, mFramesPerPacket
,
67 mChannelsPerFrame
, mBitsPerChannel
;
68 pcm_sample_description_t
*desc
= &reader
->sample_format
;
70 ENSURE(chunk_size
>= 32);
71 TRY_IO(pcm_scanb(&reader
->io
, "QLLLLLL", &mSampleRate
, &mFormatID
,
72 &mFormatFlags
, &mBytesPerPacket
, &mFramesPerPacket
,
73 &mChannelsPerFrame
, &mBitsPerChannel
) != 7);
75 ENSURE(mFormatID
== M4AF_FOURCC('l','p','c','m'));
76 ENSURE(mSampleRate
&& mBytesPerPacket
&&
77 mChannelsPerFrame
>= 1 && mChannelsPerFrame
<= 8 &&
78 mBitsPerChannel
&& mFramesPerPacket
== 1 &&
79 mBytesPerPacket
% mChannelsPerFrame
== 0 &&
80 mBytesPerPacket
>= mChannelsPerFrame
* ((mBitsPerChannel
+ 7) / 8));
82 desc
->sample_rate
= mSampleRate
;
83 desc
->bits_per_channel
= mBitsPerChannel
;
84 desc
->bytes_per_frame
= mBytesPerPacket
;
85 desc
->channels_per_frame
= mChannelsPerFrame
;
87 switch (mFormatFlags
) {
88 case 0: desc
->sample_type
= PCM_TYPE_SINT_BE
; break;
89 case 1: desc
->sample_type
= PCM_TYPE_FLOAT_BE
; break;
90 case 2: desc
->sample_type
= PCM_TYPE_SINT
; break;
91 case 3: desc
->sample_type
= PCM_TYPE_FLOAT
; break;
95 TRY_IO(pcm_skip(&reader
->io
, chunk_size
- 32));
102 int caf_info(caf_reader_t
*reader
, int64_t chunk_size
)
104 char *buf
, *key
, *val
, *end
;
107 if (chunk_size
< 4 || (buf
= malloc(chunk_size
)) == 0)
109 pcm_read(&reader
->io
, buf
, chunk_size
);
111 end
= buf
+ chunk_size
;
113 if ((val
= key
+ strlen(key
) + 1) < end
) {
115 if (reader
->tag_callback
)
116 reader
->tag_callback(reader
->tag_ctx
, key
, val
, len
);
119 } while (key
< end
&& val
< end
);
121 if (reader
->tag_callback
)
122 reader
->tag_callback(reader
->tag_ctx
, 0, 0, 0);
128 int caf_read_frames(pcm_reader_t
*preader
, void *buffer
, unsigned nframes
)
131 unsigned i
, j
, nbytes
;
132 caf_reader_t
*reader
= (caf_reader_t
*)preader
;
133 unsigned bpf
= reader
->sample_format
.bytes_per_frame
;
134 unsigned nchannels
= reader
->sample_format
.channels_per_frame
;
135 unsigned bpc
= bpf
/ nchannels
;
136 uint8_t tmp
[64]; /* enough room for maximum bpf: 8ch float64 */
138 uint8_t *chanmap
= reader
->chanmap
;
140 if (nframes
> reader
->length
- reader
->position
)
141 nframes
= reader
->length
- reader
->position
;
142 nbytes
= nframes
* bpf
;
144 if ((rc
= pcm_read(&reader
->io
, buffer
, nbytes
)) < 0)
147 for (bp
= buffer
, i
= 0; i
< nframes
; ++i
, bp
+= bpf
) {
148 memcpy(tmp
, bp
, bpf
);
149 for (j
= 0; j
< nchannels
; ++j
)
150 memcpy(bp
+ bpc
* j
, tmp
+ bpc
* chanmap
[j
], bpc
);
152 reader
->position
+= nframes
;
155 /* fetch info after data chunk */
158 while ((fcc
= caf_next_chunk(reader
, &chunk_size
)) != 0) {
159 if (fcc
== M4AF_FOURCC('i','n','f','o'))
160 TRY_IO(caf_info(reader
, chunk_size
));
162 TRY_IO(pcm_skip(&reader
->io
, chunk_size
));
171 int caf_parse(caf_reader_t
*reader
, int64_t *data_length
)
179 TRY_IO(pcm_read32be(&reader
->io
, &fcc
));
180 ENSURE(fcc
== M4AF_FOURCC('c','a','f','f'));
181 TRY_IO(pcm_skip(&reader
->io
, 4)); /* mFileVersion, mFileFlags */
183 while ((fcc
= caf_next_chunk(reader
, &chunk_size
)) != 0) {
184 if (fcc
== M4AF_FOURCC('d','e','s','c'))
185 TRY_IO(caf_desc(reader
, chunk_size
));
186 else if (fcc
== M4AF_FOURCC('i','n','f','o'))
187 TRY_IO(caf_info(reader
, chunk_size
));
188 else if (fcc
== M4AF_FOURCC('c','h','a','n')) {
189 ENSURE(reader
->sample_format
.channels_per_frame
);
190 if (apple_chan_chunk(&reader
->io
, chunk_size
,
191 &reader
->sample_format
, reader
->chanmap
) < 0)
193 } else if (fcc
== M4AF_FOURCC('d','a','t','a')) {
194 TRY_IO(pcm_skip(&reader
->io
, 4)); /* mEditCount */
195 *data_length
= (chunk_size
== ~0ULL) ? chunk_size
: chunk_size
- 4;
196 reader
->data_offset
= pcm_tell(&reader
->io
);
199 TRY_IO(pcm_skip(&reader
->io
, chunk_size
));
201 ENSURE(reader
->sample_format
.channels_per_frame
);
202 ENSURE(fcc
== M4AF_FOURCC('d','a','t','a'));
208 static pcm_reader_vtbl_t caf_vtable
= {
216 pcm_reader_t
*caf_open(pcm_io_context_t
*io
,
217 aacenc_tag_callback_t tag_callback
, void *tag_ctx
)
219 caf_reader_t
*reader
= 0;
223 if ((reader
= calloc(1, sizeof(caf_reader_t
))) == 0)
225 memcpy(&reader
->io
, io
, sizeof(pcm_io_context_t
));
226 reader
->tag_callback
= tag_callback
;
227 reader
->tag_ctx
= tag_ctx
;
228 memcpy(reader
->chanmap
, "\000\001\002\003\004\005\006\007", 8);
230 if (caf_parse(reader
, &data_length
) < 0) {
234 bpf
= reader
->sample_format
.bytes_per_frame
;
236 /* CAF uses -1 to indicate "unknown size" */
237 if (data_length
< 0 || data_length
% bpf
)
238 reader
->length
= INT64_MAX
;
240 reader
->length
= data_length
/ bpf
;
242 if (reader
->length
== INT64_MAX
) {
243 if (pcm_seek(&reader
->io
, 0, SEEK_END
) >= 0) {
244 int64_t size
= pcm_tell(&reader
->io
);
246 reader
->length
= (size
- reader
->data_offset
) / bpf
;
247 pcm_seek(&reader
->io
, reader
->data_offset
, SEEK_SET
);
250 reader
->vtbl
= &caf_vtable
;
251 return (pcm_reader_t
*)reader
;