コード例 #1
0
ファイル: pcm_io.c プロジェクト: justinruggles/flake
int
pcmfile_seek_set(PcmFile *pf, uint64_t dest)
{
    FILE *fp = pf->io.fp;
    int slow_seek = !(pf->seekable);

    if(pf->seekable) {
        if(dest <= INT32_MAX) {
            // destination is within first 2GB
            if(fseek(fp, (long)dest, SEEK_SET)) return -1;
        } else {
            int64_t offset = (int64_t)dest - (int64_t)pf->filepos;
            if(offset >= INT32_MIN && offset <= INT32_MAX) {
                // offset is within +/- 2GB of file start
                if(fseek(fp, (long)offset, SEEK_CUR)) return -1;
            } else {
                // absolute offset is more than 2GB
                if(offset < 0) {
                    fprintf(stderr, "error: backward seeking is limited to 2GB\n");
                    return -1;
                } else {
                    fprintf(stderr, "warning: forward seeking more than 2GB will be slow.\n");
                }
                slow_seek = 1;
            }
        }
        byteio_flush(&pf->io);
    }
    if(slow_seek) {
        // do forward-only seek by reading data to temp buffer
        uint64_t offset;
        uint8_t buf[1024];

        if(dest < pf->filepos)
            return -1;

        for(offset = dest - pf->filepos; offset > 1024; offset -= 1024)
            byteio_read(buf, 1024, &pf->io);

        byteio_read(buf, offset, &pf->io);
    }
    pf->filepos = dest;

    return 0;
}
コード例 #2
0
ファイル: caff.c プロジェクト: 9060/wavtoac3encoder
/**
 * Reads a 2-byte big-endian word from the input stream
 */
static inline uint16_t
read2be(PcmFile *pf)
{
    uint16_t x;
    if (byteio_read(&x, 2, &pf->io) != 2)
        return 0;
    pf->filepos += 2;
    return be2me_16(x);
}
コード例 #3
0
ファイル: caff.c プロジェクト: 9060/wavtoac3encoder
/**
 * Reads a 4-byte big-endian word from the input stream
 */
static inline uint32_t
read4be(PcmFile *pf)
{
    uint32_t x;
    if (byteio_read(&x, 4, &pf->io) != 4)
        return 0;
    pf->filepos += 4;
    return be2me_32(x);
}
コード例 #4
0
ファイル: caff.c プロジェクト: 9060/wavtoac3encoder
/**
 * Reads a 8-byte big-endian word from the input stream
 */
static inline uint64_t
read8be(PcmFile *pf)
{
    uint64_t x;
    if (byteio_read(&x, 8, &pf->io) != 8)
        return 0;
    pf->filepos += 8;
    return be2me_64(x);
}
コード例 #5
0
ファイル: pcm_io.c プロジェクト: justinruggles/flake
int
pcmfile_read_samples(PcmFile *pf, void *output, int num_samples)
{
    uint8_t *buffer;
    uint8_t *read_buffer;
    uint32_t bytes_needed, buffer_size;
    int nr, i, j, bps, nsmp;

    // check input and limit number of samples
    if(pf == NULL || pf->io.fp == NULL || output == NULL || pf->fmt_convert == NULL) {
        fprintf(stderr, "null input to pcmfile_read_samples()\n");
        return -1;
    }
    if(pf->block_align <= 0) {
        fprintf(stderr, "invalid block_align\n");
        return -1;
    }
    num_samples = MIN(num_samples, PCM_MAX_READ);

    // calculate number of bytes to read, being careful not to read past
    // the end of the data chunk
    bytes_needed = pf->block_align * num_samples;
    if(!pf->read_to_eof) {
        if((pf->filepos + bytes_needed) >= (pf->data_start + pf->data_size)) {
            bytes_needed = (uint32_t)((pf->data_start + pf->data_size) - pf->filepos);
            num_samples = bytes_needed / pf->block_align;
        }
    }
    if(num_samples <= 0) return 0;

    // allocate temporary buffer for raw input data
    bps = pf->block_align / pf->channels;
    buffer_size = (bps != 3) ? bytes_needed : num_samples * sizeof(int32_t) * pf->channels;
    buffer = calloc(buffer_size+1, 1);
    if(!buffer) {
        fprintf(stderr, "error allocating read buffer\n");
        return -1;
    }
    read_buffer = buffer + (buffer_size - bytes_needed);

    // read raw audio samples from input stream into temporary buffer
    nr = byteio_read(read_buffer, bytes_needed, &pf->io);
    if (nr <= 0) {
        free(buffer);
        return nr;
    }
    pf->filepos += nr;
    nr /= pf->block_align;
    nsmp = nr * pf->channels;

    // do any necessary conversion based on source_format and read_format.
    // also do byte swapping when necessary based on source audio and system
    // byte orders.
    switch (bps) {
    case 2:
#ifdef WORDS_BIGENDIAN
        if(pf->order == PCM_BYTE_ORDER_LE)
#else
        if(pf->order == PCM_BYTE_ORDER_BE)
#endif
        {
            uint16_t *buf16 = (uint16_t *)buffer;
            for(i=0; i<nsmp; i++) {
                buf16[i] = bswap_16(buf16[i]);
            }
        }
        break;
    case 3:
        {
            int32_t *input = (int32_t*)buffer;
            int unused_bits = 32 - pf->bit_width;
            int32_t v;
            for(i=0,j=0; i<nsmp*bps; i+=bps,j++) {
#ifdef WORDS_BIGENDIAN
                if(pf->order == PCM_BYTE_ORDER_LE)
#else
                if(pf->order == PCM_BYTE_ORDER_BE)
#endif
                {
                    v = be2me_32((*(int32_t*)(read_buffer + i)) << 8);
                } else {
                    v = *(int32_t*)(read_buffer + i);
                }
                v <<= unused_bits; // clear unused high bits
                v >>= unused_bits; // sign extend
                input[j] = v;
            }
        }
        break;
    case 4:
#ifdef WORDS_BIGENDIAN
        if(pf->order == PCM_BYTE_ORDER_LE)
#else
        if(pf->order == PCM_BYTE_ORDER_BE)
#endif
        {
            uint32_t *buf32 = (uint32_t *)buffer;
            for(i=0; i<nsmp; i++) {
                buf32[i] = bswap_32(buf32[i]);
            }
        }
        break;
    default:
#ifdef WORDS_BIGENDIAN
        if(pf->order == PCM_BYTE_ORDER_LE)
#else
        if(pf->order == PCM_BYTE_ORDER_BE)
#endif
        {
            uint64_t *buf64 = (uint64_t *)buffer;
            for(i=0; i<nsmp; i++) {
                buf64[i] = bswap_64(buf64[i]);
            }
        }
        break;
    }
    pf->fmt_convert(output, buffer, nsmp);

    // free temporary buffer
    free(buffer);

    return nr;
}