[Sound-open-firmware] [RFC PATCH 2/6] host: add new component for file IO
Ranjani Sridharan
ranjani.sridharan at linux.intel.com
Fri Jun 1 04:29:06 CEST 2018
This patch adds a new file component that testbench
can use to read in samples and write out processed samples. Both
text and raw pcm input formats are supported.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
---
src/host/file.c | 720 ++++++++++++++++++++++++++++++++++++++++
src/include/host/file.h | 77 +++++
2 files changed, 797 insertions(+)
create mode 100644 src/host/file.c
create mode 100644 src/include/host/file.h
diff --git a/src/host/file.c b/src/host/file.c
new file mode 100644
index 0000000..f0d420f
--- /dev/null
+++ b/src/host/file.c
@@ -0,0 +1,720 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author(s): Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+ * Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
+ */
+
+/* file component for reading/writing pcm samples to/from a file */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sof/sof.h>
+#include <sof/lock.h>
+#include <sof/list.h>
+#include <sof/stream.h>
+#include <sof/work.h>
+#include <sof/clock.h>
+#include <sof/audio/component.h>
+#include <sof/audio/format.h>
+#include <sof/audio/pipeline.h>
+#include <uapi/ipc.h>
+#include "host/common_test.h"
+#include "host/file.h"
+
+static inline void buffer_check_wrap_32(int32_t **ptr, int32_t *end,
+ size_t size)
+{
+ if (*ptr >= end)
+ *ptr = (int32_t *)((size_t)*ptr - size);
+}
+
+static inline void buffer_check_wrap_16(int16_t **ptr, int16_t *end,
+ size_t size)
+{
+ if (*ptr >= end)
+ *ptr = (int16_t *)((size_t)*ptr - size);
+}
+
+/*
+ * Read 32-bit samples from file
+ * currently only supports txt files
+ */
+static int read_samples_32(struct comp_dev *dev, struct comp_buffer *sink,
+ int n, int fmt, int nch)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int32_t *dest = (int32_t *)sink->w_ptr;
+ int32_t sample;
+ int n_samples = 0;
+ int i, n_wrap, n_min, ret;
+
+ while (n > 0) {
+ n_wrap = (int32_t *)sink->end_addr - dest;
+
+ /* check for buffer wrap and copy to the end of the buffer */
+ n_min = (n < n_wrap) ? n : n_wrap;
+ while (n_min > 0) {
+ n -= nch;
+ n_min -= nch;
+
+ /* copy sample per channel */
+ for (i = 0; i < nch; i++) {
+ /* read sample from file */
+ switch (cd->fs.f_format) {
+ /* text input file */
+ case FILE_TEXT:
+ if (fmt == SOF_IPC_FRAME_S32_LE)
+ ret = fscanf(cd->fs.rfh, "%d",
+ dest);
+
+ /* mask bits if 24-bit samples */
+ if (fmt == SOF_IPC_FRAME_S24_4LE) {
+ ret = fscanf(cd->fs.rfh, "%d",
+ &sample);
+ *dest = sample & 0x00ffffff;
+ }
+ /* quit if eof is reached */
+ if (ret == EOF) {
+ cd->fs.reached_eof = 1;
+ goto quit;
+ }
+ break;
+
+ /* raw input file */
+ default:
+ if (fmt == SOF_IPC_FRAME_S32_LE)
+ ret = fread(dest,
+ sizeof(int32_t),
+ 1, cd->fs.rfh);
+
+ /* mask bits if 24-bit samples */
+ if (fmt == SOF_IPC_FRAME_S24_4LE) {
+ ret = fread(&sample,
+ sizeof(int32_t),
+ 1, cd->fs.rfh);
+ *dest = sample & 0x00ffffff;
+ }
+ /* quit if eof is reached */
+ if (ret != 1) {
+ cd->fs.reached_eof = 1;
+ goto quit;
+ }
+ break;
+ }
+ dest++;
+ n_samples++;
+ }
+ }
+ /* check for buffer wrap and update pointer */
+ buffer_check_wrap_32(&dest, sink->end_addr,
+ sink->size);
+ }
+quit:
+ return n_samples;
+}
+
+/*
+ * Read 16-bit samples from file
+ * currently only supports txt files
+ */
+static int read_samples_16(struct comp_dev *dev, struct comp_buffer *sink,
+ int n, int nch)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int16_t *dest = (int16_t *)sink->w_ptr;
+ int i, n_wrap, n_min, ret;
+ int n_samples = 0;
+
+ /* copy samples */
+ while (n > 0) {
+ n_wrap = (int16_t *)sink->end_addr - dest;
+
+ /* check for buffer wrap and copy to the end of the buffer */
+ n_min = (n < n_wrap) ? n : n_wrap;
+ while (n_min > 0) {
+ n -= nch;
+ n_min -= nch;
+
+ /* copy sample per channel */
+ for (i = 0; i < nch; i++) {
+ /* read sample from file */
+ ret = fscanf(cd->fs.rfh, "%hd", dest);
+ switch (cd->fs.f_format) {
+ /* text input file */
+ case FILE_TEXT:
+ ret = fscanf(cd->fs.rfh, "%hd", dest);
+ if (ret == EOF) {
+ cd->fs.reached_eof = 1;
+ goto quit;
+ }
+ break;
+
+ /* rw pcm input file */
+ default:
+ ret = fread(dest, sizeof(int16_t), 1,
+ cd->fs.rfh);
+ if (ret != 1) {
+ cd->fs.reached_eof = 1;
+ goto quit;
+ }
+ break;
+ }
+
+ dest++;
+ n_samples++;
+ }
+ }
+ /* check for buffer wrap and update pointer */
+ buffer_check_wrap_16(&dest, sink->end_addr,
+ sink->size);
+ }
+
+quit:
+ return n_samples;
+}
+
+/*
+ * Write 16-bit samples from file
+ * currently only supports txt files
+ */
+static int write_samples_16(struct comp_dev *dev, struct comp_buffer *source,
+ int n, int nch)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int16_t *src = (int16_t *)source->r_ptr;
+ int i, n_wrap, n_min, ret;
+ int n_samples = 0;
+
+ /* copy samples */
+ while (n > 0) {
+ n_wrap = (int16_t *)source->end_addr - src;
+
+ /* check for buffer wrap and copy to the end of the buffer */
+ n_min = (n < n_wrap) ? n : n_wrap;
+ while (n_min > 0) {
+ n -= nch;
+ n_min -= nch;
+
+ /* copy sample per channel */
+ for (i = 0; i < nch; i++) {
+ switch (cd->fs.f_format) {
+ /* text output file */
+ case FILE_TEXT:
+ ret = fprintf(cd->fs.wfh,
+ "%d\n", *src);
+ if (ret < 0)
+ goto quit;
+ break;
+
+ /* raw pcm output file */
+ default:
+ ret = fwrite(src,
+ sizeof(int16_t),
+ 1, cd->fs.wfh);
+ if (ret != 1)
+ goto quit;
+ break;
+ }
+
+ src++;
+ n_samples++;
+ }
+ }
+ /* check for buffer wrap and update pointer */
+ buffer_check_wrap_16(&src, source->end_addr,
+ source->size);
+ }
+quit:
+ return n_samples;
+}
+
+/*
+ * Write 32-bit samples from file
+ * currently only supports txt files
+ */
+static int write_samples_32(struct comp_dev *dev, struct comp_buffer *source,
+ int n, int fmt, int nch)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int32_t *src = (int32_t *)source->r_ptr;
+ int i, n_wrap, n_min, ret;
+ int n_samples = 0;
+ int32_t sample;
+
+ /* copy samples */
+ while (n > 0) {
+ n_wrap = (int32_t *)source->end_addr - src;
+
+ /* check for buffer wrap and copy to the end of the buffer */
+ n_min = (n < n_wrap) ? n : n_wrap;
+ while (n_min > 0) {
+ n -= nch;
+ n_min -= nch;
+
+ /* copy sample per channel */
+ for (i = 0; i < nch; i++) {
+ switch (cd->fs.f_format) {
+ /* text output file */
+ case FILE_TEXT:
+ if (fmt == SOF_IPC_FRAME_S32_LE)
+ ret = fprintf(cd->fs.wfh,
+ "%d\n", *src);
+ if (fmt == SOF_IPC_FRAME_S24_4LE) {
+ sample = *src << 8;
+ ret = fprintf(cd->fs.wfh,
+ "%d\n",
+ sample >> 8);
+ }
+ if (ret < 0)
+ goto quit;
+ break;
+
+ /* raw pcm output file */
+ default:
+ if (fmt == SOF_IPC_FRAME_S32_LE)
+ ret = fwrite(src,
+ sizeof(int32_t),
+ 1, cd->fs.wfh);
+ if (fmt == SOF_IPC_FRAME_S24_4LE) {
+ sample = *src << 8;
+ sample >>= 8;
+ ret = fwrite(&sample,
+ sizeof(int32_t),
+ 1, cd->fs.wfh);
+ }
+ if (ret != 1)
+ goto quit;
+ break;
+ }
+
+ /* increment read pointer */
+ src++;
+
+ /* increment number of samples written */
+ n_samples++;
+ }
+ }
+ /* check for buffer wrap and update pointer */
+ buffer_check_wrap_32(&src, source->end_addr,
+ source->size);
+ }
+quit:
+ return n_samples;
+}
+
+/* function for processing 32-bit samples */
+static int file_s32_default(struct comp_dev *dev, struct comp_buffer *sink,
+ struct comp_buffer *source, uint32_t frames)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int nch = dev->params.channels;
+ int n_samples = 0;
+
+ switch (cd->fs.mode) {
+ case FILE_READ:
+ /* read samples */
+ n_samples = read_samples_32(dev, sink, frames * nch,
+ SOF_IPC_FRAME_S32_LE, nch);
+ break;
+ case FILE_WRITE:
+ /* write samples */
+ n_samples = write_samples_32(dev, source, frames * nch,
+ SOF_IPC_FRAME_S32_LE, nch);
+ break;
+ default:
+ /* TODO: duplex mode */
+ break;
+ }
+
+ cd->fs.n += n_samples;
+ return n_samples;
+}
+
+/* function for processing 16-bit samples */
+static int file_s16(struct comp_dev *dev, struct comp_buffer *sink,
+ struct comp_buffer *source, uint32_t frames)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int nch = dev->params.channels;
+ int n_samples = 0;
+
+ switch (cd->fs.mode) {
+ case FILE_READ:
+ /* read samples */
+ n_samples = read_samples_16(dev, sink, frames * nch, nch);
+ break;
+ case FILE_WRITE:
+ /* write samples */
+ n_samples = write_samples_16(dev, source, frames * nch, nch);
+ break;
+ default:
+ /* TODO: duplex mode */
+ break;
+ }
+
+ cd->fs.n += n_samples;
+ return n_samples;
+}
+
+/* function for processing 24-bit samples */
+static int file_s24(struct comp_dev *dev, struct comp_buffer *sink,
+ struct comp_buffer *source, uint32_t frames)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int nch = dev->params.channels;
+ int n_samples = 0;
+
+ switch (cd->fs.mode) {
+ case FILE_READ:
+ /* read samples */
+ n_samples = read_samples_32(dev, sink, frames * nch,
+ SOF_IPC_FRAME_S24_4LE, nch);
+ break;
+ case FILE_WRITE:
+ /* write samples */
+ n_samples = write_samples_32(dev, source, frames * nch,
+ SOF_IPC_FRAME_S24_4LE, nch);
+ break;
+ default:
+ /* TODO: duplex mode */
+ break;
+ }
+
+ cd->fs.n += n_samples;
+ return n_samples;
+}
+
+static enum file_format get_file_format(char *filename)
+{
+ char *ext = strrchr(filename, '.');
+
+ if (!strcmp(ext, ".txt"))
+ return FILE_TEXT;
+
+ return FILE_RAW;
+}
+
+static struct comp_dev *file_new(struct sof_ipc_comp *comp)
+{
+ struct comp_dev *dev;
+ struct sof_ipc_comp_file *file;
+ struct sof_ipc_comp_file *ipc_file =
+ (struct sof_ipc_comp_file *)comp;
+ struct file_comp_data *cd;
+
+ /* allocate memory for file comp */
+ dev = malloc(COMP_SIZE(struct sof_ipc_comp_file));
+ if (!dev)
+ return NULL;
+
+ /* copy file comp config */
+ file = (struct sof_ipc_comp_file *)&dev->comp;
+ memcpy(file, ipc_file, sizeof(struct sof_ipc_comp_file));
+
+ /* allocate memory for file comp data */
+ cd = rzalloc(RZONE_RUNTIME, SOF_MEM_CAPS_RAM, sizeof(*cd));
+ if (!cd) {
+ free(dev);
+ return NULL;
+ }
+
+ comp_set_drvdata(dev, cd);
+
+ /* default function for processing samples */
+ cd->file_func = file_s32_default;
+
+ /* get filename from IPC and open file */
+ cd->fs.fn = strdup(ipc_file->fn);
+
+ /* set file format */
+ cd->fs.f_format = get_file_format(cd->fs.fn);
+
+ /* set file comp mode */
+ cd->fs.mode = ipc_file->mode;
+
+ /* open file handle(s) depending on mode */
+ switch (cd->fs.mode) {
+ case FILE_READ:
+ cd->fs.rfh = fopen(cd->fs.fn, "r");
+ if (!cd->fs.rfh) {
+ fprintf(stderr, "error: opening file %s\n", cd->fs.fn);
+ free(cd);
+ free(dev);
+ return NULL;
+ }
+ break;
+ case FILE_WRITE:
+ cd->fs.wfh = fopen(cd->fs.fn, "w");
+ if (!cd->fs.wfh) {
+ fprintf(stderr, "error: opening file %s\n", cd->fs.fn);
+ free(cd);
+ free(dev);
+ return NULL;
+ }
+ break;
+ default:
+ /* TODO: duplex mode */
+ break;
+ }
+
+ cd->fs.reached_eof = 0;
+ cd->fs.n = 0;
+
+ dev->state = COMP_STATE_READY;
+
+ return dev;
+}
+
+static void file_free(struct comp_dev *dev)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+
+ if (cd->fs.mode == FILE_READ)
+ fclose(cd->fs.rfh);
+ else
+ fclose(cd->fs.wfh);
+
+ free(cd->fs.fn);
+ free(cd);
+ free(dev);
+
+ debug_print("free file component\n");
+}
+
+/* set component audio stream parameters */
+static int file_params(struct comp_dev *dev)
+{
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
+
+ /* for file endpoint set the following from topology config */
+ if (cd->fs.mode == FILE_WRITE) {
+ dev->params.frame_fmt = config->frame_fmt;
+ if (dev->params.frame_fmt == SOF_IPC_FRAME_S16_LE)
+ dev->params.sample_container_bytes = 2;
+ else
+ dev->params.sample_container_bytes = 4;
+ }
+
+ /* Need to compute this in non-host endpoint */
+ dev->frame_bytes =
+ dev->params.sample_container_bytes * dev->params.channels;
+
+ /* calculate period size based on config */
+ cd->period_bytes = dev->frames * dev->frame_bytes;
+
+ /* File to sink supports only S32_LE/S16_LE/S24_4LE PCM formats */
+ if (config->frame_fmt != SOF_IPC_FRAME_S32_LE &&
+ config->frame_fmt != SOF_IPC_FRAME_S24_4LE &&
+ config->frame_fmt != SOF_IPC_FRAME_S16_LE)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int fr_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata)
+{
+ return -EINVAL;
+}
+
+static int file_trigger(struct comp_dev *dev, int cmd)
+{
+ return comp_set_state(dev, cmd);
+}
+
+/* used to pass standard and bespoke commands (with data) to component */
+static int file_cmd(struct comp_dev *dev, int cmd, void *data)
+{
+ struct sof_ipc_ctrl_data *cdata = data;
+ int ret = 0;
+
+ switch (cmd) {
+ case COMP_CMD_SET_DATA:
+ ret = fr_cmd(dev, cdata);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * copy and process stream samples
+ * returns the number of bytes copied
+ */
+static int file_copy(struct comp_dev *dev)
+{
+ struct comp_buffer *buffer;
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int ret = 0, bytes;
+
+ switch (cd->fs.mode) {
+ case FILE_READ:
+ /* file component sink buffer */
+ buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
+ source_list);
+
+ /* test sink has enough free frames */
+ if (buffer->free >= cd->period_bytes && !cd->fs.reached_eof) {
+ /* read PCM samples from file */
+ ret = cd->file_func(dev, buffer, NULL, dev->frames);
+
+ /* update sink buffer pointers */
+ bytes = dev->params.sample_container_bytes;
+ if (ret > 0)
+ comp_update_buffer_produce(buffer,
+ ret * bytes);
+ }
+ break;
+ case FILE_WRITE:
+ /* file component source buffer */
+ buffer = list_first_item(&dev->bsource_list,
+ struct comp_buffer, sink_list);
+
+ /* test source has enough free frames */
+ if (buffer->avail >= cd->period_bytes) {
+ /* write PCM samples into file */
+ ret = cd->file_func(dev, NULL, buffer, dev->frames);
+
+ /* update source buffer pointers */
+ bytes = dev->params.sample_container_bytes;
+ if (ret > 0)
+ comp_update_buffer_consume(buffer,
+ ret * bytes);
+ }
+ break;
+ default:
+ /* TODO: duplex mode */
+ break;
+ }
+
+ return ret;
+}
+
+static int file_prepare(struct comp_dev *dev)
+{
+ struct sof_ipc_comp_config *config = COMP_GET_CONFIG(dev);
+ struct comp_buffer *buffer = NULL;
+ struct file_comp_data *cd = comp_get_drvdata(dev);
+ int ret = 0, periods;
+
+ /* file component sink/source buffer period count */
+ switch (cd->fs.mode) {
+ case FILE_READ:
+ buffer = list_first_item(&dev->bsink_list, struct comp_buffer,
+ source_list);
+ periods = config->periods_sink;
+ break;
+ case FILE_WRITE:
+ buffer = list_first_item(&dev->bsource_list,
+ struct comp_buffer, sink_list);
+ periods = config->periods_source;
+ break;
+ default:
+ /* TODO: duplex mode */
+ break;
+ }
+
+ if (!buffer) {
+ printf("error: no sink/source buffer\n");
+ return -EINVAL;
+ }
+
+ /* set downstream buffer size */
+ switch (config->frame_fmt) {
+ case(SOF_IPC_FRAME_S16_LE):
+ ret = buffer_set_size(buffer, dev->frames * 2 *
+ periods * dev->params.channels);
+ if (ret < 0) {
+ printf("error: file buffer size set\n");
+ return ret;
+ }
+ buffer_reset_pos(buffer);
+
+ /* set file function */
+ cd->file_func = file_s16;
+ break;
+ case(SOF_IPC_FRAME_S24_4LE):
+ ret = buffer_set_size(buffer, dev->frames * 4 *
+ periods * dev->params.channels);
+ if (ret < 0) {
+ fprintf(stderr, "error: file buffer size set\n");
+ return ret;
+ }
+ buffer_reset_pos(buffer);
+
+ /* set file function */
+ cd->file_func = file_s24;
+ break;
+ case(SOF_IPC_FRAME_S32_LE):
+ ret = buffer_set_size(buffer, dev->frames * 4 *
+ periods * dev->params.channels);
+ if (ret < 0) {
+ fprintf(stderr, "error: file buffer size set\n");
+ return ret;
+ }
+ buffer_reset_pos(buffer);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dev->state = COMP_STATE_PREPARE;
+
+ return ret;
+}
+
+static int file_reset(struct comp_dev *dev)
+{
+ dev->state = COMP_STATE_INIT;
+
+ return 0;
+}
+
+struct comp_driver comp_file = {
+ .type = SOF_COMP_FILEREAD,
+ .ops = {
+ .new = file_new,
+ .free = file_free,
+ .params = file_params,
+ .cmd = file_cmd,
+ .trigger = file_trigger,
+ .copy = file_copy,
+ .prepare = file_prepare,
+ .reset = file_reset,
+ },
+};
+
+void sys_comp_file_init(void)
+{
+ comp_register(&comp_file);
+}
diff --git a/src/include/host/file.h b/src/include/host/file.h
new file mode 100644
index 0000000..777b26d
--- /dev/null
+++ b/src/include/host/file.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Intel Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
+ * Liam Girdwood <liam.r.girdwood at linux.intel.com>
+ * Keyon Jie <yang.jie at linux.intel.com>
+ * Ranjani Sridharan <ranjani.sridharan at linux.intel.com>
+ */
+#ifndef _FILE_H
+#define _FILE_H
+
+/* file component modes */
+enum file_mode {
+ FILE_READ = 0,
+ FILE_WRITE,
+ FILE_DUPLEX,
+};
+
+enum file_format {
+ FILE_TEXT = 0,
+ FILE_RAW,
+};
+
+/* file component state */
+struct file_state {
+ char *fn;
+ FILE *rfh, *wfh; /* read/write file handle */
+ int reached_eof;
+ int n;
+ enum file_mode mode;
+ enum file_format f_format;
+};
+
+/* file comp data */
+struct file_comp_data {
+ uint32_t period_bytes;
+ uint32_t channels;
+ uint32_t frame_bytes;
+ uint32_t rate;
+ struct file_state fs;
+ int (*file_func)(struct comp_dev *dev, struct comp_buffer *sink,
+ struct comp_buffer *source, uint32_t frames);
+
+};
+
+/* file IO ipc comp */
+struct sof_ipc_comp_file {
+ struct sof_ipc_comp comp;
+ struct sof_ipc_comp_config config;
+ char *fn;
+ enum file_mode mode;
+};
+#endif
--
2.17.0
More information about the Sound-open-firmware
mailing list