|
Packit |
3ae693 |
/*-*- Mode: C; c-basic-offset: 8 -*-*/
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
/***
|
|
Packit |
3ae693 |
This file is part of libcanberra.
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
Copyright 2008 Lennart Poettering
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
libcanberra is free software; you can redistribute it and/or modify
|
|
Packit |
3ae693 |
it under the terms of the GNU Lesser General Public License as
|
|
Packit |
3ae693 |
published by the Free Software Foundation, either version 2.1 of the
|
|
Packit |
3ae693 |
License, or (at your option) any later version.
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
libcanberra is distributed in the hope that it will be useful, but
|
|
Packit |
3ae693 |
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
3ae693 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
3ae693 |
Lesser General Public License for more details.
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
You should have received a copy of the GNU Lesser General Public
|
|
Packit |
3ae693 |
License along with libcanberra. If not, see
|
|
Packit |
3ae693 |
<http://www.gnu.org/licenses/>.
|
|
Packit |
3ae693 |
***/
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
3ae693 |
#include <config.h>
|
|
Packit |
3ae693 |
#endif
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
#include "canberra.h"
|
|
Packit |
3ae693 |
#include "read-wav.h"
|
|
Packit |
3ae693 |
#include "macro.h"
|
|
Packit |
3ae693 |
#include "malloc.h"
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
#define FILE_SIZE_MAX (64U*1024U*1024U)
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
/* Stores the bit indexes in dwChannelMask */
|
|
Packit |
3ae693 |
enum {
|
|
Packit |
3ae693 |
BIT_FRONT_LEFT,
|
|
Packit |
3ae693 |
BIT_FRONT_RIGHT,
|
|
Packit |
3ae693 |
BIT_FRONT_CENTER,
|
|
Packit |
3ae693 |
BIT_LOW_FREQUENCY,
|
|
Packit |
3ae693 |
BIT_BACK_LEFT,
|
|
Packit |
3ae693 |
BIT_BACK_RIGHT,
|
|
Packit |
3ae693 |
BIT_FRONT_LEFT_OF_CENTER,
|
|
Packit |
3ae693 |
BIT_FRONT_RIGHT_OF_CENTER,
|
|
Packit |
3ae693 |
BIT_BACK_CENTER,
|
|
Packit |
3ae693 |
BIT_SIDE_LEFT,
|
|
Packit |
3ae693 |
BIT_SIDE_RIGHT,
|
|
Packit |
3ae693 |
BIT_TOP_CENTER,
|
|
Packit |
3ae693 |
BIT_TOP_FRONT_LEFT,
|
|
Packit |
3ae693 |
BIT_TOP_FRONT_CENTER,
|
|
Packit |
3ae693 |
BIT_TOP_FRONT_RIGHT,
|
|
Packit |
3ae693 |
BIT_TOP_BACK_LEFT,
|
|
Packit |
3ae693 |
BIT_TOP_BACK_CENTER,
|
|
Packit |
3ae693 |
BIT_TOP_BACK_RIGHT,
|
|
Packit |
3ae693 |
_BIT_MAX
|
|
Packit |
3ae693 |
};
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
static const ca_channel_position_t channel_table[_BIT_MAX] = {
|
|
Packit |
3ae693 |
[BIT_FRONT_LEFT] = CA_CHANNEL_FRONT_LEFT,
|
|
Packit |
3ae693 |
[BIT_FRONT_RIGHT] = CA_CHANNEL_FRONT_RIGHT,
|
|
Packit |
3ae693 |
[BIT_FRONT_CENTER] = CA_CHANNEL_FRONT_CENTER,
|
|
Packit |
3ae693 |
[BIT_LOW_FREQUENCY] = CA_CHANNEL_LFE,
|
|
Packit |
3ae693 |
[BIT_BACK_LEFT] = CA_CHANNEL_REAR_LEFT,
|
|
Packit |
3ae693 |
[BIT_BACK_RIGHT] = CA_CHANNEL_REAR_RIGHT,
|
|
Packit |
3ae693 |
[BIT_FRONT_LEFT_OF_CENTER] = CA_CHANNEL_FRONT_LEFT_OF_CENTER,
|
|
Packit |
3ae693 |
[BIT_FRONT_RIGHT_OF_CENTER] = CA_CHANNEL_FRONT_RIGHT_OF_CENTER,
|
|
Packit |
3ae693 |
[BIT_BACK_CENTER] = CA_CHANNEL_REAR_CENTER,
|
|
Packit |
3ae693 |
[BIT_SIDE_LEFT] = CA_CHANNEL_SIDE_LEFT,
|
|
Packit |
3ae693 |
[BIT_SIDE_RIGHT] = CA_CHANNEL_SIDE_RIGHT,
|
|
Packit |
3ae693 |
[BIT_TOP_CENTER] = CA_CHANNEL_TOP_CENTER,
|
|
Packit |
3ae693 |
[BIT_TOP_FRONT_LEFT] = CA_CHANNEL_TOP_FRONT_LEFT,
|
|
Packit |
3ae693 |
[BIT_TOP_FRONT_CENTER] = CA_CHANNEL_TOP_FRONT_CENTER,
|
|
Packit |
3ae693 |
[BIT_TOP_FRONT_RIGHT] = CA_CHANNEL_TOP_FRONT_RIGHT,
|
|
Packit |
3ae693 |
[BIT_TOP_BACK_LEFT] = CA_CHANNEL_TOP_REAR_LEFT,
|
|
Packit |
3ae693 |
[BIT_TOP_BACK_CENTER] = CA_CHANNEL_TOP_REAR_CENTER,
|
|
Packit |
3ae693 |
[BIT_TOP_BACK_RIGHT] = CA_CHANNEL_TOP_REAR_RIGHT
|
|
Packit |
3ae693 |
};
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
struct ca_wav {
|
|
Packit |
3ae693 |
FILE *file;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
off_t data_size;
|
|
Packit |
3ae693 |
unsigned nchannels;
|
|
Packit |
3ae693 |
unsigned rate;
|
|
Packit |
3ae693 |
unsigned depth;
|
|
Packit |
3ae693 |
uint32_t channel_mask;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_channel_position_t channel_map[_BIT_MAX];
|
|
Packit |
3ae693 |
};
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
#define CHUNK_ID_DATA 0x61746164U
|
|
Packit |
3ae693 |
#define CHUNK_ID_FMT 0x20746d66U
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
static const uint8_t pcm_guid[16] = {
|
|
Packit |
3ae693 |
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
|
|
Packit |
3ae693 |
0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
|
|
Packit |
3ae693 |
};
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
static int skip_to_chunk(ca_wav *w, uint32_t id, uint32_t *size) {
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_return_val_if_fail(w, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(size, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
for (;;) {
|
|
Packit |
3ae693 |
uint32_t chunk[2];
|
|
Packit |
3ae693 |
uint32_t s;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (fread(chunk, sizeof(uint32_t), CA_ELEMENTSOF(chunk), w->file) != CA_ELEMENTSOF(chunk))
|
|
Packit |
3ae693 |
goto fail_io;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
s = CA_UINT32_FROM_LE(chunk[1]);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (s <= 0 || s >= FILE_SIZE_MAX)
|
|
Packit |
3ae693 |
return CA_ERROR_TOOBIG;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (CA_UINT32_FROM_LE(chunk[0]) == id) {
|
|
Packit |
3ae693 |
*size = s;
|
|
Packit |
3ae693 |
break;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (fseek(w->file, (long) s, SEEK_CUR) < 0)
|
|
Packit |
3ae693 |
return CA_ERROR_SYSTEM;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return CA_SUCCESS;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
fail_io:
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (feof(w->file))
|
|
Packit |
3ae693 |
return CA_ERROR_CORRUPT;
|
|
Packit |
3ae693 |
else if (ferror(w->file))
|
|
Packit |
3ae693 |
return CA_ERROR_SYSTEM;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_assert_not_reached();
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
int ca_wav_open(ca_wav **_w, FILE *f) {
|
|
Packit |
3ae693 |
uint32_t header[3], fmt_chunk[10];
|
|
Packit |
3ae693 |
int ret;
|
|
Packit |
3ae693 |
ca_wav *w;
|
|
Packit |
3ae693 |
uint32_t file_size, fmt_size, data_size;
|
|
Packit |
3ae693 |
ca_bool_t extensible;
|
|
Packit |
3ae693 |
uint32_t format;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_return_val_if_fail(_w, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(f, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (!(w = ca_new(ca_wav, 1)))
|
|
Packit |
3ae693 |
return CA_ERROR_OOM;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
w->file = f;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (fread(header, sizeof(uint32_t), CA_ELEMENTSOF(header), f) != CA_ELEMENTSOF(header))
|
|
Packit |
3ae693 |
goto fail_io;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (CA_UINT32_FROM_LE(header[0]) != 0x46464952U ||
|
|
Packit |
3ae693 |
CA_UINT32_FROM_LE(header[2]) != 0x45564157U) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_CORRUPT;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
file_size = CA_UINT32_FROM_LE(header[1]);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (file_size <= 0 || file_size >= FILE_SIZE_MAX) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_TOOBIG;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
/* Skip to the fmt chunk */
|
|
Packit |
3ae693 |
if ((ret = skip_to_chunk(w, CHUNK_ID_FMT, &fmt_size)) < 0)
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
switch (fmt_size) {
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
case 14: /* WAVEFORMAT */
|
|
Packit |
3ae693 |
case 16:
|
|
Packit |
3ae693 |
case 18: /* WAVEFORMATEX */
|
|
Packit |
3ae693 |
extensible = FALSE;
|
|
Packit |
3ae693 |
break;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
case 40: /* WAVEFORMATEXTENSIBLE */
|
|
Packit |
3ae693 |
extensible = TRUE;
|
|
Packit |
3ae693 |
break;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
default:
|
|
Packit |
3ae693 |
ret = CA_ERROR_NOTSUPPORTED;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (fread(fmt_chunk, 1, fmt_size, f) != fmt_size)
|
|
Packit |
3ae693 |
goto fail_io;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
/* PCM? or WAVEX? */
|
|
Packit |
3ae693 |
format = (CA_UINT32_FROM_LE(fmt_chunk[0]) & 0xFFFF);
|
|
Packit |
3ae693 |
if ((!extensible && format != 0x0001) ||
|
|
Packit |
3ae693 |
(extensible && format != 0xFFFE)) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_NOTSUPPORTED;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (extensible) {
|
|
Packit |
3ae693 |
if (memcmp(fmt_chunk + 6, pcm_guid, 16) != 0) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_NOTSUPPORTED;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
w->channel_mask = CA_UINT32_FROM_LE(fmt_chunk[5]);
|
|
Packit |
3ae693 |
} else
|
|
Packit |
3ae693 |
w->channel_mask = 0;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
w->nchannels = CA_UINT32_FROM_LE(fmt_chunk[0]) >> 16;
|
|
Packit |
3ae693 |
w->rate = CA_UINT32_FROM_LE(fmt_chunk[1]);
|
|
Packit |
3ae693 |
w->depth = CA_UINT32_FROM_LE(fmt_chunk[3]) >> 16;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (w->nchannels <= 0 || w->rate <= 0) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_CORRUPT;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (w->depth != 16 && w->depth != 8) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_NOTSUPPORTED;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
/* Skip to the data chunk */
|
|
Packit |
3ae693 |
if ((ret = skip_to_chunk(w, CHUNK_ID_DATA, &data_size)) < 0)
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
w->data_size = (off_t) data_size;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if ((w->data_size % (w->depth/8)) != 0) {
|
|
Packit |
3ae693 |
ret = CA_ERROR_CORRUPT;
|
|
Packit |
3ae693 |
goto fail;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
*_w = w;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return CA_SUCCESS;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
fail_io:
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (feof(f))
|
|
Packit |
3ae693 |
ret = CA_ERROR_CORRUPT;
|
|
Packit |
3ae693 |
else if (ferror(f))
|
|
Packit |
3ae693 |
ret = CA_ERROR_SYSTEM;
|
|
Packit |
3ae693 |
else
|
|
Packit |
3ae693 |
ca_assert_not_reached();
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
fail:
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_free(w);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return ret;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
void ca_wav_close(ca_wav *w) {
|
|
Packit |
3ae693 |
ca_assert(w);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
fclose(w->file);
|
|
Packit |
3ae693 |
ca_free(w);
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
unsigned ca_wav_get_nchannels(ca_wav *w) {
|
|
Packit |
3ae693 |
ca_assert(w);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return w->nchannels;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
unsigned ca_wav_get_rate(ca_wav *w) {
|
|
Packit |
3ae693 |
ca_assert(w);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return w->rate;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
const ca_channel_position_t* ca_wav_get_channel_map(ca_wav *w) {
|
|
Packit |
3ae693 |
unsigned c;
|
|
Packit |
3ae693 |
ca_channel_position_t *p;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_assert(w);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (!w->channel_mask)
|
|
Packit |
3ae693 |
return NULL;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
p = w->channel_map;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
for (c = 0; c < _BIT_MAX; c++)
|
|
Packit |
3ae693 |
if ((w->channel_mask & (1 << c)))
|
|
Packit |
3ae693 |
*(p++) = channel_table[c];
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_assert(p <= w->channel_map + _BIT_MAX);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (p != w->channel_map + w->nchannels)
|
|
Packit |
3ae693 |
return NULL;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return w->channel_map;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_sample_type_t ca_wav_get_sample_type(ca_wav *w) {
|
|
Packit |
3ae693 |
ca_assert(w);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return w->depth == 16 ?
|
|
Packit |
3ae693 |
#ifdef WORDS_BIGENDIAN
|
|
Packit |
3ae693 |
CA_SAMPLE_S16RE
|
|
Packit |
3ae693 |
#else
|
|
Packit |
3ae693 |
CA_SAMPLE_S16NE
|
|
Packit |
3ae693 |
#endif
|
|
Packit |
3ae693 |
: CA_SAMPLE_U8;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
int ca_wav_read_s16le(ca_wav *w, int16_t *d, size_t *n) {
|
|
Packit |
3ae693 |
off_t remaining;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_return_val_if_fail(w, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(w->depth == 16, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(d, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(n, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(*n > 0, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
remaining = w->data_size / (off_t) sizeof(int16_t);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if ((off_t) *n > remaining)
|
|
Packit |
3ae693 |
*n = (size_t) remaining;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (*n > 0) {
|
|
Packit |
3ae693 |
*n = fread(d, sizeof(int16_t), *n, w->file);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (*n <= 0 && ferror(w->file))
|
|
Packit |
3ae693 |
return CA_ERROR_SYSTEM;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_assert(w->data_size >= (off_t) *n * (off_t) sizeof(int16_t));
|
|
Packit |
3ae693 |
w->data_size -= (off_t) *n * (off_t) sizeof(int16_t);
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return CA_SUCCESS;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
int ca_wav_read_u8(ca_wav *w, uint8_t *d, size_t *n) {
|
|
Packit |
3ae693 |
off_t remaining;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_return_val_if_fail(w, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(w->depth == 8, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(d, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(n, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
ca_return_val_if_fail(*n > 0, CA_ERROR_INVALID);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
remaining = w->data_size / (off_t) sizeof(uint8_t);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if ((off_t) *n > remaining)
|
|
Packit |
3ae693 |
*n = (size_t) remaining;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (*n > 0) {
|
|
Packit |
3ae693 |
*n = fread(d, sizeof(uint8_t), *n, w->file);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
if (*n <= 0 && ferror(w->file))
|
|
Packit |
3ae693 |
return CA_ERROR_SYSTEM;
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
ca_assert(w->data_size >= (off_t) *n * (off_t) sizeof(uint8_t));
|
|
Packit |
3ae693 |
w->data_size -= (off_t) *n * (off_t) sizeof(uint8_t);
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return CA_SUCCESS;
|
|
Packit |
3ae693 |
}
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
off_t ca_wav_get_size(ca_wav *v) {
|
|
Packit |
3ae693 |
ca_return_val_if_fail(v, (off_t) -1);
|
|
Packit |
3ae693 |
|
|
Packit |
3ae693 |
return v->data_size;
|
|
Packit |
3ae693 |
}
|