/src/libsndfile/src/caf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | ** Copyright (C) 2005-2017 Erik de Castro Lopo <erikd@mega-nerd.com> |
3 | | ** |
4 | | ** This program is free software; you can redistribute it and/or modify |
5 | | ** it under the terms of the GNU Lesser General Public License as published by |
6 | | ** the Free Software Foundation; either version 2.1 of the License, or |
7 | | ** (at your option) any later version. |
8 | | ** |
9 | | ** This program is distributed in the hope that it will be useful, |
10 | | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | ** GNU Lesser General Public License for more details. |
13 | | ** |
14 | | ** You should have received a copy of the GNU Lesser General Public License |
15 | | ** along with this program; if not, write to the Free Software |
16 | | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | | */ |
18 | | |
19 | | #include "sfconfig.h" |
20 | | |
21 | | #include <stdio.h> |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | #include <ctype.h> |
25 | | #include <math.h> |
26 | | #include <inttypes.h> |
27 | | |
28 | | #include "sndfile.h" |
29 | | #include "sfendian.h" |
30 | | #include "common.h" |
31 | | #include "chanmap.h" |
32 | | |
33 | | /*------------------------------------------------------------------------------ |
34 | | ** Macros to handle big/little endian issues. |
35 | | */ |
36 | | |
37 | | #define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ') |
38 | 1.30k | #define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c') |
39 | 199 | #define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w') |
40 | 2.57k | #define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f') |
41 | 507 | #define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n') |
42 | 8.42k | #define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a') |
43 | 2.57k | #define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c') |
44 | | #define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't') |
45 | 68 | #define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e') |
46 | | #define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4') |
47 | 926 | #define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o') |
48 | | #define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't') |
49 | 1.06k | #define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i') |
50 | 408 | #define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm') |
51 | | #define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k') |
52 | | #define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i') |
53 | | #define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1') |
54 | | #define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2') |
55 | | #define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3') |
56 | | #define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w') |
57 | 1.63k | #define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't') |
58 | 265 | #define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k') |
59 | | #define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n') |
60 | | #define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g') |
61 | | #define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd') |
62 | | #define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd') |
63 | 198 | #define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w') |
64 | | #define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3') |
65 | | #define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6') |
66 | | |
67 | 273 | #define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8))) |
68 | | |
69 | | /*------------------------------------------------------------------------------ |
70 | | ** Typedefs. |
71 | | */ |
72 | | |
73 | | typedef struct |
74 | | { uint8_t srate [8] ; |
75 | | uint32_t fmt_id ; |
76 | | uint32_t fmt_flags ; |
77 | | uint32_t pkt_bytes ; |
78 | | uint32_t frames_per_packet ; |
79 | | uint32_t channels_per_frame ; |
80 | | uint32_t bits_per_chan ; |
81 | | } DESC_CHUNK ; |
82 | | |
83 | | typedef struct |
84 | | { int chanmap_tag ; |
85 | | |
86 | | ALAC_DECODER_INFO alac ; |
87 | | } CAF_PRIVATE ; |
88 | | |
89 | | /*------------------------------------------------------------------------------ |
90 | | ** Private static functions. |
91 | | */ |
92 | | |
93 | | static int caf_close (SF_PRIVATE *psf) ; |
94 | | static int caf_read_header (SF_PRIVATE *psf) ; |
95 | | static int caf_write_header (SF_PRIVATE *psf, int calc_length) ; |
96 | | static int caf_write_tailer (SF_PRIVATE *psf) ; |
97 | | static int caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; |
98 | | static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ; |
99 | | static int caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size) ; |
100 | | static void caf_write_strings (SF_PRIVATE * psf, int location) ; |
101 | | |
102 | | |
103 | | static int caf_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) ; |
104 | | static SF_CHUNK_ITERATOR * caf_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) ; |
105 | | static int caf_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ; |
106 | | static int caf_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ; |
107 | | |
108 | | /*------------------------------------------------------------------------------ |
109 | | ** Public function. |
110 | | */ |
111 | | |
112 | | int |
113 | | caf_open (SF_PRIVATE *psf) |
114 | 2.57k | { CAF_PRIVATE * pcaf ; |
115 | 2.57k | int subformat, format, error = 0 ; |
116 | | |
117 | 2.57k | if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL) |
118 | 0 | return SFE_MALLOC_FAILED ; |
119 | | |
120 | 2.57k | pcaf = psf->container_data ; |
121 | | |
122 | 2.57k | if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0)) |
123 | 2.57k | { if ((error = caf_read_header (psf))) |
124 | 1.46k | return error ; |
125 | | |
126 | 1.10k | psf->next_chunk_iterator = caf_next_chunk_iterator ; |
127 | 1.10k | psf->get_chunk_size = caf_get_chunk_size ; |
128 | 1.10k | psf->get_chunk_data = caf_get_chunk_data ; |
129 | 1.10k | } ; |
130 | | |
131 | 1.10k | subformat = SF_CODEC (psf->sf.format) ; |
132 | | |
133 | 1.10k | if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) |
134 | 0 | { if (psf->is_pipe) |
135 | 0 | return SFE_NO_PIPE_WRITE ; |
136 | | |
137 | 0 | format = SF_CONTAINER (psf->sf.format) ; |
138 | 0 | if (format != SF_FORMAT_CAF) |
139 | 0 | return SFE_BAD_OPEN_FORMAT ; |
140 | | |
141 | 0 | psf->blockwidth = psf->bytewidth * psf->sf.channels ; |
142 | |
|
143 | 0 | if (psf->file.mode != SFM_RDWR || psf->filelength < 44) |
144 | 0 | { psf->filelength = 0 ; |
145 | 0 | psf->datalength = 0 ; |
146 | 0 | psf->dataoffset = 0 ; |
147 | 0 | psf->sf.frames = 0 ; |
148 | 0 | } ; |
149 | |
|
150 | 0 | psf->strings.flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; |
151 | | |
152 | | /* |
153 | | ** By default, add the peak chunk to floating point files. Default behaviour |
154 | | ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE). |
155 | | */ |
156 | 0 | if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) |
157 | 0 | { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) |
158 | 0 | return SFE_MALLOC_FAILED ; |
159 | 0 | psf->peak_info->peak_loc = SF_PEAK_START ; |
160 | 0 | } ; |
161 | |
|
162 | 0 | if ((error = caf_write_header (psf, SF_FALSE)) != 0) |
163 | 0 | return error ; |
164 | | |
165 | 0 | psf->write_header = caf_write_header ; |
166 | 0 | psf->set_chunk = caf_set_chunk ; |
167 | 1.10k | } ; |
168 | | |
169 | 1.10k | psf->container_close = caf_close ; |
170 | 1.10k | psf->command = caf_command ; |
171 | | |
172 | 1.10k | switch (subformat) |
173 | 1.10k | { case SF_FORMAT_PCM_S8 : |
174 | 2 | case SF_FORMAT_PCM_16 : |
175 | 3 | case SF_FORMAT_PCM_24 : |
176 | 4 | case SF_FORMAT_PCM_32 : |
177 | 4 | error = pcm_init (psf) ; |
178 | 4 | break ; |
179 | | |
180 | 1 | case SF_FORMAT_ULAW : |
181 | 1 | error = ulaw_init (psf) ; |
182 | 1 | break ; |
183 | | |
184 | 1 | case SF_FORMAT_ALAW : |
185 | 1 | error = alaw_init (psf) ; |
186 | 1 | break ; |
187 | | |
188 | | /* Lite remove start */ |
189 | 1 | case SF_FORMAT_FLOAT : |
190 | 1 | error = float32_init (psf) ; |
191 | 1 | break ; |
192 | | |
193 | 1 | case SF_FORMAT_DOUBLE : |
194 | 1 | error = double64_init (psf) ; |
195 | 1 | break ; |
196 | | |
197 | 590 | case SF_FORMAT_ALAC_16 : |
198 | 800 | case SF_FORMAT_ALAC_20 : |
199 | 951 | case SF_FORMAT_ALAC_24 : |
200 | 1.09k | case SF_FORMAT_ALAC_32 : |
201 | 1.09k | if (psf->file.mode == SFM_READ) |
202 | | /* Only pass the ALAC_DECODER_INFO in read mode. */ |
203 | 1.09k | error = alac_init (psf, &pcaf->alac) ; |
204 | 0 | else |
205 | 0 | error = alac_init (psf, NULL) ; |
206 | 1.09k | break ; |
207 | | |
208 | | /* Lite remove end */ |
209 | | |
210 | 2 | default : |
211 | 2 | return SFE_UNSUPPORTED_ENCODING ; |
212 | 1.10k | } ; |
213 | | |
214 | 1.10k | return error ; |
215 | 1.10k | } /* caf_open */ |
216 | | |
217 | | static int |
218 | | caf_close (SF_PRIVATE *psf) |
219 | 1.10k | { |
220 | 1.10k | if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) |
221 | 0 | { caf_write_tailer (psf) ; |
222 | 0 | caf_write_header (psf, SF_TRUE) ; |
223 | 0 | } ; |
224 | | |
225 | 1.10k | return 0 ; |
226 | 1.10k | } /* caf_close */ |
227 | | |
228 | | static int |
229 | | caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize)) |
230 | 0 | { CAF_PRIVATE *pcaf ; |
231 | |
|
232 | 0 | if ((pcaf = psf->container_data) == NULL) |
233 | 0 | return SFE_INTERNAL ; |
234 | | |
235 | 0 | switch (command) |
236 | 0 | { case SFC_SET_CHANNEL_MAP_INFO : |
237 | 0 | pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ; |
238 | 0 | return (pcaf->chanmap_tag != 0) ; |
239 | | |
240 | 0 | default : |
241 | 0 | break ; |
242 | 0 | } ; |
243 | |
|
244 | 0 | return 0 ; |
245 | 0 | } /* caf_command */ |
246 | | |
247 | | /*------------------------------------------------------------------------------ |
248 | | */ |
249 | | |
250 | | static int |
251 | | decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc) |
252 | 1.30k | { int format = SF_FORMAT_CAF ; |
253 | | |
254 | 1.30k | psf->sf.channels = desc->channels_per_frame ; |
255 | | |
256 | 1.30k | if (desc->fmt_id == alac_MARKER) |
257 | 1.09k | { CAF_PRIVATE *pcaf ; |
258 | | |
259 | 1.09k | if ((pcaf = psf->container_data) != NULL) |
260 | 1.09k | { switch (desc->fmt_flags) |
261 | 1.09k | { case 1 : |
262 | 590 | pcaf->alac.bits_per_sample = 16 ; |
263 | 590 | format |= SF_FORMAT_ALAC_16 ; |
264 | 590 | break ; |
265 | 210 | case 2 : |
266 | 210 | pcaf->alac.bits_per_sample = 20 ; |
267 | 210 | format |= SF_FORMAT_ALAC_20 ; |
268 | 210 | break ; |
269 | 151 | case 3 : |
270 | 151 | pcaf->alac.bits_per_sample = 24 ; |
271 | 151 | format |= SF_FORMAT_ALAC_24 ; |
272 | 151 | break ; |
273 | 144 | case 4 : |
274 | 144 | pcaf->alac.bits_per_sample = 32 ; |
275 | 144 | format |= SF_FORMAT_ALAC_32 ; |
276 | 144 | break ; |
277 | 2 | default : |
278 | 2 | psf_log_printf (psf, "Bad ALAC format flag value of %d\n", desc->fmt_flags) ; |
279 | 1.09k | } ; |
280 | | |
281 | 1.09k | pcaf->alac.frames_per_packet = desc->frames_per_packet ; |
282 | 1.09k | } ; |
283 | | |
284 | 1.09k | return format ; |
285 | 1.09k | } ; |
286 | | |
287 | 205 | format |= psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0 ; |
288 | | |
289 | 205 | if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1) |
290 | 62 | { /* Floating point data. */ |
291 | 62 | if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame) |
292 | 1 | { psf->bytewidth = 4 ; |
293 | 1 | return format | SF_FORMAT_FLOAT ; |
294 | 61 | } ; |
295 | 61 | if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame) |
296 | 1 | { psf->bytewidth = 8 ; |
297 | 1 | return format | SF_FORMAT_DOUBLE ; |
298 | 60 | } ; |
299 | 203 | } ; |
300 | | |
301 | 203 | if (desc->fmt_id == lpcm_MARKER && (desc->fmt_flags & 1) == 0) |
302 | 60 | { /* Integer data. */ |
303 | 60 | if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame) |
304 | 1 | { psf->bytewidth = 4 ; |
305 | 1 | return format | SF_FORMAT_PCM_32 ; |
306 | 59 | } ; |
307 | 59 | if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame) |
308 | 1 | { psf->bytewidth = 3 ; |
309 | 1 | return format | SF_FORMAT_PCM_24 ; |
310 | 58 | } ; |
311 | 58 | if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame) |
312 | 1 | { psf->bytewidth = 2 ; |
313 | 1 | return format | SF_FORMAT_PCM_16 ; |
314 | 57 | } ; |
315 | 57 | if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame) |
316 | 1 | { psf->bytewidth = 1 ; |
317 | 1 | return format | SF_FORMAT_PCM_S8 ; |
318 | 56 | } ; |
319 | 199 | } ; |
320 | | |
321 | 199 | if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8) |
322 | 1 | { psf->bytewidth = 1 ; |
323 | 1 | return format | SF_FORMAT_ALAW ; |
324 | 198 | } ; |
325 | | |
326 | 198 | if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8) |
327 | 1 | { psf->bytewidth = 1 ; |
328 | 1 | return format | SF_FORMAT_ULAW ; |
329 | 197 | } ; |
330 | | |
331 | 197 | psf_log_printf (psf, "**** Unknown format identifier.\n") ; |
332 | | |
333 | 197 | return 0 ; |
334 | 198 | } /* decode_desc_chunk */ |
335 | | |
336 | | static int |
337 | | caf_read_header (SF_PRIVATE *psf) |
338 | 2.57k | { CAF_PRIVATE *pcaf ; |
339 | 2.57k | BUF_UNION ubuf ; |
340 | 2.57k | DESC_CHUNK desc ; |
341 | 2.57k | sf_count_t chunk_size ; |
342 | 2.57k | double srate ; |
343 | 2.57k | short version, flags ; |
344 | 2.57k | int marker, k, have_data = 0, error ; |
345 | | |
346 | 2.57k | if ((pcaf = psf->container_data) == NULL) |
347 | 0 | return SFE_INTERNAL ; |
348 | | |
349 | 2.57k | memset (&desc, 0, sizeof (desc)) ; |
350 | | |
351 | | /* Set position to start of file to begin reading header. */ |
352 | 2.57k | psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ; |
353 | 2.57k | psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ; |
354 | 2.57k | if (marker != caff_MARKER) |
355 | 0 | return SFE_CAF_NOT_CAF ; |
356 | | |
357 | 2.57k | psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, ubuf.ucbuf, 8) ; |
358 | 2.57k | srate = double64_be_read (ubuf.ucbuf) ; |
359 | 2.57k | snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), "%5.3f", srate) ; |
360 | 2.57k | psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, ubuf.cbuf) ; |
361 | 2.57k | if (marker != desc_MARKER) |
362 | 0 | return SFE_CAF_NO_DESC ; |
363 | | |
364 | 2.57k | if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK)) |
365 | 76 | { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ; |
366 | 76 | return SFE_MALFORMED_FILE ; |
367 | 2.49k | } ; |
368 | | |
369 | 2.49k | psf->sf.samplerate = psf_lrint (srate) ; |
370 | | |
371 | 2.49k | psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.frames_per_packet, |
372 | 2.49k | &desc.channels_per_frame, &desc.bits_per_chan) ; |
373 | 2.49k | psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n" |
374 | 2.49k | " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n", |
375 | 2.49k | desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ; |
376 | | |
377 | 2.49k | if (desc.channels_per_frame > SF_MAX_CHANNELS) |
378 | 34 | { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ; |
379 | 34 | return SFE_MALFORMED_FILE ; |
380 | 2.46k | } ; |
381 | | |
382 | 2.46k | if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK)) |
383 | 2.46k | psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ; |
384 | | |
385 | 2.46k | psf->sf.channels = desc.channels_per_frame ; |
386 | | |
387 | 7.68k | while (1) |
388 | 7.68k | { marker = 0 ; |
389 | 7.68k | chunk_size = 0 ; |
390 | | |
391 | 7.68k | psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ; |
392 | 7.68k | if (marker == 0) |
393 | 163 | { sf_count_t pos = psf_ftell (psf) ; |
394 | 163 | psf_log_printf (psf, "Have 0 marker at position %D (0x%x).\n", pos, pos) ; |
395 | 163 | break ; |
396 | 7.51k | } ; |
397 | 7.51k | if (chunk_size < 0) |
398 | 136 | { psf_log_printf (psf, "%M : %D *** Should be >= 0 ***\n", marker, chunk_size) ; |
399 | 136 | break ; |
400 | 7.38k | } ; |
401 | 7.38k | if (chunk_size > psf->filelength) |
402 | 334 | break ; |
403 | | |
404 | 7.04k | psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ; |
405 | | |
406 | 7.04k | switch (marker) |
407 | 7.04k | { case peak_MARKER : |
408 | 265 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
409 | 265 | if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) |
410 | 8 | { psf_binheader_readf (psf, "j", (size_t) chunk_size) ; |
411 | 8 | psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; |
412 | 8 | return SFE_CAF_BAD_PEAK ; |
413 | 257 | } ; |
414 | | |
415 | 257 | if (psf->peak_info) |
416 | 227 | { psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ; |
417 | 227 | free (psf->peak_info) ; |
418 | 227 | psf->peak_info = NULL ; |
419 | 227 | } ; |
420 | 257 | if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) |
421 | 0 | return SFE_MALLOC_FAILED ; |
422 | | |
423 | | /* read in rest of PEAK chunk. */ |
424 | 257 | psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ; |
425 | 257 | psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ; |
426 | | |
427 | 257 | psf_log_printf (psf, " Ch Position Value\n") ; |
428 | 837 | for (k = 0 ; k < psf->sf.channels ; k++) |
429 | 580 | { sf_count_t position ; |
430 | 580 | float value ; |
431 | | |
432 | 580 | psf_binheader_readf (psf, "Ef8", &value, &position) ; |
433 | 580 | psf->peak_info->peaks [k].value = value ; |
434 | 580 | psf->peak_info->peaks [k].position = position ; |
435 | | |
436 | 580 | snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ; |
437 | 580 | psf_log_printf (psf, ubuf.cbuf) ; |
438 | 580 | } ; |
439 | | |
440 | 257 | psf->peak_info->peak_loc = SF_PEAK_START ; |
441 | 257 | break ; |
442 | | |
443 | 507 | case chan_MARKER : |
444 | 507 | if (chunk_size < 12) |
445 | 215 | { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; |
446 | 215 | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; |
447 | 215 | break ; |
448 | 215 | } |
449 | | |
450 | 292 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
451 | | |
452 | 292 | if ((error = caf_read_chanmap (psf, chunk_size))) |
453 | 0 | return error ; |
454 | 292 | break ; |
455 | | |
456 | 292 | case free_MARKER : |
457 | 68 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
458 | 68 | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; |
459 | 68 | break ; |
460 | | |
461 | 1.39k | case data_MARKER : |
462 | 1.39k | psf_binheader_readf (psf, "E4", &k) ; |
463 | 1.39k | if (chunk_size == -1) |
464 | 0 | { psf_log_printf (psf, "%M : -1\n") ; |
465 | 0 | chunk_size = psf->filelength - psf->header.indx ; |
466 | 0 | } |
467 | 1.39k | else if (psf->filelength > 0 && chunk_size > psf->filelength - psf->header.indx + 10) |
468 | 19 | { psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, psf->filelength - psf->header.indx - 8) ; |
469 | 19 | psf->datalength = psf->filelength - psf->header.indx - 8 ; |
470 | 19 | } |
471 | 1.37k | else |
472 | 1.37k | { psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
473 | | /* Subtract the 4 bytes of the 'edit' field above. */ |
474 | 1.37k | psf->datalength = chunk_size - 4 ; |
475 | 1.37k | } ; |
476 | | |
477 | 1.39k | psf_log_printf (psf, " edit : %u\n", k) ; |
478 | | |
479 | 1.39k | psf->dataoffset = psf->header.indx ; |
480 | 1.39k | if (psf->datalength + psf->dataoffset < psf->filelength) |
481 | 1.39k | psf->dataend = psf->datalength + psf->dataoffset ; |
482 | | |
483 | 1.39k | psf_binheader_readf (psf, "j", (size_t) psf->datalength) ; |
484 | 1.39k | have_data = 1 ; |
485 | 1.39k | break ; |
486 | | |
487 | 1.06k | case kuki_MARKER : |
488 | 1.06k | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
489 | 1.06k | pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ; |
490 | 1.06k | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; |
491 | 1.06k | break ; |
492 | | |
493 | 1.63k | case pakt_MARKER : |
494 | 1.63k | if (chunk_size < 24) |
495 | 3 | { psf_log_printf (psf, "%M : %D (should be > 24)\n", marker, chunk_size) ; |
496 | 3 | return SFE_MALFORMED_FILE ; |
497 | 3 | } |
498 | 1.62k | else if (chunk_size > psf->filelength - psf->header.indx) |
499 | 1 | { psf_log_printf (psf, "%M : %D (should be < %D)\n", marker, chunk_size, psf->filelength - psf->header.indx) ; |
500 | 1 | return SFE_MALFORMED_FILE ; |
501 | 1 | } |
502 | 1.62k | else |
503 | 1.62k | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
504 | | |
505 | 1.62k | psf_binheader_readf (psf, "E8844", &pcaf->alac.packets, &pcaf->alac.valid_frames, |
506 | 1.62k | &pcaf->alac.priming_frames, &pcaf->alac.remainder_frames) ; |
507 | | |
508 | 1.62k | psf_log_printf (psf, |
509 | 1.62k | " Packets : %D\n" |
510 | 1.62k | " Valid frames : %D\n" |
511 | 1.62k | " Priming frames : %d\n" |
512 | 1.62k | " Remainder frames : %d\n", |
513 | 1.62k | pcaf->alac.packets, pcaf->alac.valid_frames, pcaf->alac.priming_frames, |
514 | 1.62k | pcaf->alac.remainder_frames |
515 | 1.62k | ) ; |
516 | | |
517 | 1.62k | if (pcaf->alac.packets == 0 && pcaf->alac.valid_frames == 0 |
518 | 1.62k | && pcaf->alac.priming_frames == 0 && pcaf->alac.remainder_frames == 0) |
519 | 113 | psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ; |
520 | | |
521 | 1.62k | pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ; |
522 | 1.62k | psf_binheader_readf (psf, "j", (size_t) chunk_size - 24) ; |
523 | 1.62k | break ; |
524 | | |
525 | 926 | case info_MARKER : |
526 | 926 | if (chunk_size < 4) |
527 | 2 | { psf_log_printf (psf, "%M : %D (should be > 4)\n", marker, chunk_size) ; |
528 | 2 | return SFE_MALFORMED_FILE ; |
529 | 2 | } |
530 | 924 | else if (chunk_size > psf->filelength - psf->header.indx) |
531 | 10 | { psf_log_printf (psf, "%M : %D (should be < %D)\n", marker, chunk_size, psf->filelength - psf->header.indx) ; |
532 | 10 | return SFE_MALFORMED_FILE ; |
533 | 914 | } ; |
534 | 914 | psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; |
535 | 914 | if (chunk_size > 4) |
536 | 904 | caf_read_strings (psf, chunk_size - 4) ; |
537 | 914 | break ; |
538 | | |
539 | 1.18k | default : |
540 | 1.18k | psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ; |
541 | 1.18k | psf_binheader_readf (psf, "j", (size_t) chunk_size) ; |
542 | 1.18k | break ; |
543 | 7.04k | } ; |
544 | | |
545 | 7.02k | if (marker != data_MARKER && chunk_size >= 0xffffff00) |
546 | 0 | break ; |
547 | | |
548 | 7.02k | if (! psf->sf.seekable && have_data) |
549 | 0 | break ; |
550 | | |
551 | 7.02k | if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (chunk_size)) |
552 | 1.80k | { psf_log_printf (psf, "End\n") ; |
553 | 1.80k | break ; |
554 | 5.21k | } ; |
555 | 5.21k | } ; |
556 | | |
557 | 2.44k | if (have_data == 0) |
558 | 1.13k | { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ; |
559 | 1.13k | return SFE_MALFORMED_FILE ; |
560 | 1.30k | } ; |
561 | | |
562 | 1.30k | psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; |
563 | | |
564 | 1.30k | psf_fseek (psf, psf->dataoffset, SEEK_SET) ; |
565 | | |
566 | 1.30k | if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0) |
567 | 197 | return SFE_UNSUPPORTED_ENCODING ; |
568 | | |
569 | 1.10k | if (psf->bytewidth > 0) |
570 | 8 | psf->sf.frames = psf->datalength / psf->bytewidth ; |
571 | | |
572 | 1.10k | return 0 ; |
573 | 1.30k | } /* caf_read_header */ |
574 | | |
575 | | /*------------------------------------------------------------------------------ |
576 | | */ |
577 | | |
578 | | static int |
579 | | caf_write_header (SF_PRIVATE *psf, int calc_length) |
580 | 0 | { BUF_UNION ubuf ; |
581 | 0 | CAF_PRIVATE *pcaf ; |
582 | 0 | DESC_CHUNK desc ; |
583 | 0 | sf_count_t current ; |
584 | 0 | uint32_t uk ; |
585 | 0 | int subformat, append_free_block = SF_TRUE ; |
586 | |
|
587 | 0 | if ((pcaf = psf->container_data) == NULL) |
588 | 0 | return SFE_INTERNAL ; |
589 | | |
590 | 0 | memset (&desc, 0, sizeof (desc)) ; |
591 | |
|
592 | 0 | current = psf_ftell (psf) ; |
593 | |
|
594 | 0 | if (calc_length) |
595 | 0 | { psf->filelength = psf_get_filelen (psf) ; |
596 | |
|
597 | 0 | psf->datalength = psf->filelength - psf->dataoffset ; |
598 | |
|
599 | 0 | if (psf->dataend) |
600 | 0 | psf->datalength -= psf->filelength - psf->dataend ; |
601 | |
|
602 | 0 | if (psf->bytewidth > 0) |
603 | 0 | psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; |
604 | 0 | } ; |
605 | | |
606 | | /* Reset the current header length to zero. */ |
607 | 0 | psf->header.ptr [0] = 0 ; |
608 | 0 | psf->header.indx = 0 ; |
609 | 0 | psf_fseek (psf, 0, SEEK_SET) ; |
610 | | |
611 | | /* 'caff' marker, version and flags. */ |
612 | 0 | psf_binheader_writef (psf, "Em22", BHWm (caff_MARKER), BHW2 (1), BHW2 (0)) ; |
613 | | |
614 | | /* 'desc' marker and chunk size. */ |
615 | 0 | psf_binheader_writef (psf, "Em8", BHWm (desc_MARKER), BHW8 ((sf_count_t) (sizeof (DESC_CHUNK)))) ; |
616 | |
|
617 | 0 | double64_be_write (1.0 * psf->sf.samplerate, ubuf.ucbuf) ; |
618 | 0 | psf_binheader_writef (psf, "b", BHWv (ubuf.ucbuf), BHWz (8)) ; |
619 | |
|
620 | 0 | subformat = SF_CODEC (psf->sf.format) ; |
621 | |
|
622 | 0 | psf->endian = SF_ENDIAN (psf->sf.format) ; |
623 | |
|
624 | 0 | if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) |
625 | 0 | psf->endian = SF_ENDIAN_BIG ; |
626 | 0 | else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU)) |
627 | 0 | psf->endian = SF_ENDIAN_LITTLE ; |
628 | |
|
629 | 0 | if (psf->endian == SF_ENDIAN_LITTLE) |
630 | 0 | desc.fmt_flags = 2 ; |
631 | 0 | else |
632 | 0 | psf->endian = SF_ENDIAN_BIG ; |
633 | | |
634 | | /* initial section (same for all, it appears) */ |
635 | 0 | switch (subformat) |
636 | 0 | { case SF_FORMAT_PCM_S8 : |
637 | 0 | desc.fmt_id = lpcm_MARKER ; |
638 | 0 | psf->bytewidth = 1 ; |
639 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
640 | 0 | desc.frames_per_packet = 1 ; |
641 | 0 | desc.channels_per_frame = psf->sf.channels ; |
642 | 0 | desc.bits_per_chan = 8 ; |
643 | 0 | break ; |
644 | | |
645 | 0 | case SF_FORMAT_PCM_16 : |
646 | 0 | desc.fmt_id = lpcm_MARKER ; |
647 | 0 | psf->bytewidth = 2 ; |
648 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
649 | 0 | desc.frames_per_packet = 1 ; |
650 | 0 | desc.channels_per_frame = psf->sf.channels ; |
651 | 0 | desc.bits_per_chan = 16 ; |
652 | 0 | break ; |
653 | | |
654 | 0 | case SF_FORMAT_PCM_24 : |
655 | 0 | psf->bytewidth = 3 ; |
656 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
657 | 0 | desc.frames_per_packet = 1 ; |
658 | 0 | desc.channels_per_frame = psf->sf.channels ; |
659 | 0 | desc.bits_per_chan = 24 ; |
660 | 0 | desc.fmt_id = lpcm_MARKER ; |
661 | 0 | break ; |
662 | | |
663 | 0 | case SF_FORMAT_PCM_32 : |
664 | 0 | desc.fmt_id = lpcm_MARKER ; |
665 | 0 | psf->bytewidth = 4 ; |
666 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
667 | 0 | desc.frames_per_packet = 1 ; |
668 | 0 | desc.channels_per_frame = psf->sf.channels ; |
669 | 0 | desc.bits_per_chan = 32 ; |
670 | 0 | break ; |
671 | | |
672 | 0 | case SF_FORMAT_FLOAT : |
673 | 0 | desc.fmt_id = lpcm_MARKER ; |
674 | 0 | desc.fmt_flags |= 1 ; |
675 | 0 | psf->bytewidth = 4 ; |
676 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
677 | 0 | desc.frames_per_packet = 1 ; |
678 | 0 | desc.channels_per_frame = psf->sf.channels ; |
679 | 0 | desc.bits_per_chan = 32 ; |
680 | 0 | break ; |
681 | | |
682 | 0 | case SF_FORMAT_DOUBLE : |
683 | 0 | desc.fmt_id = lpcm_MARKER ; |
684 | 0 | desc.fmt_flags |= 1 ; |
685 | 0 | psf->bytewidth = 8 ; |
686 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
687 | 0 | desc.frames_per_packet = 1 ; |
688 | 0 | desc.channels_per_frame = psf->sf.channels ; |
689 | 0 | desc.bits_per_chan = 64 ; |
690 | 0 | break ; |
691 | | |
692 | 0 | case SF_FORMAT_ALAW : |
693 | 0 | desc.fmt_id = alaw_MARKER ; |
694 | 0 | psf->bytewidth = 1 ; |
695 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
696 | 0 | desc.frames_per_packet = 1 ; |
697 | 0 | desc.channels_per_frame = psf->sf.channels ; |
698 | 0 | desc.bits_per_chan = 8 ; |
699 | 0 | break ; |
700 | | |
701 | 0 | case SF_FORMAT_ULAW : |
702 | 0 | desc.fmt_id = ulaw_MARKER ; |
703 | 0 | psf->bytewidth = 1 ; |
704 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
705 | 0 | desc.frames_per_packet = 1 ; |
706 | 0 | desc.channels_per_frame = psf->sf.channels ; |
707 | 0 | desc.bits_per_chan = 8 ; |
708 | 0 | break ; |
709 | | |
710 | 0 | case SF_FORMAT_ALAC_16 : |
711 | 0 | case SF_FORMAT_ALAC_20 : |
712 | 0 | case SF_FORMAT_ALAC_24 : |
713 | 0 | case SF_FORMAT_ALAC_32 : |
714 | 0 | desc.fmt_id = alac_MARKER ; |
715 | 0 | desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; |
716 | 0 | desc.channels_per_frame = psf->sf.channels ; |
717 | 0 | alac_get_desc_chunk_items (subformat, &desc.fmt_flags, &desc.frames_per_packet) ; |
718 | 0 | append_free_block = SF_FALSE ; |
719 | 0 | break ; |
720 | | |
721 | 0 | default : |
722 | 0 | return SFE_UNIMPLEMENTED ; |
723 | 0 | } ; |
724 | |
|
725 | 0 | psf_binheader_writef (psf, "mE44444", BHWm (desc.fmt_id), BHW4 (desc.fmt_flags), BHW4 (desc.pkt_bytes), BHW4 (desc.frames_per_packet), BHW4 (desc.channels_per_frame), BHW4 (desc.bits_per_chan)) ; |
726 | |
|
727 | 0 | caf_write_strings (psf, SF_STR_LOCATE_START) ; |
728 | |
|
729 | 0 | if (psf->peak_info != NULL) |
730 | 0 | { int k ; |
731 | 0 | psf_binheader_writef (psf, "Em84", BHWm (peak_MARKER), BHW8 ((sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels)), BHW4 (psf->peak_info->edit_number)) ; |
732 | 0 | for (k = 0 ; k < psf->sf.channels ; k++) |
733 | 0 | psf_binheader_writef (psf, "Ef8", BHWf ((float) psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ; |
734 | 0 | } ; |
735 | |
|
736 | 0 | if (psf->channel_map && pcaf->chanmap_tag) |
737 | 0 | psf_binheader_writef (psf, "Em8444", BHWm (chan_MARKER), BHW8 ((sf_count_t) 12), BHW4 (pcaf->chanmap_tag), BHW4 (0), BHW4 (0)) ; |
738 | | |
739 | | /* Write custom headers. */ |
740 | 0 | for (uk = 0 ; uk < psf->wchunks.used ; uk++) |
741 | 0 | psf_binheader_writef (psf, "m44b", BHWm ((int) psf->wchunks.chunks [uk].mark32), BHW4 (0), BHW4 (psf->wchunks.chunks [uk].len), BHWv (psf->wchunks.chunks [uk].data), BHWz (psf->wchunks.chunks [uk].len)) ; |
742 | |
|
743 | 0 | if (append_free_block) |
744 | 0 | { /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */ |
745 | 0 | sf_count_t free_len = 0x1000 - psf->header.indx - 16 - 12 ; |
746 | 0 | while (free_len < 0) |
747 | 0 | free_len += 0x1000 ; |
748 | 0 | psf_binheader_writef (psf, "Em8z", BHWm (free_MARKER), BHW8 (free_len), BHWz (free_len)) ; |
749 | 0 | } ; |
750 | |
|
751 | 0 | psf_binheader_writef (psf, "Em84", BHWm (data_MARKER), BHW8 (psf->datalength + 4), BHW4 (0)) ; |
752 | |
|
753 | 0 | psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; |
754 | 0 | if (psf->error) |
755 | 0 | return psf->error ; |
756 | | |
757 | 0 | psf->dataoffset = psf->header.indx ; |
758 | 0 | if (current < psf->dataoffset) |
759 | 0 | psf_fseek (psf, psf->dataoffset, SEEK_SET) ; |
760 | 0 | else if (current > 0) |
761 | 0 | psf_fseek (psf, current, SEEK_SET) ; |
762 | |
|
763 | 0 | return psf->error ; |
764 | 0 | } /* caf_write_header */ |
765 | | |
766 | | static int |
767 | | caf_write_tailer (SF_PRIVATE *psf) |
768 | 0 | { |
769 | | /* Reset the current header buffer length to zero. */ |
770 | 0 | psf->header.ptr [0] = 0 ; |
771 | 0 | psf->header.indx = 0 ; |
772 | |
|
773 | 0 | if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE) |
774 | 0 | { psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ; |
775 | 0 | psf->dataend = psf->dataoffset + psf->datalength ; |
776 | 0 | } ; |
777 | |
|
778 | 0 | if (psf->dataend > 0) |
779 | 0 | psf_fseek (psf, psf->dataend, SEEK_SET) ; |
780 | 0 | else |
781 | 0 | psf->dataend = psf_fseek (psf, 0, SEEK_END) ; |
782 | |
|
783 | 0 | if (psf->dataend & 1) |
784 | 0 | psf_binheader_writef (psf, "z", BHWz (1)) ; |
785 | |
|
786 | 0 | if (psf->strings.flags & SF_STR_LOCATE_END) |
787 | 0 | caf_write_strings (psf, SF_STR_LOCATE_END) ; |
788 | | |
789 | | /* Write the tailer. */ |
790 | 0 | if (psf->header.indx > 0) |
791 | 0 | psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; |
792 | |
|
793 | 0 | return 0 ; |
794 | 0 | } /* caf_write_tailer */ |
795 | | |
796 | | static int |
797 | | caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) |
798 | 292 | { const AIFF_CAF_CHANNEL_MAP * map_info ; |
799 | 292 | unsigned channel_bitmap, channel_decriptions, bytesread ; |
800 | 292 | int layout_tag ; |
801 | | |
802 | 292 | bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ; |
803 | | |
804 | 292 | map_info = aiff_caf_of_channel_layout_tag (layout_tag) ; |
805 | | |
806 | 292 | psf_log_printf (psf, " Tag : %x\n", layout_tag) ; |
807 | 292 | if (map_info) |
808 | 257 | psf_log_printf (psf, " Layout : %s\n", map_info->name) ; |
809 | | |
810 | 292 | if (bytesread < chunk_size) |
811 | 202 | psf_binheader_readf (psf, "j", chunk_size - bytesread) ; |
812 | | |
813 | 292 | if (map_info && map_info->channel_map != NULL) |
814 | 178 | { size_t chanmap_size = SF_MIN (psf->sf.channels, layout_tag & 0xff) * sizeof (psf->channel_map [0]) ; |
815 | | |
816 | 178 | free (psf->channel_map) ; |
817 | | |
818 | 178 | if ((psf->channel_map = malloc (chanmap_size)) == NULL) |
819 | 0 | return SFE_MALLOC_FAILED ; |
820 | | |
821 | 178 | memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ; |
822 | 292 | } ; |
823 | | |
824 | 292 | return 0 ; |
825 | 292 | } /* caf_read_chanmap */ |
826 | | |
827 | | |
828 | | static uint32_t |
829 | | string_hash32 (const char * str) |
830 | 167k | { uint32_t hash = 0x87654321 ; |
831 | | |
832 | 426k | while (str [0]) |
833 | 258k | { hash = hash * 333 + str [0] ; |
834 | 258k | str ++ ; |
835 | 258k | } ; |
836 | | |
837 | 167k | return hash ; |
838 | 167k | } /* string_hash32 */ |
839 | | |
840 | | static int |
841 | | caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size) |
842 | 904 | { char *buf ; |
843 | 904 | char *key, *value ; |
844 | 904 | uint32_t count, hash ; |
845 | | |
846 | 904 | if ((buf = malloc (chunk_size + 1)) == NULL) |
847 | 0 | return (psf->error = SFE_MALLOC_FAILED) ; |
848 | | |
849 | 904 | psf_binheader_readf (psf, "E4b", &count, buf, (size_t) chunk_size) ; |
850 | 904 | psf_log_printf (psf, " count: %u\n", count) ; |
851 | | |
852 | | /* Force terminate `buf` to make sure. */ |
853 | 904 | buf [chunk_size] = 0 ; |
854 | | |
855 | 168k | for (key = buf ; key < buf + chunk_size ; ) |
856 | 168k | { value = key + strlen (key) + 1 ; |
857 | 168k | if (value > buf + chunk_size) |
858 | 411 | break ; |
859 | 167k | psf_log_printf (psf, " %-12s : %s\n", key, value) ; |
860 | | |
861 | 167k | hash = string_hash32 (key) ; |
862 | 167k | switch (hash) |
863 | 167k | { case 0xC4861943 : /* 'title' */ |
864 | 78 | psf_store_string (psf, SF_STR_TITLE, value) ; |
865 | 78 | break ; |
866 | 285 | case 0xAD47A394 : /* 'software' */ |
867 | 285 | psf_store_string (psf, SF_STR_SOFTWARE, value) ; |
868 | 285 | break ; |
869 | 89 | case 0x5D178E2A : /* 'copyright' */ |
870 | 89 | psf_store_string (psf, SF_STR_COPYRIGHT, value) ; |
871 | 89 | break ; |
872 | 247 | case 0x60E4D0C8 : /* 'artist' */ |
873 | 247 | psf_store_string (psf, SF_STR_ARTIST, value) ; |
874 | 247 | break ; |
875 | 145 | case 0x83B5D16A : /* 'genre' */ |
876 | 145 | psf_store_string (psf, SF_STR_GENRE, value) ; |
877 | 145 | break ; |
878 | 267 | case 0x15E5FC88 : /* 'comment' */ |
879 | 486 | case 0x7C297D5B : /* 'comments' */ |
880 | 486 | psf_store_string (psf, SF_STR_COMMENT, value) ; |
881 | 486 | break ; |
882 | 332 | case 0x24A7C347 : /* 'tracknumber' */ |
883 | 332 | psf_store_string (psf, SF_STR_TRACKNUMBER, value) ; |
884 | 332 | break ; |
885 | 198 | case 0x50A31EB7 : /* 'date' */ |
886 | 198 | psf_store_string (psf, SF_STR_DATE, value) ; |
887 | 198 | break ; |
888 | 297 | case 0x6583545A : /* 'album' */ |
889 | 297 | psf_store_string (psf, SF_STR_ALBUM, value) ; |
890 | 297 | break ; |
891 | 144 | case 0xE7C64B6C : /* 'license' */ |
892 | 144 | psf_store_string (psf, SF_STR_LICENSE, value) ; |
893 | 144 | break ; |
894 | 165k | default : |
895 | 165k | psf_log_printf (psf, " Unhandled hash 0x%x : /* '%s' */\n", hash, key) ; |
896 | 165k | break ; |
897 | 167k | } ; |
898 | | |
899 | 167k | key = value + strlen (value) + 1 ; |
900 | 167k | } ; |
901 | | |
902 | 904 | free (buf) ; |
903 | | |
904 | 904 | return 0 ; |
905 | 904 | } /* caf_read_strings */ |
906 | | |
907 | | struct put_buffer |
908 | | { uint32_t index ; |
909 | | char s [16 * 1024] ; |
910 | | } ; |
911 | | |
912 | | static uint32_t |
913 | | put_key_value (struct put_buffer * buf, const char * key, const char * value) |
914 | 0 | { uint32_t written ; |
915 | |
|
916 | 0 | if (buf->index + strlen (key) + strlen (value) + 2 > sizeof (buf->s)) |
917 | 0 | return 0 ; |
918 | | |
919 | 0 | written = snprintf (buf->s + buf->index, sizeof (buf->s) - buf->index, "%s%c%s%c", key, 0, value, 0) ; |
920 | |
|
921 | 0 | if (buf->index + written >= sizeof (buf->s)) |
922 | 0 | return 0 ; |
923 | | |
924 | 0 | buf->index += written ; |
925 | 0 | return 1 ; |
926 | 0 | } /* put_key_value */ |
927 | | |
928 | | static void |
929 | | caf_write_strings (SF_PRIVATE * psf, int location) |
930 | 0 | { struct put_buffer buf ; |
931 | 0 | const char * cptr ; |
932 | 0 | uint32_t k, string_count = 0 ; |
933 | |
|
934 | 0 | memset (&buf, 0, sizeof (buf)) ; |
935 | |
|
936 | 0 | for (k = 0 ; k < SF_MAX_STRINGS ; k++) |
937 | 0 | { if (psf->strings.data [k].type == 0) |
938 | 0 | break ; |
939 | | |
940 | 0 | if (psf->strings.data [k].flags != location) |
941 | 0 | continue ; |
942 | | |
943 | 0 | if ((cptr = psf_get_string (psf, psf->strings.data [k].type)) == NULL) |
944 | 0 | continue ; |
945 | | |
946 | 0 | switch (psf->strings.data [k].type) |
947 | 0 | { case SF_STR_TITLE : |
948 | 0 | string_count += put_key_value (&buf, "title", cptr) ; |
949 | 0 | break ; |
950 | 0 | case SF_STR_COPYRIGHT : |
951 | 0 | string_count += put_key_value (&buf, "copyright", cptr) ; |
952 | 0 | break ; |
953 | 0 | case SF_STR_SOFTWARE : |
954 | 0 | string_count += put_key_value (&buf, "software", cptr) ; |
955 | 0 | break ; |
956 | 0 | case SF_STR_ARTIST : |
957 | 0 | string_count += put_key_value (&buf, "artist", cptr) ; |
958 | 0 | break ; |
959 | 0 | case SF_STR_COMMENT : |
960 | 0 | string_count += put_key_value (&buf, "comment", cptr) ; |
961 | 0 | break ; |
962 | 0 | case SF_STR_DATE : |
963 | 0 | string_count += put_key_value (&buf, "date", cptr) ; |
964 | 0 | break ; |
965 | 0 | case SF_STR_ALBUM : |
966 | 0 | string_count += put_key_value (&buf, "album", cptr) ; |
967 | 0 | break ; |
968 | 0 | case SF_STR_LICENSE : |
969 | 0 | string_count += put_key_value (&buf, "license", cptr) ; |
970 | 0 | break ; |
971 | 0 | case SF_STR_TRACKNUMBER : |
972 | 0 | string_count += put_key_value (&buf, "tracknumber", cptr) ; |
973 | 0 | break ; |
974 | 0 | case SF_STR_GENRE : |
975 | 0 | string_count += put_key_value (&buf, "genre", cptr) ; |
976 | 0 | break ; |
977 | | |
978 | 0 | default : |
979 | 0 | break ; |
980 | 0 | } ; |
981 | 0 | } ; |
982 | |
|
983 | 0 | if (string_count == 0 || buf.index == 0) |
984 | 0 | return ; |
985 | | |
986 | 0 | psf_binheader_writef (psf, "Em84b", BHWm (info_MARKER), BHW8 (buf.index + 4), BHW4 (string_count), BHWv (buf.s), BHWz (buf.index)) ; |
987 | 0 | } /* caf_write_strings */ |
988 | | |
989 | | /*============================================================================== |
990 | | */ |
991 | | |
992 | | static int |
993 | | caf_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) |
994 | 0 | { return psf_save_write_chunk (&psf->wchunks, chunk_info) ; |
995 | 0 | } /* caf_set_chunk */ |
996 | | |
997 | | static SF_CHUNK_ITERATOR * |
998 | | caf_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) |
999 | 1.17k | { return psf_next_chunk_iterator (&psf->rchunks, iterator) ; |
1000 | 1.17k | } /* caf_next_chunk_iterator */ |
1001 | | |
1002 | | static int |
1003 | | caf_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) |
1004 | 1.02k | { int indx ; |
1005 | | |
1006 | 1.02k | if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0) |
1007 | 0 | return SFE_UNKNOWN_CHUNK ; |
1008 | | |
1009 | 1.02k | chunk_info->datalen = psf->rchunks.chunks [indx].len ; |
1010 | | |
1011 | 1.02k | return SFE_NO_ERROR ; |
1012 | 1.02k | } /* caf_get_chunk_size */ |
1013 | | |
1014 | | static int |
1015 | | caf_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) |
1016 | 1.02k | { int indx ; |
1017 | 1.02k | sf_count_t pos ; |
1018 | | |
1019 | 1.02k | if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0) |
1020 | 0 | return SFE_UNKNOWN_CHUNK ; |
1021 | | |
1022 | 1.02k | if (chunk_info->data == NULL) |
1023 | 0 | return SFE_BAD_CHUNK_DATA_PTR ; |
1024 | | |
1025 | 1.02k | chunk_info->id_size = psf->rchunks.chunks [indx].id_size ; |
1026 | 1.02k | memcpy (chunk_info->id, psf->rchunks.chunks [indx].id, sizeof (chunk_info->id) / sizeof (*chunk_info->id)) ; |
1027 | | |
1028 | 1.02k | pos = psf_ftell (psf) ; |
1029 | 1.02k | psf_fseek (psf, psf->rchunks.chunks [indx].offset, SEEK_SET) ; |
1030 | 1.02k | psf_fread (chunk_info->data, SF_MIN (chunk_info->datalen, psf->rchunks.chunks [indx].len), 1, psf) ; |
1031 | 1.02k | psf_fseek (psf, pos, SEEK_SET) ; |
1032 | | |
1033 | 1.02k | return SFE_NO_ERROR ; |
1034 | 1.02k | } /* caf_get_chunk_data */ |