Logo Search packages:      
Sourcecode: aften version File versions  Download package

int pcmfile_read_samples ( PcmFile *  pf,
void *  buffer,
int  num_samples 
)

Reads audio samples to the output buffer. Output is channel-interleaved, native byte order. Only up to PCM_MAX_READ samples can be read in one call. The output sample format depends on the value of pf->read_format. Returns number of samples read or -1 on error.

Definition at line 82 of file pcm_io.c.

Referenced by pcm_read_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:
        if (pf->order == PCM_NON_NATIVE_BYTE_ORDER) {
            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;
            if (pf->order == PCM_NON_NATIVE_BYTE_ORDER) {
                for (i = 0, j = 0; i < nsmp*bps; i += bps, j++) {
                    v = bswap_32(*(uint32_t*)(read_buffer + i) << 8);
                    v <<= unused_bits; // clear unused high bits
                    v >>= unused_bits; // sign extend
                    input[j] = v;
                }
            } else {
                for (i = 0, j = 0; i < nsmp*bps; i += bps, j++) {
                    v = *(int32_t*)(read_buffer + i);
                    v <<= unused_bits; // clear unused high bits
                    v >>= unused_bits; // sign extend
                    input[j] = v;
                }
            }
        }
        break;
    case 4:
        if (pf->order == PCM_NON_NATIVE_BYTE_ORDER) {
            uint32_t *buf32 = (uint32_t *)buffer;
            for (i = 0; i < nsmp; i++)
                buf32[i] = bswap_32(buf32[i]);
        }
        break;
    case 8:
        if (pf->order == PCM_NON_NATIVE_BYTE_ORDER) {
            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;
}


Generated by  Doxygen 1.6.0   Back to index