blob: 67c163216b1fb1c0b086117e580eef4ed4f76abd [file] [log] [blame]
/*
* Copyright (c) 2016, 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@linux.intel.com>
* Liam Girdwood <liam.r.girdwood@linux.intel.com>
* Keyon Jie <yang.jie@linux.intel.com>
*/
#ifndef AUDIO_FORMAT_H
#define AUDIO_FORMAT_H
/* Maximum and minimum values for 24 bit */
#define INT24_MAXVALUE 8388607
#define INT24_MINVALUE -8388608
/* Collection of common fractional numbers */
#define ONE_Q2_30 1073741824 /* Q2.30 1.0 */
#define ONE_Q1_31 2147483647 /* Q1.31 ~1.0 */
#define MINUS_3DB_Q1_31 1520301996 /* 10^(-3/20) */
#define MINUS_6DB_Q1_31 1076291389 /* 10^(-6/20) */
#define MINUS_10DB_Q1_31 679093957 /* 10^(-10/20) */
#define MINUS_20DB_Q1_31 214748365 /* 10^(-20/20) */
#define MINUS_30DB_Q1_31 67909396 /* 10^(-30/20) */
#define MINUS_40DB_Q1_31 21474836 /* 10^(-40/20) */
#define MINUS_50DB_Q1_31 6790940 /* 10^(-50/20) */
#define MINUS_60DB_Q1_31 2147484 /* 10^(-60/20) */
#define MINUS_70DB_Q1_31 679094 /* 10^(-70/20) */
#define MINUS_80DB_Q1_31 214748 /* 10^(-80/20) */
#define MINUS_90DB_Q1_31 67909 /* 10^(-90/20) */
/* Align the number to the nearest alignment value */
#define ALIGN_UP(size, alignment) \
(((size) % (alignment) == 0) ? (size) : \
((size) - ((size) % (alignment)) + (alignment)))
#define ALIGN_DOWN(size, alignment) \
((size) - ((size) % (alignment)))
/* Compute the number of shifts
* This will result in a compiler overflow error if shift bits are out of
* range as INT64_MAX/MIN is greater than 32 bit Q shift parameter
*/
#define Q_SHIFT_BITS_64(qx, qy, qz) \
((qx + qy - qz) <= 63 ? (((qx + qy - qz) >= 0) ? \
(qx + qy - qz) : INT64_MIN) : INT64_MAX)
#define Q_SHIFT_BITS_32(qx, qy, qz) \
((qx + qy - qz) <= 31 ? (((qx + qy - qz) >= 0) ? \
(qx + qy - qz) : INT32_MIN) : INT32_MAX)
/* Convert a float number to fractional Qnx.ny format. Note that there is no
* check for nx+ny number of bits to fit the word length of int.
*/
#define Q_CONVERT_FLOAT(f, qy) ((int)((f) * (1 << qy) + 0.5)) /* f is float */
/* Convert fractional Qnx.ny number x to float */
#define Q_CONVERT_QTOF(x, ny) ((float)(x) / ((int64_t)1 << (ny)))
/* A more clever macro for Q-shifts */
#define Q_SHIFT(x, src_q, dst_q) ((x)>>((src_q)-(dst_q)))
#define Q_SHIFT_RND(x, src_q, dst_q) ((((x) >> ((src_q)-(dst_q) -1)) +1) >> 1)
/* Alternative version since compiler does not allow (x >> -1) */
#define Q_SHIFT_LEFT(x, src_q, dst_q) ((x)<<((dst_q)-(src_q)))
/* Fractional multiplication with shift
* Note that the parameters px and py must be cast to (int64_t) if other type.
*/
#define Q_MULTS_32X32(px, py, qx, qy, qp) ((px) * (py) >> (((qx)+(qy)-(qp))))
/* Fractional multiplication with shift and round
* Note that the parameters px and py must be cast to (int64_t) if other type.
*/
#define Q_MULTSR_32X32(px, py, qx, qy, qp) \
((((px) * (py) >> ((qx)+(qy)-(qp)-1)) + 1) >> 1)
/* Saturation */
#define SATP_INT32(x) (((x) > INT32_MAX) ? INT32_MAX : (x))
#define SATM_INT32(x) (((x) < INT32_MIN) ? INT32_MIN : (x))
static inline int64_t q_mults_32x32(int32_t x, int32_t y, const int shift_bits)
{
return ((int64_t)x * y) >> shift_bits;
}
static inline int64_t q_multsr_32x32(int32_t x, int32_t y, const int shift_bits)
{
return ((((int64_t)x * y) >> (shift_bits - 1)) + 1) >> 1;
}
static inline int32_t q_mults_16x16(int16_t x, int32_t y, const int shift_bits)
{
return ((int32_t)x * y) >> shift_bits;
}
static inline int16_t q_multsr_16x16(int16_t x, int32_t y, const int shift_bits)
{
return ((((int32_t)x * y) >> (shift_bits - 1)) + 1) >> 1;
}
/* Saturation inline functions */
static inline int32_t sat_int32(int64_t x)
{
#if 1
/* TODO: Is this faster */
if (x > INT32_MAX)
return INT32_MAX;
else if (x < INT32_MIN)
return INT32_MIN;
else
return (int32_t)x;
#else
/* Or this */
int64_t y;
y = SATP_INT32(x);
return (int32_t)SATM_INT32(y);
#endif
}
static inline int32_t sat_int24(int32_t x)
{
if (x > INT24_MAXVALUE)
return INT24_MAXVALUE;
else if (x < INT24_MINVALUE)
return INT24_MINVALUE;
else
return x;
}
static inline int16_t sat_int16(int32_t x)
{
if (x > INT16_MAX)
return INT16_MAX;
else if (x < INT16_MIN)
return INT16_MIN;
else
return (int16_t)x;
}
/* Fractional multiplication with shift and saturation */
static inline int32_t q_multsr_sat_32x32(int32_t x, int32_t y,
const int shift_bits)
{
return sat_int32(((((int64_t)x * y) >> (shift_bits - 1)) + 1) >> 1);
}
static inline int16_t q_multsr_sat_16x16(int16_t x, int32_t y,
const int shift_bits)
{
return sat_int16(((((int32_t)x * y) >> (shift_bits - 1)) + 1) >> 1);
}
static inline int32_t sign_extend_s24(int32_t x)
{
return (x << 8) >> 8;
}
#endif