annotate src/libsndfile-1.0.25/src/caf.c @ 22:b07fe9e906dc

Portaudio: add missed file
author Chris Cannam
date Tue, 26 Mar 2013 12:14:11 +0000
parents c7265573341e
children
rev   line source
Chris@0 1 /*
Chris@0 2 ** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
Chris@0 3 **
Chris@0 4 ** This program is free software; you can redistribute it and/or modify
Chris@0 5 ** it under the terms of the GNU Lesser General Public License as published by
Chris@0 6 ** the Free Software Foundation; either version 2.1 of the License, or
Chris@0 7 ** (at your option) any later version.
Chris@0 8 **
Chris@0 9 ** This program is distributed in the hope that it will be useful,
Chris@0 10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 12 ** GNU Lesser General Public License for more details.
Chris@0 13 **
Chris@0 14 ** You should have received a copy of the GNU Lesser General Public License
Chris@0 15 ** along with this program; if not, write to the Free Software
Chris@0 16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Chris@0 17 */
Chris@0 18
Chris@0 19 #include "sfconfig.h"
Chris@0 20
Chris@0 21 #include <stdio.h>
Chris@0 22 #include <stdlib.h>
Chris@0 23 #include <string.h>
Chris@0 24 #include <ctype.h>
Chris@0 25 #include <math.h>
Chris@0 26 #include <inttypes.h>
Chris@0 27
Chris@0 28 #include "sndfile.h"
Chris@0 29 #include "sfendian.h"
Chris@0 30 #include "common.h"
Chris@0 31 #include "chanmap.h"
Chris@0 32
Chris@0 33 /*------------------------------------------------------------------------------
Chris@0 34 ** Macros to handle big/little endian issues.
Chris@0 35 */
Chris@0 36
Chris@0 37 #define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ')
Chris@0 38 #define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c')
Chris@0 39 #define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w')
Chris@0 40 #define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f')
Chris@0 41 #define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n')
Chris@0 42 #define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a')
Chris@0 43 #define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c')
Chris@0 44 #define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't')
Chris@0 45 #define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e')
Chris@0 46 #define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4')
Chris@0 47 #define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o')
Chris@0 48 #define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't')
Chris@0 49 #define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i')
Chris@0 50 #define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm')
Chris@0 51 #define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k')
Chris@0 52 #define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i')
Chris@0 53 #define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1')
Chris@0 54 #define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2')
Chris@0 55 #define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3')
Chris@0 56 #define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w')
Chris@0 57 #define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't')
Chris@0 58 #define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k')
Chris@0 59 #define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n')
Chris@0 60 #define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g')
Chris@0 61 #define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd')
Chris@0 62 #define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd')
Chris@0 63 #define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w')
Chris@0 64 #define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3')
Chris@0 65 #define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6')
Chris@0 66
Chris@0 67 #define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8)))
Chris@0 68
Chris@0 69 #define SFE_CAF_NOT_CAF 666
Chris@0 70 #define SFE_CAF_NO_DESC 667
Chris@0 71 #define SFE_CAF_BAD_PEAK 668
Chris@0 72
Chris@0 73 /*------------------------------------------------------------------------------
Chris@0 74 ** Typedefs.
Chris@0 75 */
Chris@0 76
Chris@0 77 typedef struct
Chris@0 78 { unsigned char srate [8] ;
Chris@0 79 unsigned int fmt_id ;
Chris@0 80 unsigned int fmt_flags ;
Chris@0 81 unsigned int pkt_bytes ;
Chris@0 82 unsigned int pkt_frames ;
Chris@0 83 unsigned int channels_per_frame ;
Chris@0 84 unsigned int bits_per_chan ;
Chris@0 85 } DESC_CHUNK ;
Chris@0 86
Chris@0 87 typedef struct
Chris@0 88 { int chanmap_tag ;
Chris@0 89 } CAF_PRIVATE ;
Chris@0 90
Chris@0 91 /*------------------------------------------------------------------------------
Chris@0 92 ** Private static functions.
Chris@0 93 */
Chris@0 94
Chris@0 95 static int caf_close (SF_PRIVATE *psf) ;
Chris@0 96 static int caf_read_header (SF_PRIVATE *psf) ;
Chris@0 97 static int caf_write_header (SF_PRIVATE *psf, int calc_length) ;
Chris@0 98 static int caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
Chris@0 99 static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ;
Chris@0 100
Chris@0 101 /*------------------------------------------------------------------------------
Chris@0 102 ** Public function.
Chris@0 103 */
Chris@0 104
Chris@0 105 int
Chris@0 106 caf_open (SF_PRIVATE *psf)
Chris@0 107 { int subformat, format, error = 0 ;
Chris@0 108
Chris@0 109 if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
Chris@0 110 { if ((error = caf_read_header (psf)))
Chris@0 111 return error ;
Chris@0 112 } ;
Chris@0 113
Chris@0 114 subformat = SF_CODEC (psf->sf.format) ;
Chris@0 115
Chris@0 116 if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL)
Chris@0 117 return SFE_MALLOC_FAILED ;
Chris@0 118
Chris@0 119 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
Chris@0 120 { if (psf->is_pipe)
Chris@0 121 return SFE_NO_PIPE_WRITE ;
Chris@0 122
Chris@0 123 format = SF_CONTAINER (psf->sf.format) ;
Chris@0 124 if (format != SF_FORMAT_CAF)
Chris@0 125 return SFE_BAD_OPEN_FORMAT ;
Chris@0 126
Chris@0 127 psf->blockwidth = psf->bytewidth * psf->sf.channels ;
Chris@0 128
Chris@0 129 if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
Chris@0 130 { psf->filelength = 0 ;
Chris@0 131 psf->datalength = 0 ;
Chris@0 132 psf->dataoffset = 0 ;
Chris@0 133 psf->sf.frames = 0 ;
Chris@0 134 } ;
Chris@0 135
Chris@0 136 psf->str_flags = SF_STR_ALLOW_START ;
Chris@0 137
Chris@0 138 /*
Chris@0 139 ** By default, add the peak chunk to floating point files. Default behaviour
Chris@0 140 ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
Chris@0 141 */
Chris@0 142 if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
Chris@0 143 { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
Chris@0 144 return SFE_MALLOC_FAILED ;
Chris@0 145 psf->peak_info->peak_loc = SF_PEAK_START ;
Chris@0 146 } ;
Chris@0 147
Chris@0 148 if ((error = caf_write_header (psf, SF_FALSE)) != 0)
Chris@0 149 return error ;
Chris@0 150
Chris@0 151 psf->write_header = caf_write_header ;
Chris@0 152 } ;
Chris@0 153
Chris@0 154 psf->container_close = caf_close ;
Chris@0 155 psf->command = caf_command ;
Chris@0 156
Chris@0 157 switch (subformat)
Chris@0 158 { case SF_FORMAT_PCM_S8 :
Chris@0 159 case SF_FORMAT_PCM_16 :
Chris@0 160 case SF_FORMAT_PCM_24 :
Chris@0 161 case SF_FORMAT_PCM_32 :
Chris@0 162 error = pcm_init (psf) ;
Chris@0 163 break ;
Chris@0 164
Chris@0 165 case SF_FORMAT_ULAW :
Chris@0 166 error = ulaw_init (psf) ;
Chris@0 167 break ;
Chris@0 168
Chris@0 169 case SF_FORMAT_ALAW :
Chris@0 170 error = alaw_init (psf) ;
Chris@0 171 break ;
Chris@0 172
Chris@0 173 /* Lite remove start */
Chris@0 174 case SF_FORMAT_FLOAT :
Chris@0 175 error = float32_init (psf) ;
Chris@0 176 break ;
Chris@0 177
Chris@0 178 case SF_FORMAT_DOUBLE :
Chris@0 179 error = double64_init (psf) ;
Chris@0 180 break ;
Chris@0 181 /* Lite remove end */
Chris@0 182
Chris@0 183 default :
Chris@0 184 return SFE_UNSUPPORTED_ENCODING ;
Chris@0 185 } ;
Chris@0 186
Chris@0 187 return error ;
Chris@0 188 } /* caf_open */
Chris@0 189
Chris@0 190 static int
Chris@0 191 caf_close (SF_PRIVATE *psf)
Chris@0 192 {
Chris@0 193 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
Chris@0 194 caf_write_header (psf, SF_TRUE) ;
Chris@0 195
Chris@0 196 return 0 ;
Chris@0 197 } /* caf_close */
Chris@0 198
Chris@0 199 static int
Chris@0 200 caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize))
Chris@0 201 { CAF_PRIVATE *pcaf ;
Chris@0 202
Chris@0 203 if ((pcaf = psf->container_data) == NULL)
Chris@0 204 return SFE_INTERNAL ;
Chris@0 205
Chris@0 206 switch (command)
Chris@0 207 { case SFC_SET_CHANNEL_MAP_INFO :
Chris@0 208 pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ;
Chris@0 209 return (pcaf->chanmap_tag != 0) ;
Chris@0 210
Chris@0 211 default :
Chris@0 212 break ;
Chris@0 213 } ;
Chris@0 214
Chris@0 215 return 0 ;
Chris@0 216 } /* caf_command */
Chris@0 217
Chris@0 218 /*------------------------------------------------------------------------------
Chris@0 219 */
Chris@0 220
Chris@0 221 static int
Chris@0 222 decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
Chris@0 223 { int format ;
Chris@0 224
Chris@0 225 psf->sf.channels = desc->channels_per_frame ;
Chris@0 226
Chris@0 227 format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ;
Chris@0 228
Chris@0 229 if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1)
Chris@0 230 { /* Floating point data. */
Chris@0 231 if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
Chris@0 232 { psf->bytewidth = 4 ;
Chris@0 233 return format | SF_FORMAT_FLOAT ;
Chris@0 234 } ;
Chris@0 235 if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame)
Chris@0 236 { psf->bytewidth = 8 ;
Chris@0 237 return format | SF_FORMAT_DOUBLE ;
Chris@0 238 } ;
Chris@0 239 } ;
Chris@0 240
Chris@0 241 if ((desc->fmt_flags & 1) != 0)
Chris@0 242 { psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ;
Chris@0 243 return 0 ;
Chris@0 244 } ;
Chris@0 245
Chris@0 246 if (desc->fmt_id == lpcm_MARKER)
Chris@0 247 { /* Integer data. */
Chris@0 248 if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
Chris@0 249 { psf->bytewidth = 4 ;
Chris@0 250 return format | SF_FORMAT_PCM_32 ;
Chris@0 251 } ;
Chris@0 252 if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame)
Chris@0 253 { psf->bytewidth = 3 ;
Chris@0 254 return format | SF_FORMAT_PCM_24 ;
Chris@0 255 } ;
Chris@0 256 if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame)
Chris@0 257 { psf->bytewidth = 2 ;
Chris@0 258 return format | SF_FORMAT_PCM_16 ;
Chris@0 259 } ;
Chris@0 260 if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame)
Chris@0 261 { psf->bytewidth = 1 ;
Chris@0 262 return format | SF_FORMAT_PCM_S8 ;
Chris@0 263 } ;
Chris@0 264 } ;
Chris@0 265
Chris@0 266 if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8)
Chris@0 267 { psf->bytewidth = 1 ;
Chris@0 268 return format | SF_FORMAT_ALAW ;
Chris@0 269 } ;
Chris@0 270
Chris@0 271 if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8)
Chris@0 272 { psf->bytewidth = 1 ;
Chris@0 273 return format | SF_FORMAT_ULAW ;
Chris@0 274 } ;
Chris@0 275
Chris@0 276 return 0 ;
Chris@0 277 } /* decode_desc_chunk */
Chris@0 278
Chris@0 279 static int
Chris@0 280 caf_read_header (SF_PRIVATE *psf)
Chris@0 281 { DESC_CHUNK desc ;
Chris@0 282 sf_count_t chunk_size ;
Chris@0 283 double srate ;
Chris@0 284 short version, flags ;
Chris@0 285 int marker, k, have_data = 0, error ;
Chris@0 286
Chris@0 287 memset (&desc, 0, sizeof (desc)) ;
Chris@0 288
Chris@0 289 /* Set position to start of file to begin reading header. */
Chris@0 290 psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ;
Chris@0 291 psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ;
Chris@0 292 if (marker != caff_MARKER)
Chris@0 293 return SFE_CAF_NOT_CAF ;
Chris@0 294
Chris@0 295 psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ;
Chris@0 296 srate = double64_be_read (psf->u.ucbuf) ;
Chris@0 297 snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ;
Chris@0 298 psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ;
Chris@0 299 if (marker != desc_MARKER)
Chris@0 300 return SFE_CAF_NO_DESC ;
Chris@0 301
Chris@0 302 if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK))
Chris@0 303 { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ;
Chris@0 304 return SFE_MALFORMED_FILE ;
Chris@0 305 } ;
Chris@0 306
Chris@0 307 psf->sf.samplerate = lrint (srate) ;
Chris@0 308
Chris@0 309 psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames,
Chris@0 310 &desc.channels_per_frame, &desc.bits_per_chan) ;
Chris@0 311 psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n"
Chris@0 312 " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n",
Chris@0 313 desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
Chris@0 314
Chris@0 315 if (desc.channels_per_frame > SF_MAX_CHANNELS)
Chris@0 316 { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ;
Chris@0 317 return SFE_MALFORMED_FILE ;
Chris@0 318 } ;
Chris@0 319
Chris@0 320 if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK))
Chris@0 321 psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ;
Chris@0 322
Chris@0 323 psf->sf.channels = desc.channels_per_frame ;
Chris@0 324
Chris@0 325 while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker))
Chris@0 326 { psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
Chris@0 327
Chris@0 328 switch (marker)
Chris@0 329 { case peak_MARKER :
Chris@0 330 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
Chris@0 331 if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
Chris@0 332 { psf_binheader_readf (psf, "j", (int) chunk_size) ;
Chris@0 333 psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
Chris@0 334 return SFE_CAF_BAD_PEAK ;
Chris@0 335 } ;
Chris@0 336
Chris@0 337 if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
Chris@0 338 return SFE_MALLOC_FAILED ;
Chris@0 339
Chris@0 340 /* read in rest of PEAK chunk. */
Chris@0 341 psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ;
Chris@0 342 psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ;
Chris@0 343
Chris@0 344 psf_log_printf (psf, " Ch Position Value\n") ;
Chris@0 345 for (k = 0 ; k < psf->sf.channels ; k++)
Chris@0 346 { sf_count_t position ;
Chris@0 347 float value ;
Chris@0 348
Chris@0 349 psf_binheader_readf (psf, "Ef8", &value, &position) ;
Chris@0 350 psf->peak_info->peaks [k].value = value ;
Chris@0 351 psf->peak_info->peaks [k].position = position ;
Chris@0 352
Chris@0 353 snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ;
Chris@0 354 psf_log_printf (psf, psf->u.cbuf) ;
Chris@0 355 } ;
Chris@0 356
Chris@0 357 psf->peak_info->peak_loc = SF_PEAK_START ;
Chris@0 358 break ;
Chris@0 359
Chris@0 360 case chan_MARKER :
Chris@0 361 if (chunk_size < 12)
Chris@0 362 { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ;
Chris@0 363 psf_binheader_readf (psf, "j", (int) chunk_size) ;
Chris@0 364 break ;
Chris@0 365 }
Chris@0 366
Chris@0 367 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
Chris@0 368
Chris@0 369 if ((error = caf_read_chanmap (psf, chunk_size)))
Chris@0 370 return error ;
Chris@0 371 break ;
Chris@0 372
Chris@0 373 case free_MARKER :
Chris@0 374 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
Chris@0 375 psf_binheader_readf (psf, "j", (int) chunk_size) ;
Chris@0 376 break ;
Chris@0 377
Chris@0 378 case data_MARKER :
Chris@0 379 if (psf->filelength > 0 && chunk_size + psf->headindex != psf->filelength)
Chris@0 380 psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, chunk_size + 4) ;
Chris@0 381 else
Chris@0 382 psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
Chris@0 383 psf_binheader_readf (psf, "E4", &k) ;
Chris@0 384 psf_log_printf (psf, " edit : %u\n", k) ;
Chris@0 385 have_data = 1 ;
Chris@0 386 break ;
Chris@0 387
Chris@0 388 default :
Chris@0 389 psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ;
Chris@0 390 psf_binheader_readf (psf, "j", (int) chunk_size) ;
Chris@0 391 break ;
Chris@0 392 } ;
Chris@0 393 } ;
Chris@0 394
Chris@0 395 if (have_data == 0)
Chris@0 396 { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ;
Chris@0 397 return SFE_MALFORMED_FILE ;
Chris@0 398 } ;
Chris@0 399
Chris@0 400 psf_log_printf (psf, "End\n") ;
Chris@0 401
Chris@0 402 psf->dataoffset = psf_ftell (psf) ;
Chris@0 403 psf->datalength = psf->filelength - psf->dataoffset ;
Chris@0 404 psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
Chris@0 405
Chris@0 406 if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0)
Chris@0 407 return SFE_UNSUPPORTED_ENCODING ;
Chris@0 408
Chris@0 409 if (psf->bytewidth > 0)
Chris@0 410 psf->sf.frames = psf->datalength / psf->bytewidth ;
Chris@0 411
Chris@0 412 return 0 ;
Chris@0 413 } /* caf_read_header */
Chris@0 414
Chris@0 415 /*------------------------------------------------------------------------------
Chris@0 416 */
Chris@0 417
Chris@0 418 static int
Chris@0 419 caf_write_header (SF_PRIVATE *psf, int calc_length)
Chris@0 420 { CAF_PRIVATE *pcaf ;
Chris@0 421 DESC_CHUNK desc ;
Chris@0 422 sf_count_t current, free_len ;
Chris@0 423 int subformat ;
Chris@0 424
Chris@0 425 if ((pcaf = psf->container_data) == NULL)
Chris@0 426 return SFE_INTERNAL ;
Chris@0 427
Chris@0 428 memset (&desc, 0, sizeof (desc)) ;
Chris@0 429
Chris@0 430 current = psf_ftell (psf) ;
Chris@0 431
Chris@0 432 if (calc_length)
Chris@0 433 { psf->filelength = psf_get_filelen (psf) ;
Chris@0 434
Chris@0 435 psf->datalength = psf->filelength - psf->dataoffset ;
Chris@0 436
Chris@0 437 if (psf->dataend)
Chris@0 438 psf->datalength -= psf->filelength - psf->dataend ;
Chris@0 439
Chris@0 440 if (psf->bytewidth > 0)
Chris@0 441 psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
Chris@0 442 } ;
Chris@0 443
Chris@0 444 /* Reset the current header length to zero. */
Chris@0 445 psf->header [0] = 0 ;
Chris@0 446 psf->headindex = 0 ;
Chris@0 447 psf_fseek (psf, 0, SEEK_SET) ;
Chris@0 448
Chris@0 449 /* 'caff' marker, version and flags. */
Chris@0 450 psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ;
Chris@0 451
Chris@0 452 /* 'desc' marker and chunk size. */
Chris@0 453 psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ;
Chris@0 454
Chris@0 455 double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ;
Chris@0 456 psf_binheader_writef (psf, "b", psf->u.ucbuf, make_size_t (8)) ;
Chris@0 457
Chris@0 458 subformat = SF_CODEC (psf->sf.format) ;
Chris@0 459
Chris@0 460 psf->endian = SF_ENDIAN (psf->sf.format) ;
Chris@0 461
Chris@0 462 if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
Chris@0 463 psf->endian = SF_ENDIAN_BIG ;
Chris@0 464 else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU))
Chris@0 465 psf->endian = SF_ENDIAN_LITTLE ;
Chris@0 466
Chris@0 467 if (psf->endian == SF_ENDIAN_LITTLE)
Chris@0 468 desc.fmt_flags = 2 ;
Chris@0 469 else
Chris@0 470 psf->endian = SF_ENDIAN_BIG ;
Chris@0 471
Chris@0 472 /* initial section (same for all, it appears) */
Chris@0 473 switch (subformat)
Chris@0 474 { case SF_FORMAT_PCM_S8 :
Chris@0 475 desc.fmt_id = lpcm_MARKER ;
Chris@0 476 psf->bytewidth = 1 ;
Chris@0 477 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 478 desc.pkt_frames = 1 ;
Chris@0 479 desc.channels_per_frame = psf->sf.channels ;
Chris@0 480 desc.bits_per_chan = 8 ;
Chris@0 481 break ;
Chris@0 482
Chris@0 483 case SF_FORMAT_PCM_16 :
Chris@0 484 desc.fmt_id = lpcm_MARKER ;
Chris@0 485 psf->bytewidth = 2 ;
Chris@0 486 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 487 desc.pkt_frames = 1 ;
Chris@0 488 desc.channels_per_frame = psf->sf.channels ;
Chris@0 489 desc.bits_per_chan = 16 ;
Chris@0 490 break ;
Chris@0 491
Chris@0 492 case SF_FORMAT_PCM_24 :
Chris@0 493 psf->bytewidth = 3 ;
Chris@0 494 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 495 desc.pkt_frames = 1 ;
Chris@0 496 desc.channels_per_frame = psf->sf.channels ;
Chris@0 497 desc.bits_per_chan = 24 ;
Chris@0 498 desc.fmt_id = lpcm_MARKER ;
Chris@0 499 break ;
Chris@0 500
Chris@0 501 case SF_FORMAT_PCM_32 :
Chris@0 502 desc.fmt_id = lpcm_MARKER ;
Chris@0 503 psf->bytewidth = 4 ;
Chris@0 504 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 505 desc.pkt_frames = 1 ;
Chris@0 506 desc.channels_per_frame = psf->sf.channels ;
Chris@0 507 desc.bits_per_chan = 32 ;
Chris@0 508 break ;
Chris@0 509
Chris@0 510 case SF_FORMAT_FLOAT :
Chris@0 511 desc.fmt_id = lpcm_MARKER ;
Chris@0 512 desc.fmt_flags |= 1 ;
Chris@0 513 psf->bytewidth = 4 ;
Chris@0 514 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 515 desc.pkt_frames = 1 ;
Chris@0 516 desc.channels_per_frame = psf->sf.channels ;
Chris@0 517 desc.bits_per_chan = 32 ;
Chris@0 518 break ;
Chris@0 519
Chris@0 520 case SF_FORMAT_DOUBLE :
Chris@0 521 desc.fmt_id = lpcm_MARKER ;
Chris@0 522 desc.fmt_flags |= 1 ;
Chris@0 523 psf->bytewidth = 8 ;
Chris@0 524 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 525 desc.pkt_frames = 1 ;
Chris@0 526 desc.channels_per_frame = psf->sf.channels ;
Chris@0 527 desc.bits_per_chan = 64 ;
Chris@0 528 break ;
Chris@0 529
Chris@0 530 case SF_FORMAT_ALAW :
Chris@0 531 desc.fmt_id = alaw_MARKER ;
Chris@0 532 psf->bytewidth = 1 ;
Chris@0 533 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 534 desc.pkt_frames = 1 ;
Chris@0 535 desc.channels_per_frame = psf->sf.channels ;
Chris@0 536 desc.bits_per_chan = 8 ;
Chris@0 537 break ;
Chris@0 538
Chris@0 539 case SF_FORMAT_ULAW :
Chris@0 540 desc.fmt_id = ulaw_MARKER ;
Chris@0 541 psf->bytewidth = 1 ;
Chris@0 542 desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
Chris@0 543 desc.pkt_frames = 1 ;
Chris@0 544 desc.channels_per_frame = psf->sf.channels ;
Chris@0 545 desc.bits_per_chan = 8 ;
Chris@0 546 break ;
Chris@0 547
Chris@0 548 default :
Chris@0 549 return SFE_UNIMPLEMENTED ;
Chris@0 550 } ;
Chris@0 551
Chris@0 552 psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
Chris@0 553
Chris@0 554 #if 0
Chris@0 555 if (psf->str_flags & SF_STR_LOCATE_START)
Chris@0 556 caf_write_strings (psf, SF_STR_LOCATE_START) ;
Chris@0 557 #endif
Chris@0 558
Chris@0 559 if (psf->peak_info != NULL)
Chris@0 560 { int k ;
Chris@0 561 psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ;
Chris@0 562 for (k = 0 ; k < psf->sf.channels ; k++)
Chris@0 563 psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
Chris@0 564 } ;
Chris@0 565
Chris@0 566 if (psf->channel_map && pcaf->chanmap_tag)
Chris@0 567 psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ;
Chris@0 568
Chris@0 569 /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
Chris@0 570 free_len = 0x1000 - psf->headindex - 16 - 12 ;
Chris@0 571 while (free_len < 0)
Chris@0 572 free_len += 0x1000 ;
Chris@0 573 psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ;
Chris@0 574
Chris@0 575 psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ;
Chris@0 576
Chris@0 577 psf_fwrite (psf->header, psf->headindex, 1, psf) ;
Chris@0 578 if (psf->error)
Chris@0 579 return psf->error ;
Chris@0 580
Chris@0 581 psf->dataoffset = psf->headindex ;
Chris@0 582 if (current < psf->dataoffset)
Chris@0 583 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
Chris@0 584 else if (current > 0)
Chris@0 585 psf_fseek (psf, current, SEEK_SET) ;
Chris@0 586
Chris@0 587 return psf->error ;
Chris@0 588 } /* caf_write_header */
Chris@0 589
Chris@0 590 static int
Chris@0 591 caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size)
Chris@0 592 { const AIFF_CAF_CHANNEL_MAP * map_info ;
Chris@0 593 unsigned channel_bitmap, channel_decriptions, bytesread ;
Chris@0 594 int layout_tag ;
Chris@0 595
Chris@0 596 bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ;
Chris@0 597
Chris@0 598 map_info = aiff_caf_of_channel_layout_tag (layout_tag) ;
Chris@0 599
Chris@0 600 psf_log_printf (psf, " Tag : %x\n", layout_tag) ;
Chris@0 601 if (map_info)
Chris@0 602 psf_log_printf (psf, " Layout : %s\n", map_info->name) ;
Chris@0 603
Chris@0 604 if (bytesread < chunk_size)
Chris@0 605 psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
Chris@0 606
Chris@0 607 if (map_info->channel_map != NULL)
Chris@0 608 { size_t chanmap_size = psf->sf.channels * sizeof (psf->channel_map [0]) ;
Chris@0 609
Chris@0 610 free (psf->channel_map) ;
Chris@0 611
Chris@0 612 if ((psf->channel_map = malloc (chanmap_size)) == NULL)
Chris@0 613 return SFE_MALLOC_FAILED ;
Chris@0 614
Chris@0 615 memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ;
Chris@0 616 } ;
Chris@0 617
Chris@0 618 return 0 ;
Chris@0 619 } /* caf_read_chanmap */
Chris@0 620