HelenOS sources
This source file includes following definitions.
- rwave_encode_fmt
- rwave_decode_fmt
- rwave_wopen
- rwave_write_samples
- rwave_wclose
- rwave_ropen
- rwave_read_samples
- rwave_rclose
#include <assert.h>
#include <byteorder.h>
#include <errno.h>
#include <macros.h>
#include <mem.h>
#include <riff/chunk.h>
#include <riff/rwave.h>
#include <stdlib.h>
static void rwave_encode_fmt(rwave_params_t *params, rwave_fmt_t *fmt)
{
int bytes_smp;
bytes_smp = (params->bits_smp + 7) / 8;
fmt->format_tag = host2uint16_t_le(WFMT_PCM);
fmt->channels = host2uint16_t_le(params->channels);
fmt->smp_sec = host2uint32_t_le(params->smp_freq);
fmt->avg_bytes_sec = host2uint32_t_le(bytes_smp * params->smp_freq *
params->channels);
fmt->block_align = host2uint16_t_le(bytes_smp);
fmt->bits_smp = host2uint16_t_le(params->bits_smp);
}
static int rwave_decode_fmt(rwave_fmt_t *fmt, rwave_params_t *params)
{
uint16_t fmt_tag;
fmt_tag = uint16_t_le2host(fmt->format_tag);
printf("fmt_tag=0x%x\n", fmt_tag);
if (fmt_tag != WFMT_PCM)
return EINVAL;
params->channels = uint16_t_le2host(fmt->channels);
params->smp_freq = uint32_t_le2host(fmt->smp_sec);
params->bits_smp = uint16_t_le2host(fmt->bits_smp);
return EOK;
}
errno_t rwave_wopen(const char *fname, rwave_params_t *params, rwavew_t **rww)
{
riff_wchunk_t fmt;
rwave_fmt_t rwfmt;
errno_t rc;
rwavew_t *ww;
rwave_encode_fmt(params, &rwfmt);
ww = calloc(1, sizeof(rwavew_t));
if (ww == NULL) {
rc = ENOMEM;
goto error;
}
ww->bufsize = 4096;
ww->buf = calloc(1, ww->bufsize);
if (ww->buf == NULL) {
rc = ENOMEM;
goto error;
}
ww->params = *params;
rc = riff_wopen(fname, &ww->rw);
if (rc != EOK) {
assert(rc == EIO || rc == ENOMEM);
goto error;
}
rc = riff_wchunk_start(ww->rw, CKID_RIFF, &ww->wave);
if (rc != EOK)
goto error;
rc = riff_write_uint32(ww->rw, FORM_WAVE);
if (rc != EOK)
goto error;
rc = riff_wchunk_start(ww->rw, CKID_fmt, &fmt);
if (rc != EOK)
goto error;
rc = riff_write(ww->rw, &rwfmt, sizeof(rwfmt));
if (rc != EOK)
goto error;
rc = riff_wchunk_end(ww->rw, &fmt);
if (rc != EOK)
goto error;
rc = riff_wchunk_start(ww->rw, CKID_data, &ww->data);
if (rc != EOK)
goto error;
*rww = ww;
return EOK;
error:
if (ww != NULL)
free(ww->buf);
if (ww->rw != NULL)
riff_wclose(ww->rw);
free(ww);
return rc;
}
errno_t rwave_write_samples(rwavew_t *ww, void *data, size_t bytes)
{
size_t i;
uint16_t *d16, *b16;
size_t now;
errno_t rc;
while (bytes > 0) {
now = min(bytes, ww->bufsize);
switch (ww->params.bits_smp / 8) {
case 1:
memcpy(ww->buf, data, now);
break;
case 2:
b16 = (uint16_t *)ww->buf;
d16 = (uint16_t *)data;
for (i = 0; i < now / 2; i++) {
b16[i] = host2uint16_t_le(d16[i]);
}
break;
default:
return ENOTSUP;
}
rc = riff_write(ww->rw, ww->buf, now);
if (rc != EOK) {
assert(rc == EIO);
return rc;
}
bytes -= now;
data += now;
}
return EOK;
}
errno_t rwave_wclose(rwavew_t *ww)
{
errno_t rc;
rc = riff_wchunk_end(ww->rw, &ww->wave);
if (rc == EOK)
rc = riff_wchunk_end(ww->rw, &ww->data);
rc = riff_wclose(ww->rw);
ww->rw = NULL;
free(ww->buf);
free(ww);
return rc;
}
errno_t rwave_ropen(const char *fname, rwave_params_t *params, rwaver_t **rwr)
{
rwaver_t *wr = NULL;
uint32_t form_id;
riff_rchunk_t fmt;
rwave_fmt_t wfmt;
size_t nread;
errno_t rc;
wr = calloc(1, sizeof(rwaver_t));
if (wr == NULL) {
rc = ENOMEM;
goto error;
}
rc = riff_ropen(fname, &wr->wave, &wr->rr);
if (rc != EOK) {
assert(rc == EIO || rc == ENOMEM);
goto error;
}
if (wr->wave.ckid != CKID_RIFF) {
printf("Not RIFF file\n");
rc = ENOMEM;
goto error;
}
rc = riff_read_uint32(&wr->wave, &form_id);
if (rc != EOK) {
assert(rc == EIO);
goto error;
}
if (form_id != FORM_WAVE) {
printf("wrong form ID\n");
rc = EIO;
goto error;
}
rc = riff_rchunk_start(&wr->wave, &fmt);
if (rc != EOK) {
assert(rc == EIO);
goto error;
}
if (fmt.ckid != CKID_fmt) {
printf("not fmt chunk\n");
rc = ENOMEM;
goto error;
}
rc = riff_read(&fmt, &wfmt, sizeof(rwave_fmt_t), &nread);
if (rc != EOK) {
printf("error reading fmt chunk\n");
assert(rc == EIO || rc == ELIMIT);
rc = EIO;
goto error;
}
if (nread < sizeof(rwave_fmt_t)) {
rc = EIO;
goto error;
}
rc = riff_rchunk_end(&fmt);
if (rc != EOK) {
assert(rc == EIO);
goto error;
}
rc = rwave_decode_fmt(&wfmt, params);
if (rc != EOK) {
printf("decode fmt fail\n");
assert(rc == EINVAL);
rc = EIO;
goto error;
}
rc = riff_rchunk_start(&wr->wave, &wr->data);
if (rc != EOK) {
assert(rc == EIO);
goto error;
}
if (wr->data.ckid != CKID_data) {
printf("not data ckid\n");
rc = EIO;
goto error;
}
*rwr = wr;
return EOK;
error:
if (wr != NULL && wr->rr != NULL)
riff_rclose(wr->rr);
free(wr);
return rc;
}
errno_t rwave_read_samples(rwaver_t *wr, void *buf, size_t bytes, size_t *nread)
{
errno_t rc;
rc = riff_read(&wr->data, buf, bytes, nread);
if (rc != EOK) {
assert(rc == EIO || rc == ELIMIT);
return EIO;
}
return EOK;
}
errno_t rwave_rclose(rwaver_t *wr)
{
errno_t rc;
rc = riff_rchunk_end(&wr->wave);
if (rc != EOK) {
assert(rc == EIO);
goto error;
}
riff_rclose(wr->rr);
free(wr);
return EOK;
error:
return rc;
}
HelenOS homepage, sources at GitHub