Coverage Report

Created: 2025-07-18 06:14

/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 */