X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/992d59159547267e1491fcd1c5123765b4c452b8..63cf293f572ae7d5c1c83b9dffb31e7d774f8854:/interpretor/lib/src/libsndfile-1.0.25/src/caf.c diff --git a/interpretor/lib/src/libsndfile-1.0.25/src/caf.c b/interpretor/lib/src/libsndfile-1.0.25/src/caf.c new file mode 100644 index 0000000..99e9117 --- /dev/null +++ b/interpretor/lib/src/libsndfile-1.0.25/src/caf.c @@ -0,0 +1,620 @@ +/* +** Copyright (C) 2005-2011 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "sfconfig.h" + +#include +#include +#include +#include +#include +#include + +#include "sndfile.h" +#include "sfendian.h" +#include "common.h" +#include "chanmap.h" + +/*------------------------------------------------------------------------------ +** Macros to handle big/little endian issues. +*/ + +#define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ') +#define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c') +#define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w') +#define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f') +#define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n') +#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a') +#define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c') +#define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't') +#define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e') +#define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4') +#define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o') +#define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't') +#define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i') +#define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm') +#define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k') +#define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i') +#define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1') +#define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2') +#define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3') +#define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w') +#define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't') +#define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k') +#define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n') +#define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g') +#define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd') +#define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd') +#define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w') +#define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3') +#define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6') + +#define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8))) + +#define SFE_CAF_NOT_CAF 666 +#define SFE_CAF_NO_DESC 667 +#define SFE_CAF_BAD_PEAK 668 + +/*------------------------------------------------------------------------------ +** Typedefs. +*/ + +typedef struct +{ unsigned char srate [8] ; + unsigned int fmt_id ; + unsigned int fmt_flags ; + unsigned int pkt_bytes ; + unsigned int pkt_frames ; + unsigned int channels_per_frame ; + unsigned int bits_per_chan ; +} DESC_CHUNK ; + +typedef struct +{ int chanmap_tag ; +} CAF_PRIVATE ; + +/*------------------------------------------------------------------------------ +** Private static functions. +*/ + +static int caf_close (SF_PRIVATE *psf) ; +static int caf_read_header (SF_PRIVATE *psf) ; +static int caf_write_header (SF_PRIVATE *psf, int calc_length) ; +static int caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; +static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ; + +/*------------------------------------------------------------------------------ +** Public function. +*/ + +int +caf_open (SF_PRIVATE *psf) +{ int subformat, format, error = 0 ; + + if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0)) + { if ((error = caf_read_header (psf))) + return error ; + } ; + + subformat = SF_CODEC (psf->sf.format) ; + + if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL) + return SFE_MALLOC_FAILED ; + + if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) + { if (psf->is_pipe) + return SFE_NO_PIPE_WRITE ; + + format = SF_CONTAINER (psf->sf.format) ; + if (format != SF_FORMAT_CAF) + return SFE_BAD_OPEN_FORMAT ; + + psf->blockwidth = psf->bytewidth * psf->sf.channels ; + + if (psf->file.mode != SFM_RDWR || psf->filelength < 44) + { psf->filelength = 0 ; + psf->datalength = 0 ; + psf->dataoffset = 0 ; + psf->sf.frames = 0 ; + } ; + + psf->str_flags = SF_STR_ALLOW_START ; + + /* + ** By default, add the peak chunk to floating point files. Default behaviour + ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE). + */ + if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) + { if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + psf->peak_info->peak_loc = SF_PEAK_START ; + } ; + + if ((error = caf_write_header (psf, SF_FALSE)) != 0) + return error ; + + psf->write_header = caf_write_header ; + } ; + + psf->container_close = caf_close ; + psf->command = caf_command ; + + switch (subformat) + { case SF_FORMAT_PCM_S8 : + case SF_FORMAT_PCM_16 : + case SF_FORMAT_PCM_24 : + case SF_FORMAT_PCM_32 : + error = pcm_init (psf) ; + break ; + + case SF_FORMAT_ULAW : + error = ulaw_init (psf) ; + break ; + + case SF_FORMAT_ALAW : + error = alaw_init (psf) ; + break ; + + /* Lite remove start */ + case SF_FORMAT_FLOAT : + error = float32_init (psf) ; + break ; + + case SF_FORMAT_DOUBLE : + error = double64_init (psf) ; + break ; + /* Lite remove end */ + + default : + return SFE_UNSUPPORTED_ENCODING ; + } ; + + return error ; +} /* caf_open */ + +static int +caf_close (SF_PRIVATE *psf) +{ + if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) + caf_write_header (psf, SF_TRUE) ; + + return 0 ; +} /* caf_close */ + +static int +caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize)) +{ CAF_PRIVATE *pcaf ; + + if ((pcaf = psf->container_data) == NULL) + return SFE_INTERNAL ; + + switch (command) + { case SFC_SET_CHANNEL_MAP_INFO : + pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ; + return (pcaf->chanmap_tag != 0) ; + + default : + break ; + } ; + + return 0 ; +} /* caf_command */ + +/*------------------------------------------------------------------------------ +*/ + +static int +decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc) +{ int format ; + + psf->sf.channels = desc->channels_per_frame ; + + format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ; + + if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1) + { /* Floating point data. */ + if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame) + { psf->bytewidth = 4 ; + return format | SF_FORMAT_FLOAT ; + } ; + if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame) + { psf->bytewidth = 8 ; + return format | SF_FORMAT_DOUBLE ; + } ; + } ; + + if ((desc->fmt_flags & 1) != 0) + { psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ; + return 0 ; + } ; + + if (desc->fmt_id == lpcm_MARKER) + { /* Integer data. */ + if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame) + { psf->bytewidth = 4 ; + return format | SF_FORMAT_PCM_32 ; + } ; + if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame) + { psf->bytewidth = 3 ; + return format | SF_FORMAT_PCM_24 ; + } ; + if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame) + { psf->bytewidth = 2 ; + return format | SF_FORMAT_PCM_16 ; + } ; + if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame) + { psf->bytewidth = 1 ; + return format | SF_FORMAT_PCM_S8 ; + } ; + } ; + + if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8) + { psf->bytewidth = 1 ; + return format | SF_FORMAT_ALAW ; + } ; + + if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8) + { psf->bytewidth = 1 ; + return format | SF_FORMAT_ULAW ; + } ; + + return 0 ; +} /* decode_desc_chunk */ + +static int +caf_read_header (SF_PRIVATE *psf) +{ DESC_CHUNK desc ; + sf_count_t chunk_size ; + double srate ; + short version, flags ; + int marker, k, have_data = 0, error ; + + memset (&desc, 0, sizeof (desc)) ; + + /* Set position to start of file to begin reading header. */ + psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ; + psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ; + if (marker != caff_MARKER) + return SFE_CAF_NOT_CAF ; + + psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ; + srate = double64_be_read (psf->u.ucbuf) ; + snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ; + psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ; + if (marker != desc_MARKER) + return SFE_CAF_NO_DESC ; + + if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK)) + { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ; + return SFE_MALFORMED_FILE ; + } ; + + psf->sf.samplerate = lrint (srate) ; + + psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames, + &desc.channels_per_frame, &desc.bits_per_chan) ; + psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n" + " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n", + desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ; + + if (desc.channels_per_frame > SF_MAX_CHANNELS) + { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ; + return SFE_MALFORMED_FILE ; + } ; + + if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK)) + psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ; + + psf->sf.channels = desc.channels_per_frame ; + + while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker)) + { psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ; + + switch (marker) + { case peak_MARKER : + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) + { psf_binheader_readf (psf, "j", (int) chunk_size) ; + psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; + return SFE_CAF_BAD_PEAK ; + } ; + + if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) + return SFE_MALLOC_FAILED ; + + /* read in rest of PEAK chunk. */ + psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ; + psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ; + + psf_log_printf (psf, " Ch Position Value\n") ; + for (k = 0 ; k < psf->sf.channels ; k++) + { sf_count_t position ; + float value ; + + psf_binheader_readf (psf, "Ef8", &value, &position) ; + psf->peak_info->peaks [k].value = value ; + psf->peak_info->peaks [k].position = position ; + + snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ; + psf_log_printf (psf, psf->u.cbuf) ; + } ; + + psf->peak_info->peak_loc = SF_PEAK_START ; + break ; + + case chan_MARKER : + if (chunk_size < 12) + { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; + psf_binheader_readf (psf, "j", (int) chunk_size) ; + break ; + } + + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + + if ((error = caf_read_chanmap (psf, chunk_size))) + return error ; + break ; + + case free_MARKER : + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + psf_binheader_readf (psf, "j", (int) chunk_size) ; + break ; + + case data_MARKER : + if (psf->filelength > 0 && chunk_size + psf->headindex != psf->filelength) + psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, chunk_size + 4) ; + else + psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; + psf_binheader_readf (psf, "E4", &k) ; + psf_log_printf (psf, " edit : %u\n", k) ; + have_data = 1 ; + break ; + + default : + psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ; + psf_binheader_readf (psf, "j", (int) chunk_size) ; + break ; + } ; + } ; + + if (have_data == 0) + { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ; + return SFE_MALFORMED_FILE ; + } ; + + psf_log_printf (psf, "End\n") ; + + psf->dataoffset = psf_ftell (psf) ; + psf->datalength = psf->filelength - psf->dataoffset ; + psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; + + if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0) + return SFE_UNSUPPORTED_ENCODING ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / psf->bytewidth ; + + return 0 ; +} /* caf_read_header */ + +/*------------------------------------------------------------------------------ +*/ + +static int +caf_write_header (SF_PRIVATE *psf, int calc_length) +{ CAF_PRIVATE *pcaf ; + DESC_CHUNK desc ; + sf_count_t current, free_len ; + int subformat ; + + if ((pcaf = psf->container_data) == NULL) + return SFE_INTERNAL ; + + memset (&desc, 0, sizeof (desc)) ; + + current = psf_ftell (psf) ; + + if (calc_length) + { psf->filelength = psf_get_filelen (psf) ; + + psf->datalength = psf->filelength - psf->dataoffset ; + + if (psf->dataend) + psf->datalength -= psf->filelength - psf->dataend ; + + if (psf->bytewidth > 0) + psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; + } ; + + /* Reset the current header length to zero. */ + psf->header [0] = 0 ; + psf->headindex = 0 ; + psf_fseek (psf, 0, SEEK_SET) ; + + /* 'caff' marker, version and flags. */ + psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ; + + /* 'desc' marker and chunk size. */ + psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ; + + double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ; + psf_binheader_writef (psf, "b", psf->u.ucbuf, make_size_t (8)) ; + + subformat = SF_CODEC (psf->sf.format) ; + + psf->endian = SF_ENDIAN (psf->sf.format) ; + + if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) + psf->endian = SF_ENDIAN_BIG ; + else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU)) + psf->endian = SF_ENDIAN_LITTLE ; + + if (psf->endian == SF_ENDIAN_LITTLE) + desc.fmt_flags = 2 ; + else + psf->endian = SF_ENDIAN_BIG ; + + /* initial section (same for all, it appears) */ + switch (subformat) + { case SF_FORMAT_PCM_S8 : + desc.fmt_id = lpcm_MARKER ; + psf->bytewidth = 1 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 8 ; + break ; + + case SF_FORMAT_PCM_16 : + desc.fmt_id = lpcm_MARKER ; + psf->bytewidth = 2 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 16 ; + break ; + + case SF_FORMAT_PCM_24 : + psf->bytewidth = 3 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 24 ; + desc.fmt_id = lpcm_MARKER ; + break ; + + case SF_FORMAT_PCM_32 : + desc.fmt_id = lpcm_MARKER ; + psf->bytewidth = 4 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 32 ; + break ; + + case SF_FORMAT_FLOAT : + desc.fmt_id = lpcm_MARKER ; + desc.fmt_flags |= 1 ; + psf->bytewidth = 4 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 32 ; + break ; + + case SF_FORMAT_DOUBLE : + desc.fmt_id = lpcm_MARKER ; + desc.fmt_flags |= 1 ; + psf->bytewidth = 8 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 64 ; + break ; + + case SF_FORMAT_ALAW : + desc.fmt_id = alaw_MARKER ; + psf->bytewidth = 1 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 8 ; + break ; + + case SF_FORMAT_ULAW : + desc.fmt_id = ulaw_MARKER ; + psf->bytewidth = 1 ; + desc.pkt_bytes = psf->bytewidth * psf->sf.channels ; + desc.pkt_frames = 1 ; + desc.channels_per_frame = psf->sf.channels ; + desc.bits_per_chan = 8 ; + break ; + + default : + return SFE_UNIMPLEMENTED ; + } ; + + 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) ; + +#if 0 + if (psf->str_flags & SF_STR_LOCATE_START) + caf_write_strings (psf, SF_STR_LOCATE_START) ; +#endif + + if (psf->peak_info != NULL) + { int k ; + psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ; + for (k = 0 ; k < psf->sf.channels ; k++) + psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ; + } ; + + if (psf->channel_map && pcaf->chanmap_tag) + psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ; + + /* Add free chunk so that the actual audio data starts at a multiple 0x1000. */ + free_len = 0x1000 - psf->headindex - 16 - 12 ; + while (free_len < 0) + free_len += 0x1000 ; + psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ; + + psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ; + + psf_fwrite (psf->header, psf->headindex, 1, psf) ; + if (psf->error) + return psf->error ; + + psf->dataoffset = psf->headindex ; + if (current < psf->dataoffset) + psf_fseek (psf, psf->dataoffset, SEEK_SET) ; + else if (current > 0) + psf_fseek (psf, current, SEEK_SET) ; + + return psf->error ; +} /* caf_write_header */ + +static int +caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) +{ const AIFF_CAF_CHANNEL_MAP * map_info ; + unsigned channel_bitmap, channel_decriptions, bytesread ; + int layout_tag ; + + bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ; + + map_info = aiff_caf_of_channel_layout_tag (layout_tag) ; + + psf_log_printf (psf, " Tag : %x\n", layout_tag) ; + if (map_info) + psf_log_printf (psf, " Layout : %s\n", map_info->name) ; + + if (bytesread < chunk_size) + psf_binheader_readf (psf, "j", chunk_size - bytesread) ; + + if (map_info->channel_map != NULL) + { size_t chanmap_size = psf->sf.channels * sizeof (psf->channel_map [0]) ; + + free (psf->channel_map) ; + + if ((psf->channel_map = malloc (chanmap_size)) == NULL) + return SFE_MALLOC_FAILED ; + + memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ; + } ; + + return 0 ; +} /* caf_read_chanmap */ +