[Sound-open-firmware] [PATCH v2 2/3] tune: new component for file IO
Ranjani Sridharan
ranjani.sridharan at linux.intel.com
Thu May 10 18:36:32 CEST 2018
On Thu, 2018-05-10 at 16:40 +0100, Liam Girdwood wrote:
> On Wed, 2018-05-09 at 15:58 -0700, Ranjani Sridharan wrote:
> > This patch adds a new file component that testbench
> > can use to read in samples and write out processed samples.
> >
> > Signed-off-by: Ranjani Sridharan <ranjani.sridharan at linux.intel.com
> > >
> > ---
> > tune/include/file.h | 71 +++++++
> > tune/src/file.c | 602
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 673 insertions(+)
> > create mode 100644 tune/include/file.h
> > create mode 100644 tune/src/file.c
> >
> > diff --git a/tune/include/file.h b/tune/include/file.h
> > new file mode 100644
> > index 0000000..07ce4aa
> > --- /dev/null
> > +++ b/tune/include/file.h
> > @@ -0,0 +1,71 @@
> > +/*
> > + * 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,
> > +};
> > +
> > +/* file component state */
> > +struct file_state {
> > + char *fn;
> > + FILE *rfh, *wfh; /* read/write file handle */
> > + int reached_eof;
> > + int n;
> > + enum file_mode mode;
> > +};
> > +
> > +/* 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
> > diff --git a/tune/src/file.c b/tune/src/file.c
> > new file mode 100644
> > index 0000000..049432b
> > --- /dev/null
> > +++ b/tune/src/file.c
> > @@ -0,0 +1,602 @@
> > +/*
> > + * 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>
> > + * 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 "common_test.h"
> > +#include "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
> > + * TODO: support binary input 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 */
>
> Can you put newlines before all comments/blocks (in all files), it's
> breaks
> things up nicely :) (I don't care what checkpatch says about this -
> will fix).
Yes, sure.
>
> > + 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 */
> > + if (fmt == SOF_IPC_FRAME_S32_LE)
> > + ret = fscanf(cd->fs.rfh,
> > "%d", dest);
>
>
> Why do we do an fscanf() here ?
The testbench currently only handles txt input files generated using
octave. My next action item to be able to read raw pcm files as well.
>
>
> > + /* mask bits if 24-bit samples */
> > + if (fmt == SOF_IPC_FRAME_S24_4LE)
> > {
> > + ret = fscanf(cd->fs.rfh,
> > "%d",
> > &sample);
> > + *dest = sample &
> > 0x00ffffff;
> > + }
> > + dest++;
> > + /* quit if eof is reached */
> > + if (ret == EOF) {
> > + cd->fs.reached_eof = 1;
> > + goto quit;
> > + }
> > + 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
> > + * TODO: support binary input 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);
> > + dest++;
> > + if (ret == EOF) {
> > + cd->fs.reached_eof = 1;
> > + goto quit;
> > + }
> > + 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
> > + * TODO: support binary input 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++) {
> > + /* write sample to file */
> > + ret = fprintf(cd->fs.wfh, "%d\n",
> > + *src);
> > + src++;
> > + if (ret < 0)
> > + goto quit;
> > + 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
> > + * TODO: support binary input 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;
> > + int32_t sample;
> > + int i, n_wrap, n_min, ret;
> > + int n_samples = 0;
> > +
> > + /* 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++) {
> > + /* write sample to file */
> > + 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);
> > + }
> > + src++;
> > + if (ret < 0) {
> > + //cd->fs.write_fail = 1;
>
> code to be removed ?
Yes, will remove it.
> Liam
>
> > + goto quit;
> > + }
> > + 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, sink, 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 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 == NULL)
> > + 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 = malloc(sizeof(*cd));
> > + if (cd == NULL) {
> > + 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 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 == NULL) {
> > + printf("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 == NULL) {
> > + printf("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;
> > +
> > + return dev;
> > +}
> > +
> > +static void file_free(struct comp_dev *dev)
> > +{
> > + struct file_data *td = comp_get_drvdata(dev);
> > + struct file_comp_data *cd = comp_get_drvdata(dev);
> > +
> > + fclose(cd->fs.rfh);
> > + free(td);
> > + free(dev);
> > +}
> > +
> > +/* 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);
> > +
> > + /* 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 */
> > + 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;
> > + }
> > +
> > + switch (config->frame_fmt) {
> > + case(SOF_IPC_FRAME_S16_LE):
> > + /* set downstream buffer size */
> > + 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):
> > + /* set downstream buffer size */
> > + ret = buffer_set_size(buffer, dev->frames * 4 *
> > + 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_s24;
> > + break;
> > + case(SOF_IPC_FRAME_S32_LE):
> > + /* set downstream buffer size */
> > + ret = buffer_set_size(buffer, dev->frames * 4 *
> > + periods * dev->params.channels);
> > + if (ret < 0) {
> > + printf("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);
> > +}
More information about the Sound-open-firmware
mailing list