int caf_read_frames(pcm_reader_t *preader, void *buffer, unsigned nframes)
{
    int rc;
    unsigned i, j, nbytes;
    caf_reader_t *reader = (caf_reader_t *)preader;
    unsigned bpf = reader->sample_format.bytes_per_frame;
    unsigned nchannels = reader->sample_format.channels_per_frame;
    unsigned bpc = bpf / nchannels;
    uint8_t tmp[64]; /* enough room for maximum bpf: 8ch float64 */
    uint8_t *bp;
    uint8_t *chanmap = reader->chanmap;

    if (nframes > reader->length - reader->position)
        nframes = reader->length - reader->position;
    nbytes = nframes * bpf;
    if (nbytes) {
        if ((rc = pcm_read(&reader->io, buffer, nbytes)) < 0)
            return -1;
        nframes = rc / bpf;
        for (bp = buffer, i = 0; i < nframes; ++i, bp += bpf) {
            memcpy(tmp, bp, bpf);
            for (j = 0; j < nchannels; ++j)
                memcpy(bp + bpc * j, tmp + bpc * chanmap[j], bpc);
        }
        reader->position += nframes;
    }
    if (nframes == 0) {
        /* fetch info after data chunk */
        uint32_t fcc;
        int64_t chunk_size;
        while ((fcc = caf_next_chunk(reader, &chunk_size)) != 0) {
            if (fcc == M4AF_FOURCC('i','n','f','o'))
                TRY_IO(caf_info(reader, chunk_size));
            else
                TRY_IO(pcm_skip(&reader->io, chunk_size));
        }
    }
    return nframes;
FAIL:
    return 0;
}
int caf_read_frames(pcm_reader_t *preader, void *buffer, unsigned nframes)
{
    int rc;
    unsigned i, j, nbytes;
    caf_reader_t *reader = (caf_reader_t *)preader;
    unsigned bpf = reader->sample_format.bytes_per_frame;
    unsigned nchannels = reader->sample_format.channels_per_frame;
    unsigned bpc = bpf / nchannels;
    uint8_t tmp[64];  
    uint8_t *bp;
    uint8_t *chanmap = reader->chanmap;

    if (nframes > reader->length - reader->position)
        nframes = reader->length - reader->position;
    nbytes = nframes * bpf;
    if (nbytes) {
        if ((rc = pcm_read(&reader->io, buffer, nbytes)) < 0)
            return -1;
        nframes = rc / bpf;
        for (bp = buffer, i = 0; i < nframes; ++i, bp += bpf) {
            memcpy(tmp, bp, bpf);
            for (j = 0; j < nchannels; ++j)
                memcpy(bp + bpc * j, tmp + bpc * chanmap[j], bpc);
        }
        reader->position += nframes;
    }
    if (nframes == 0) {
         
        uint32_t fcc;
        int64_t chunk_size;
        while ((fcc = caf_next_chunk(reader, &chunk_size)) != 0) {
            if (fcc == M4AF_FOURCC('i','n','f','o'))
                TRY_IO(caf_info(reader, chunk_size));
            else
                TRY_IO(pcm_skip(&reader->io, chunk_size));
        }
    }
    return nframes;
FAIL:
    return 0;
}