[Sound-open-firmware] [PATCH] volume: fix copy size incorrect issue
Keyon Jie
yang.jie at linux.intel.com
Thu Nov 16 16:04:18 CET 2017
The copy sizes for src and sink may be different,
here add fix to handle it.
Signed-off-by: Keyon Jie <yang.jie at linux.intel.com>
---
src/audio/volume.c | 38 +++++++++++++++++++++++++++++---------
src/include/reef/audio/buffer.h | 19 +++++++++++++++++++
2 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/src/audio/volume.c b/src/audio/volume.c
index 415a853..9cf766b 100644
--- a/src/audio/volume.c
+++ b/src/audio/volume.c
@@ -535,13 +535,27 @@ static int volume_cmd(struct comp_dev *dev, int cmd, void *data)
}
}
+static uint32_t get_frame_bytes(enum sof_ipc_frame frame_fmt, uint32_t chan)
+{
+ switch (frame_fmt) {
+ case SOF_IPC_FRAME_S16_LE:
+ return 2 * chan;
+ case SOF_IPC_FRAME_S24_4LE:
+ case SOF_IPC_FRAME_S32_LE:
+ return 4 * chan;
+ default:
+ return 0;
+ }
+}
+
/* copy and process stream data from source to sink buffers */
static int volume_copy(struct comp_dev *dev)
{
struct comp_data *cd = comp_get_drvdata(dev);
struct comp_buffer *sink;
struct comp_buffer *source;
- uint32_t copy_bytes;
+ uint32_t copy_src_bytes, copy_sink_bytes;
+ uint32_t copy_frames, src_frame_bytes, sink_frame_bytes;
tracev_volume("cpy");
@@ -549,16 +563,22 @@ static int volume_copy(struct comp_dev *dev)
source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list);
sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list);
+ src_frame_bytes = get_frame_bytes(cd->source_format, dev->params.channels);
+ sink_frame_bytes = get_frame_bytes(cd->sink_format, dev->params.channels);
+
/* get max number of bytes that can be copied */
- copy_bytes = comp_buffer_get_copy_bytes(dev, source, sink);
+ copy_frames = comp_buffer_get_copy_frames(source, src_frame_bytes,
+ sink, sink_frame_bytes);
+ copy_src_bytes = copy_frames * src_frame_bytes;
+ copy_sink_bytes = copy_frames * sink_frame_bytes;
/* Run volume if buffers have enough room */
- if (copy_bytes < cd->source_period_bytes) {
- comp_underrun(dev, source, copy_bytes, cd->source_period_bytes);
+ if (copy_src_bytes < cd->source_period_bytes) {
+ comp_underrun(dev, source, copy_src_bytes, cd->source_period_bytes);
return 0;
}
- if (copy_bytes < cd->sink_period_bytes) {
- comp_overrun(dev, sink, copy_bytes, cd->sink_period_bytes);
+ if (copy_sink_bytes < cd->sink_period_bytes) {
+ comp_overrun(dev, sink, copy_sink_bytes, cd->sink_period_bytes);
return 0;
}
@@ -566,10 +586,10 @@ static int volume_copy(struct comp_dev *dev)
cd->scale_vol(dev, sink, source, dev->frames);
/* calc new free and available */
- comp_update_buffer_produce(sink, cd->sink_period_bytes);
- comp_update_buffer_consume(source, cd->source_period_bytes);
+ comp_update_buffer_produce(sink, copy_sink_bytes);
+ comp_update_buffer_consume(source, copy_src_bytes);
- return dev->frames;
+ return copy_frames;
}
/*
diff --git a/src/include/reef/audio/buffer.h b/src/include/reef/audio/buffer.h
index d1d0869..45aa3ce 100644
--- a/src/include/reef/audio/buffer.h
+++ b/src/include/reef/audio/buffer.h
@@ -164,6 +164,25 @@ static inline uint32_t comp_buffer_get_copy_bytes(struct comp_dev *dev,
return copy_bytes;
}
+/* get the max number of frames that can be copied between sink and source */
+static inline uint32_t comp_buffer_get_copy_frames
+ (struct comp_buffer *source, uint32_t source_frame_bytes,
+ struct comp_buffer *sink, uint32_t sink_frame_bytes)
+{
+ uint32_t copy_frames, src_avail_frames, sink_free_frames;
+
+ src_avail_frames = source->avail / source_frame_bytes;
+ sink_free_frames = sink->free / sink_frame_bytes;
+
+ /* Check that source has enough frames available and sink
+ * has enough free frames.
+ */
+ copy_frames = src_avail_frames > sink_free_frames ?
+ sink_free_frames : src_avail_frames;
+
+ return copy_frames;
+}
+
static inline void buffer_reset_pos(struct comp_buffer *buffer)
{
buffer->r_ptr = buffer->addr;
--
2.11.0
More information about the Sound-open-firmware
mailing list