mirror of https://github.com/thesofproject/sof.git
volume: add 16bit<==>24bit volume copy function and mapping
add 16bit<==>24bit volume copy function and mapping, for 24 bits ssp output/input. here also optimize all other volume copy functions. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
This commit is contained in:
parent
6ac88d96a4
commit
71a85c764d
|
@ -75,6 +75,7 @@ struct comp_data {
|
||||||
struct comp_func_map {
|
struct comp_func_map {
|
||||||
uint16_t source; /* source format */
|
uint16_t source; /* source format */
|
||||||
uint16_t sink; /* sink format */
|
uint16_t sink; /* sink format */
|
||||||
|
uint16_t channels; /* channel number for the stream */
|
||||||
void (*func)(struct comp_dev *dev, struct comp_buffer *sink,
|
void (*func)(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
struct comp_buffer *source, uint32_t frames);
|
struct comp_buffer *source, uint32_t frames);
|
||||||
};
|
};
|
||||||
|
@ -85,21 +86,16 @@ static void vol_s16_to_s32(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
{
|
{
|
||||||
struct comp_data *cd = comp_get_drvdata(dev);
|
struct comp_data *cd = comp_get_drvdata(dev);
|
||||||
int16_t *src = (int16_t*) source->r_ptr;
|
int16_t *src = (int16_t*) source->r_ptr;
|
||||||
int32_t *dest = (int32_t*) sink->w_ptr;
|
int32_t i, *dest = (int32_t*) sink->w_ptr;
|
||||||
int i, j;
|
|
||||||
|
|
||||||
/* buffer sizes are always divisible by period frames */
|
/* buffer sizes are always divisible by period frames */
|
||||||
for (i = 0; i < frames; i++) {
|
for (i = 0; i < frames * 2; i += 2) {
|
||||||
for (j = 0; j < source->params.channels; j++) {
|
dest[i] = (int32_t)src[i] * cd->volume[0];
|
||||||
int32_t val = (int32_t)*src;
|
dest[i + 1] = (int32_t)src[i] * cd->volume[1];
|
||||||
*dest = (val * cd->volume[j]) >> 16;
|
|
||||||
dest++;
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source->r_ptr = src;
|
source->r_ptr = src + i;
|
||||||
sink->w_ptr = dest;
|
sink->w_ptr = dest + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy and scale volume from 32 bit source buffer to 16 bit dest buffer */
|
/* copy and scale volume from 32 bit source buffer to 16 bit dest buffer */
|
||||||
|
@ -107,22 +103,17 @@ static void vol_s32_to_s16(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
struct comp_buffer *source, uint32_t frames)
|
struct comp_buffer *source, uint32_t frames)
|
||||||
{
|
{
|
||||||
struct comp_data *cd = comp_get_drvdata(dev);
|
struct comp_data *cd = comp_get_drvdata(dev);
|
||||||
int32_t *src = (int32_t*) source->r_ptr;
|
int32_t i, *src = (int32_t*) source->r_ptr;
|
||||||
int16_t *dest = (int16_t*) sink->w_ptr;
|
int16_t *dest = (int16_t*) sink->w_ptr;
|
||||||
int i, j;
|
|
||||||
|
|
||||||
/* buffer sizes are always divisible by period frames */
|
/* buffer sizes are always divisible by period frames */
|
||||||
for (i = 0; i < frames; i++) {
|
for (i = 0; i < frames * 2; i += 2) {
|
||||||
for (j = 0; j < source->params.channels; j++) {
|
dest[i] = (((int32_t)src[i] >> 16) * cd->volume[0]) >> 16;
|
||||||
/* TODO: clamp when converting to int16_t */
|
dest[i + 1] = (((int32_t)src[i + 1] >> 16) * cd->volume[1]) >> 16;
|
||||||
*dest = (int16_t)((*src * cd->volume[j]) >> 16);
|
|
||||||
dest++;
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source->r_ptr = src;
|
source->r_ptr = src + i;
|
||||||
sink->w_ptr = dest;
|
sink->w_ptr = dest + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy and scale volume from 32 bit source buffer to 32 bit dest buffer */
|
/* copy and scale volume from 32 bit source buffer to 32 bit dest buffer */
|
||||||
|
@ -131,20 +122,16 @@ static void vol_s32_to_s32(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
{
|
{
|
||||||
struct comp_data *cd = comp_get_drvdata(dev);
|
struct comp_data *cd = comp_get_drvdata(dev);
|
||||||
int32_t *src = (int32_t*) source->r_ptr;
|
int32_t *src = (int32_t*) source->r_ptr;
|
||||||
int32_t *dest = (int32_t*) sink->w_ptr;
|
int32_t i, *dest = (int32_t*) sink->w_ptr;
|
||||||
int i, j;
|
|
||||||
|
|
||||||
/* buffer sizes are always divisible by period frames */
|
/* buffer sizes are always divisible by period frames */
|
||||||
for (i = 0; i < frames; i++) {
|
for (i = 0; i < frames * 2; i += 2) {
|
||||||
for (j = 0; j < source->params.channels; j++) {
|
dest[i] = ((int64_t)src[i] * cd->volume[0]) >> 16;
|
||||||
*dest = (*src * cd->volume[j]) >> 16;
|
dest[i + 1] = ((int64_t)src[i] * cd->volume[1]) >> 16;
|
||||||
dest++;
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source->r_ptr = src;
|
source->r_ptr = src + i;
|
||||||
sink->w_ptr = dest;
|
sink->w_ptr = dest + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy and scale volume from 16 bit source buffer to 16 bit dest buffer */
|
/* copy and scale volume from 16 bit source buffer to 16 bit dest buffer */
|
||||||
|
@ -154,30 +141,64 @@ static void vol_s16_to_s16(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
struct comp_data *cd = comp_get_drvdata(dev);
|
struct comp_data *cd = comp_get_drvdata(dev);
|
||||||
int16_t *src = (int16_t*) source->r_ptr;
|
int16_t *src = (int16_t*) source->r_ptr;
|
||||||
int16_t *dest = (int16_t*) sink->w_ptr;
|
int16_t *dest = (int16_t*) sink->w_ptr;
|
||||||
int i, j;
|
int32_t i;
|
||||||
|
|
||||||
/* buffer sizes are always divisible by period frames */
|
/* buffer sizes are always divisible by period frames */
|
||||||
for (i = 0; i < frames; i++) {
|
for (i = 0; i < frames * 2; i += 2) {
|
||||||
for (j = 0; j < source->params.channels; j++) {
|
dest[i] = ((int32_t)src[i] * cd->volume[0]) >> 16;
|
||||||
int32_t val = (int32_t)*src;
|
dest[i + 1] = ((int32_t)src[i + 1] * cd->volume[1]) >> 16;
|
||||||
/* TODO: clamp when converting to int16_t */
|
|
||||||
*dest = (int16_t)((val * cd->volume[j]) >> 16);
|
|
||||||
|
|
||||||
dest++;
|
|
||||||
src++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source->r_ptr = src;
|
source->r_ptr = src + i;
|
||||||
sink->w_ptr = dest;
|
sink->w_ptr = dest + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy and scale volume from 16 bit source buffer to 24 bit on 32 bit boundary dest buffer */
|
||||||
|
static void vol_s16_to_s24(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
|
struct comp_buffer *source, uint32_t frames)
|
||||||
|
{
|
||||||
|
struct comp_data *cd = comp_get_drvdata(dev);
|
||||||
|
int16_t *src = (int16_t*) source->r_ptr;
|
||||||
|
int32_t i, *dest = (int32_t*) sink->w_ptr;
|
||||||
|
|
||||||
|
/* buffer sizes are always divisible by period frames */
|
||||||
|
for (i = 0; i < frames * 2; i += 2) {
|
||||||
|
dest[i] = ((int32_t)src[i] * cd->volume[0]) >> 8;
|
||||||
|
dest[i + 1] = ((int32_t)src[i + 1] * cd->volume[0]) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
source->r_ptr = src + i;
|
||||||
|
sink->w_ptr = dest + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy and scale volume from 16 bit source buffer to 24 bit on 32 bit boundary dest buffer */
|
||||||
|
static void vol_s24_to_s16(struct comp_dev *dev, struct comp_buffer *sink,
|
||||||
|
struct comp_buffer *source, uint32_t frames)
|
||||||
|
{
|
||||||
|
struct comp_data *cd = comp_get_drvdata(dev);
|
||||||
|
int32_t i, *src = (int32_t*) source->r_ptr;
|
||||||
|
int16_t *dest = (int16_t*) sink->w_ptr;
|
||||||
|
|
||||||
|
/* buffer sizes are always divisible by period frames */
|
||||||
|
for (i = 0; i < frames * 2; i += 2) {
|
||||||
|
dest[i] = (int16_t)((((int32_t)src[i] >> 8) *
|
||||||
|
cd->volume[0]) >> 16);
|
||||||
|
dest[i + 1] = (int16_t)((((int32_t)src[i + 1] >> 8) *
|
||||||
|
cd->volume[0]) >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
source->r_ptr = src + i;
|
||||||
|
sink->w_ptr = dest + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* map of source and sink buffer formats to volume function */
|
/* map of source and sink buffer formats to volume function */
|
||||||
static const struct comp_func_map func_map[] = {
|
static const struct comp_func_map func_map[] = {
|
||||||
{STREAM_FORMAT_S16_LE, STREAM_FORMAT_S16_LE, vol_s16_to_s16},
|
{STREAM_FORMAT_S16_LE, STREAM_FORMAT_S16_LE, 2, vol_s16_to_s16},
|
||||||
{STREAM_FORMAT_S16_LE, STREAM_FORMAT_S32_LE, vol_s16_to_s32},
|
{STREAM_FORMAT_S16_LE, STREAM_FORMAT_S32_LE, 2, vol_s16_to_s32},
|
||||||
{STREAM_FORMAT_S32_LE, STREAM_FORMAT_S16_LE, vol_s32_to_s16},
|
{STREAM_FORMAT_S32_LE, STREAM_FORMAT_S16_LE, 2, vol_s32_to_s16},
|
||||||
{STREAM_FORMAT_S32_LE, STREAM_FORMAT_S32_LE, vol_s32_to_s32},
|
{STREAM_FORMAT_S32_LE, STREAM_FORMAT_S32_LE, 2, vol_s32_to_s32},
|
||||||
|
{STREAM_FORMAT_S16_LE, STREAM_FORMAT_S24_3LE, 2, vol_s16_to_s24},
|
||||||
|
{STREAM_FORMAT_S24_3LE, STREAM_FORMAT_S16_LE, 2, vol_s24_to_s16},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void vol_update(struct comp_data *cd, uint32_t chan)
|
static void vol_update(struct comp_data *cd, uint32_t chan)
|
||||||
|
@ -421,6 +442,8 @@ static int volume_prepare(struct comp_dev *dev)
|
||||||
continue;
|
continue;
|
||||||
if (sink->params.pcm.format != func_map[i].sink)
|
if (sink->params.pcm.format != func_map[i].sink)
|
||||||
continue;
|
continue;
|
||||||
|
if (sink->params.channels != func_map[i].channels)
|
||||||
|
continue;
|
||||||
|
|
||||||
cd->scale_vol = func_map[i].func;
|
cd->scale_vol = func_map[i].func;
|
||||||
goto found;
|
goto found;
|
||||||
|
|
Loading…
Reference in New Issue