blob: 01172d74c5ad2892c1263489563ee40a440014bd [file] [log] [blame]
/*
* 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: Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
* Tomasz Lauda <tomasz.lauda@linux.intel.com>
*/
/**
* \file audio/volume_generic.c
* \brief Volume generic processing implementation
* \authors Liam Girdwood <liam.r.girdwood@linux.intel.com>\n
* Keyon Jie <yang.jie@linux.intel.com>\n
* Tomasz Lauda <tomasz.lauda@linux.intel.com>
*/
#include "volume.h"
#ifdef CONFIG_GENERIC
/**
* \brief Volume processing from 16 bit to 32 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 16 bit source buffer
* to 32 bit destination buffer for 2 channels.
*/
static void vol_s16_to_s32_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = (int32_t)src[i] * cd->volume[0];
dest[i + 1] = (int32_t)src[i + 1] * cd->volume[1];
}
}
/**
* \brief Volume processing from 32 bit to 16 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 32 bit source buffer
* to 16 bit destination buffer for 2 channels.
*/
static void vol_s32_to_s16_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = (int16_t)q_multsr_sat_32x32(
src[i], cd->volume[0], Q_SHIFT_BITS_64(31, 16, 15));
dest[i + 1] = (int16_t)q_multsr_sat_32x32(
src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(31, 16, 15));
}
}
/**
* \brief Volume processing from 32 bit to 32 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 32 bit source buffer
* to 32 bit destination buffer for 2 channels.
*/
static void vol_s32_to_s32_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = q_multsr_sat_32x32(
src[i], cd->volume[0], Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 1] = q_multsr_sat_32x32(
src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(31, 16, 31));
}
}
/**
* \brief Volume processing from 16 bit to 16 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 16 bit source buffer
* to 16 bit destination buffer for 2 channels.
*/
static void vol_s16_to_s16_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = q_multsr_sat_16x16(
src[i], cd->volume[0], Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 1] = q_multsr_sat_16x16(
src[i + 1], cd->volume[1], Q_SHIFT_BITS_32(15, 16, 15));
}
}
/**
* \brief Volume processing from 16 bit to 24/32 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 16 bit source buffer
* to 24/32 bit destination buffer for 2 channels.
*/
static void vol_s16_to_s24_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = q_multsr_sat_32x32(
src[i], cd->volume[0], Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(
src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(15, 16, 23));
}
}
/**
* \brief Volume processing from 24/32 bit to 16 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 24/32 bit source buffer
* to 16 bit destination buffer for 2 channels.
*/
static void vol_s24_to_s16_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = (int16_t)q_multsr_sat_32x32(
sign_extend_s24(src[i]), cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 15));
dest[i + 1] = (int16_t)q_multsr_sat_32x32(
sign_extend_s24(src[i + 1]), cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 15));
}
}
/**
* \brief Volume processing from 32 bit to 24/32 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 32 bit source buffer
* to 24/32 bit destination buffer for 2 channels.
*/
static void vol_s32_to_s24_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = q_multsr_sat_32x32(
src[i], cd->volume[0], Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(
src[i + 1], cd->volume[1], Q_SHIFT_BITS_64(31, 16, 23));
}
}
/**
* \brief Volume processing from 24/32 bit to 32 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 24/32 bit source buffer
* to 32 bit destination buffer for 2 channels.
*/
static void vol_s24_to_s32_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = q_multsr_sat_32x32(
sign_extend_s24(src[i]), cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 1] = q_multsr_sat_32x32(
sign_extend_s24(src[i + 1]), cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 31));
}
}
/**
* \brief Volume processing from 24/32 bit to 24/32 bit in 2 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 24/32 bit source buffer
* to 24/32 bit destination buffer for 2 channels.
*/
static void vol_s24_to_s24_2ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t i, *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < dev->frames * 2; i += 2) {
dest[i] = q_multsr_sat_32x32(
sign_extend_s24(src[i]), cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(
sign_extend_s24(src[i + 1]), cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 23));
}
}
#if PLATFORM_MAX_CHANNELS >= 4
/**
* \brief Volume processing from 16 bit to 32 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 16 bit source buffer
* to 32 bit destination buffer for 4 channels.
*/
static void vol_s16_to_s32_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = (int32_t)src[i] * cd->volume[0];
dest[i + 1] = (int32_t)src[i + 1] * cd->volume[1];
dest[i + 2] = (int32_t)src[i + 2] * cd->volume[2];
dest[i + 3] = (int32_t)src[i + 3] * cd->volume[3];
}
}
/**
* \brief Volume processing from 32 bit to 16 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 32 bit source buffer
* to 16 bit destination buffer for 4 channels.
*/
static void vol_s32_to_s16_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = (int16_t)q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(31, 16,
15));
dest[i + 1] = (int16_t)q_multsr_sat_32x32(src[i + 1],
cd->volume[1],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 2] = (int16_t)q_multsr_sat_32x32(src[i + 2],
cd->volume[2],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 3] = (int16_t)q_multsr_sat_32x32(src[i + 3],
cd->volume[3],
Q_SHIFT_BITS_64(31,
16,
15));
}
}
/**
* \brief Volume processing from 32 bit to 32 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 32 bit source buffer
* to 32 bit destination buffer for 4 channels.
*/
static void vol_s32_to_s32_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 1] = q_multsr_sat_32x32(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 2] = q_multsr_sat_32x32(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 3] = q_multsr_sat_32x32(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_64(31, 16, 31));
}
}
/**
* \brief Volume processing from 16 bit to 16 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 16 bit source buffer
* to 16 bit destination buffer for 4 channels.
*/
static void vol_s16_to_s16_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = q_multsr_sat_16x16(src[i], cd->volume[0],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 1] = q_multsr_sat_16x16(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 2] = q_multsr_sat_16x16(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 3] = q_multsr_sat_16x16(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_32(15, 16, 15));
}
}
/**
* \brief Volume processing from 16 bit to 24/32 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 16 bit source buffer
* to 24/32 bit destination buffer for 4 channels.
*/
static void vol_s16_to_s24_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 2] = q_multsr_sat_32x32(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 3] = q_multsr_sat_32x32(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_64(15, 16, 23));
}
}
/**
* \brief Volume processing from 24/32 bit to 16 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 24/32 bit source buffer
* to 16 bit destination buffer for 4 channels.
*/
static void vol_s24_to_s16_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i, sample;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
sample = sign_extend_s24(src[i]);
dest[i] = (int16_t)q_multsr_sat_32x32(sample, cd->volume[0],
Q_SHIFT_BITS_64(23, 16,
15));
sample = sign_extend_s24(src[i + 1]);
dest[i + 1] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[1],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 2]);
dest[i + 2] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[2],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 3]);
dest[i + 3] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[3],
Q_SHIFT_BITS_64(23,
16,
15));
}
}
/**
* \brief Volume processing from 32 bit to 24/32 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 32 bit source buffer
* to 24/32 bit destination buffer for 4 channels.
*/
static void vol_s32_to_s24_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 2] = q_multsr_sat_32x32(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 3] = q_multsr_sat_32x32(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_64(31, 16, 23));
}
}
/**
* \brief Volume processing from 24/32 bit to 32 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 24/32 bit source buffer
* to 32 bit destination buffer for 4 channels.
*/
static void vol_s24_to_s32_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = q_multsr_sat_32x32(sign_extend_s24(src[i]),
cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 1] = q_multsr_sat_32x32(sign_extend_s24(src[i + 1]),
cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 2] = q_multsr_sat_32x32(sign_extend_s24(src[i + 2]),
cd->volume[2],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 3] = q_multsr_sat_32x32(sign_extend_s24(src[i + 3]),
cd->volume[3],
Q_SHIFT_BITS_64(23, 16, 31));
}
}
/**
* \brief Volume processing from 24/32 bit to 24/32 bit in 4 channels.
* \param[in,out] dev Volume base component device.
* \param[in,out] sink Destination buffer.
* \param[in,out] source Source buffer.
*
* Copy and scale volume from 24/32 bit source buffer
* to 24/32 bit destination buffer for 4 channels.
*/
static void vol_s24_to_s24_4ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t i, *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < dev->frames * 4; i += 4) {
dest[i] = q_multsr_sat_32x32(sign_extend_s24(src[i]),
cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(sign_extend_s24(src[i + 1]),
cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 2] = q_multsr_sat_32x32(sign_extend_s24(src[i + 2]),
cd->volume[2],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 3] = q_multsr_sat_32x32(sign_extend_s24(src[i + 3]),
cd->volume[3],
Q_SHIFT_BITS_64(23, 16, 23));
}
}
#endif
#if PLATFORM_MAX_CHANNELS >= 8
/* volume scaling functions for 8-channel input */
/* copy and scale volume from 16 bit source buffer to 32 bit dest buffer */
static void vol_s16_to_s32_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = (int32_t)src[i] * cd->volume[0];
dest[i + 1] = (int32_t)src[i + 1] * cd->volume[1];
dest[i + 2] = (int32_t)src[i + 2] * cd->volume[2];
dest[i + 3] = (int32_t)src[i + 3] * cd->volume[3];
dest[i + 4] = (int32_t)src[i + 4] * cd->volume[4];
dest[i + 5] = (int32_t)src[i + 5] * cd->volume[5];
dest[i + 6] = (int32_t)src[i + 6] * cd->volume[6];
dest[i + 7] = (int32_t)src[i + 7] * cd->volume[7];
}
}
/* copy and scale volume from 32 bit source buffer to 16 bit dest buffer */
static void vol_s32_to_s16_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = (int16_t)q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(31, 16,
15));
dest[i + 1] = (int16_t)q_multsr_sat_32x32(src[i + 1],
cd->volume[1],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 2] = (int16_t)q_multsr_sat_32x32(src[i + 2],
cd->volume[2],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 3] = (int16_t)q_multsr_sat_32x32(src[i + 3],
cd->volume[3],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 4] = (int16_t)q_multsr_sat_32x32(src[i + 4],
cd->volume[4],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 5] = (int16_t)q_multsr_sat_32x32(src[i + 5],
cd->volume[5],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 6] = (int16_t)q_multsr_sat_32x32(src[i + 6],
cd->volume[6],
Q_SHIFT_BITS_64(31,
16,
15));
dest[i + 7] = (int16_t)q_multsr_sat_32x32(src[i + 7],
cd->volume[7],
Q_SHIFT_BITS_64(31,
16,
15));
}
}
/* copy and scale volume from 32 bit source buffer to 32 bit dest buffer */
static void vol_s32_to_s32_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 1] = q_multsr_sat_32x32(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 2] = q_multsr_sat_32x32(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 3] = q_multsr_sat_32x32(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 4] = q_multsr_sat_32x32(src[i + 4], cd->volume[4],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 5] = q_multsr_sat_32x32(src[i + 5], cd->volume[5],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 6] = q_multsr_sat_32x32(src[i + 6], cd->volume[6],
Q_SHIFT_BITS_64(31, 16, 31));
dest[i + 7] = q_multsr_sat_32x32(src[i + 7], cd->volume[7],
Q_SHIFT_BITS_64(31, 16, 31));
}
}
/* copy and scale volume from 16 bit source buffer to 16 bit dest buffer */
static void vol_s16_to_s16_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = q_multsr_sat_16x16(src[i], cd->volume[0],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 1] = q_multsr_sat_16x16(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 2] = q_multsr_sat_16x16(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 3] = q_multsr_sat_16x16(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 4] = q_multsr_sat_16x16(src[i + 4], cd->volume[4],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 5] = q_multsr_sat_16x16(src[i + 5], cd->volume[5],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 6] = q_multsr_sat_16x16(src[i + 6], cd->volume[6],
Q_SHIFT_BITS_32(15, 16, 15));
dest[i + 7] = q_multsr_sat_16x16(src[i + 7], cd->volume[7],
Q_SHIFT_BITS_32(15, 16, 15));
}
}
/* copy and scale volume from 16 bit source buffer to 24 bit
* on 32 bit boundary buffer
*/
static void vol_s16_to_s24_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int16_t *src = (int16_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 2] = q_multsr_sat_32x32(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 3] = q_multsr_sat_32x32(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 4] = q_multsr_sat_32x32(src[i + 4], cd->volume[4],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 5] = q_multsr_sat_32x32(src[i + 5], cd->volume[5],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 6] = q_multsr_sat_32x32(src[i + 6], cd->volume[6],
Q_SHIFT_BITS_64(15, 16, 23));
dest[i + 7] = q_multsr_sat_32x32(src[i + 7], cd->volume[7],
Q_SHIFT_BITS_64(15, 16, 23));
}
}
/* copy and scale volume from 16 bit source buffer to 24 bit
* on 32 bit boundary dest buffer
*/
static void vol_s24_to_s16_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int16_t *dest = (int16_t *)sink->w_ptr;
int32_t i, sample;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.15 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
sample = sign_extend_s24(src[i]);
dest[i] = (int16_t)q_multsr_sat_32x32(sample, cd->volume[0],
Q_SHIFT_BITS_64(23, 16,
15));
sample = sign_extend_s24(src[i + 1]);
dest[i + 1] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[1],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 2]);
dest[i + 2] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[2],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 3]);
dest[i + 3] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[3],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 4]);
dest[i + 4] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[4],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 5]);
dest[i + 5] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[5],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 6]);
dest[i + 6] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[6],
Q_SHIFT_BITS_64(23,
16,
15));
sample = sign_extend_s24(src[i + 7]);
dest[i + 7] = (int16_t)q_multsr_sat_32x32(sample,
cd->volume[7],
Q_SHIFT_BITS_64(23,
16,
15));
}
}
/* copy and scale volume from 32 bit source buffer to 24 bit
* on 32 bit boundary dest buffer
*/
static void vol_s32_to_s24_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.31 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = q_multsr_sat_32x32(src[i], cd->volume[0],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(src[i + 1], cd->volume[1],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 2] = q_multsr_sat_32x32(src[i + 2], cd->volume[2],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 3] = q_multsr_sat_32x32(src[i + 3], cd->volume[3],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 4] = q_multsr_sat_32x32(src[i + 4], cd->volume[4],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 5] = q_multsr_sat_32x32(src[i + 5], cd->volume[5],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 6] = q_multsr_sat_32x32(src[i + 6], cd->volume[6],
Q_SHIFT_BITS_64(31, 16, 23));
dest[i + 7] = q_multsr_sat_32x32(src[i + 7], cd->volume[7],
Q_SHIFT_BITS_64(31, 16, 23));
}
}
/* copy and scale volume from 16 bit source buffer to 24 bit
* on 32 bit boundary dest buffer
*/
static void vol_s24_to_s32_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
int32_t i;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.31 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = q_multsr_sat_32x32(sign_extend_s24(src[i]),
cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 1] = q_multsr_sat_32x32(sign_extend_s24(src[i + 1]),
cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 2] = q_multsr_sat_32x32(sign_extend_s24(src[i + 2]),
cd->volume[2],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 3] = q_multsr_sat_32x32(sign_extend_s24(src[i + 3]),
cd->volume[3],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 4] = q_multsr_sat_32x32(sign_extend_s24(src[i + 4]),
cd->volume[4],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 5] = q_multsr_sat_32x32(sign_extend_s24(src[i + 5]),
cd->volume[5],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 6] = q_multsr_sat_32x32(sign_extend_s24(src[i + 6]),
cd->volume[6],
Q_SHIFT_BITS_64(23, 16, 31));
dest[i + 7] = q_multsr_sat_32x32(sign_extend_s24(src[i + 7]),
cd->volume[7],
Q_SHIFT_BITS_64(23, 16, 31));
}
}
/* Copy and scale volume from 24 bit source buffer to 24 bit on 32 bit boundary
* dest buffer.
*/
static void vol_s24_to_s24_8ch(struct comp_dev *dev, struct comp_buffer *sink,
struct comp_buffer *source)
{
struct comp_data *cd = comp_get_drvdata(dev);
int32_t i, *src = (int32_t *)source->r_ptr;
int32_t *dest = (int32_t *)sink->w_ptr;
/* buffer sizes are always divisible by period frames */
/* Samples are Q1.23 --> Q1.23 and volume is Q1.16 */
for (i = 0; i < dev->frames * 8; i += 8) {
dest[i] = q_multsr_sat_32x32(sign_extend_s24(src[i]),
cd->volume[0],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 1] = q_multsr_sat_32x32(sign_extend_s24(src[i + 1]),
cd->volume[1],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 2] = q_multsr_sat_32x32(sign_extend_s24(src[i + 2]),
cd->volume[2],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 3] = q_multsr_sat_32x32(sign_extend_s24(src[i + 3]),
cd->volume[3],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 4] = q_multsr_sat_32x32(sign_extend_s24(src[i + 4]),
cd->volume[4],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 5] = q_multsr_sat_32x32(sign_extend_s24(src[i + 5]),
cd->volume[5],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 6] = q_multsr_sat_32x32(sign_extend_s24(src[i + 6]),
cd->volume[6],
Q_SHIFT_BITS_64(23, 16, 23));
dest[i + 7] = q_multsr_sat_32x32(sign_extend_s24(src[i + 7]),
cd->volume[7],
Q_SHIFT_BITS_64(23, 16, 23));
}
}
#endif
const struct comp_func_map func_map[] = {
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, 2, vol_s16_to_s16_2ch},
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, 2, vol_s16_to_s32_2ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, 2, vol_s32_to_s16_2ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, 2, vol_s32_to_s32_2ch},
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, 2, vol_s16_to_s24_2ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, 2, vol_s24_to_s16_2ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, 2, vol_s32_to_s24_2ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, 2, vol_s24_to_s32_2ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, 2, vol_s24_to_s24_2ch},
#if PLATFORM_MAX_CHANNELS >= 4
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, 4, vol_s16_to_s16_4ch},
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, 4, vol_s16_to_s32_4ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, 4, vol_s32_to_s16_4ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, 4, vol_s32_to_s32_4ch},
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, 4, vol_s16_to_s24_4ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, 4, vol_s24_to_s16_4ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, 4, vol_s32_to_s24_4ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, 4, vol_s24_to_s32_4ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, 4, vol_s24_to_s24_4ch},
#endif
#if PLATFORM_MAX_CHANNELS >= 8
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, 8, vol_s16_to_s16_8ch},
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, 8, vol_s16_to_s32_8ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S16_LE, 8, vol_s32_to_s16_8ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, 8, vol_s32_to_s32_8ch},
{SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S24_4LE, 8, vol_s16_to_s24_8ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, 8, vol_s24_to_s16_8ch},
{SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, 8, vol_s32_to_s24_8ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, 8, vol_s24_to_s32_8ch},
{SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S24_4LE, 8, vol_s24_to_s24_8ch},
#endif
};
scale_vol vol_get_processing_function(struct comp_dev *dev)
{
struct comp_data *cd = comp_get_drvdata(dev);
int i;
/* map the volume function for source and sink buffers */
for (i = 0; i < ARRAY_SIZE(func_map); i++) {
if (cd->source_format != func_map[i].source)
continue;
if (cd->sink_format != func_map[i].sink)
continue;
if (dev->params.channels != func_map[i].channels)
continue;
return func_map[i].func;
}
return NULL;
}
#endif